GenerateContentRequest.swift 3.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. // Copyright 2023 Google LLC
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. import Foundation
  15. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  16. struct GenerateContentRequest: Sendable {
  17. /// Model name.
  18. let model: String
  19. let contents: [ModelContent]
  20. let generationConfig: GenerationConfig?
  21. let safetySettings: [SafetySetting]?
  22. let tools: [Tool]?
  23. let toolConfig: ToolConfig?
  24. let systemInstruction: ModelContent?
  25. let apiConfig: APIConfig
  26. let apiMethod: APIMethod
  27. let options: RequestOptions
  28. }
  29. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  30. extension GenerateContentRequest: Encodable {
  31. enum CodingKeys: String, CodingKey {
  32. case model
  33. case contents
  34. case generationConfig
  35. case safetySettings
  36. case tools
  37. case toolConfig
  38. case systemInstruction
  39. }
  40. func encode(to encoder: any Encoder) throws {
  41. var container = encoder.container(keyedBy: CodingKeys.self)
  42. // The model name only needs to be encoded when this `GenerateContentRequest` instance is used
  43. // in a `CountTokensRequest` (calling `countTokens`). When calling `generateContent` or
  44. // `generateContentStream`, the `model` field is populated in the backend from the `url`.
  45. if apiMethod == .countTokens {
  46. try container.encode(model, forKey: .model)
  47. }
  48. try container.encode(contents, forKey: .contents)
  49. try container.encodeIfPresent(generationConfig, forKey: .generationConfig)
  50. try container.encodeIfPresent(safetySettings, forKey: .safetySettings)
  51. try container.encodeIfPresent(tools, forKey: .tools)
  52. try container.encodeIfPresent(toolConfig, forKey: .toolConfig)
  53. try container.encodeIfPresent(systemInstruction, forKey: .systemInstruction)
  54. }
  55. }
  56. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  57. extension GenerateContentRequest {
  58. enum APIMethod: String {
  59. case generateContent
  60. case streamGenerateContent
  61. case countTokens
  62. }
  63. }
  64. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  65. extension GenerateContentRequest: GenerativeAIRequest {
  66. typealias Response = GenerateContentResponse
  67. var url: URL {
  68. let modelURL = "\(apiConfig.service.endpoint.rawValue)/\(apiConfig.version.rawValue)/\(model)"
  69. switch apiMethod {
  70. case .generateContent:
  71. return URL(string: "\(modelURL):\(apiMethod.rawValue)")!
  72. case .streamGenerateContent:
  73. return URL(string: "\(modelURL):\(apiMethod.rawValue)?alt=sse")!
  74. case .countTokens:
  75. fatalError("\(Self.self) should be a property of \(CountTokensRequest.self).")
  76. }
  77. }
  78. }