GenerateContentRequest.swift 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 apiMethod: APIMethod
  26. let options: RequestOptions
  27. }
  28. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  29. extension GenerateContentRequest: Encodable {
  30. enum CodingKeys: String, CodingKey {
  31. case model
  32. case contents
  33. case generationConfig
  34. case safetySettings
  35. case tools
  36. case toolConfig
  37. case systemInstruction
  38. }
  39. func encode(to encoder: any Encoder) throws {
  40. var container = encoder.container(keyedBy: CodingKeys.self)
  41. // The model name only needs to be encoded when this `GenerateContentRequest` instance is used
  42. // in a `CountTokensRequest` (calling `countTokens`). When calling `generateContent` or
  43. // `generateContentStream`, the `model` field is populated in the backend from the `url`.
  44. if apiMethod == .countTokens {
  45. try container.encode(model, forKey: .model)
  46. }
  47. try container.encode(contents, forKey: .contents)
  48. try container.encodeIfPresent(generationConfig, forKey: .generationConfig)
  49. try container.encodeIfPresent(safetySettings, forKey: .safetySettings)
  50. try container.encodeIfPresent(tools, forKey: .tools)
  51. try container.encodeIfPresent(toolConfig, forKey: .toolConfig)
  52. try container.encodeIfPresent(systemInstruction, forKey: .systemInstruction)
  53. }
  54. }
  55. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  56. extension GenerateContentRequest {
  57. enum APIMethod: String {
  58. case generateContent
  59. case streamGenerateContent
  60. case countTokens
  61. }
  62. }
  63. @available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *)
  64. extension GenerateContentRequest: GenerativeAIRequest {
  65. typealias Response = GenerateContentResponse
  66. func requestURL(apiConfig: APIConfig) -> URL {
  67. let modelURL = "\(apiConfig.service.endpoint.rawValue)/\(apiConfig.version.rawValue)/\(model)"
  68. switch apiMethod {
  69. case .generateContent:
  70. return URL(string: "\(modelURL):\(apiMethod.rawValue)")!
  71. case .streamGenerateContent:
  72. return URL(string: "\(modelURL):\(apiMethod.rawValue)?alt=sse")!
  73. case .countTokens:
  74. fatalError("\(Self.self) should be a property of \(CountTokensRequest.self).")
  75. }
  76. }
  77. }