mirror of
https://github.com/firebase/firebase-ios-sdk
synced 2026-11-10 22:45:59 +05:45
209 lines
8.9 KiB
Swift
209 lines
8.9 KiB
Swift
// Copyright 2025 Google LLC
|
|
//
|
|
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
// you may not use this file except in compliance with the License.
|
|
// You may obtain a copy of the License at
|
|
//
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
|
//
|
|
// Unless required by applicable law or agreed to in writing, software
|
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
// See the License for the specific language governing permissions and
|
|
// limitations under the License.
|
|
|
|
import Foundation
|
|
|
|
/// **[Public Preview]** A multimodal model (like Gemini) that generates content using
|
|
/// server-managed prompt templates.
|
|
///
|
|
/// > Warning: This API is a public preview and may be subject to change.
|
|
///
|
|
/// When using server prompt templates, prompts, system instructions, tools, and model
|
|
/// configurations are defined and stored server-side in the Firebase console or via the Firebase AI
|
|
/// Logic REST API. Client applications only pass a template identifier and any runtime input
|
|
/// variables required by the template.
|
|
///
|
|
/// Benefits of this approach include:
|
|
/// - Protecting prompts and system instructions from exposure in client code.
|
|
/// - Updating prompts, schemas, and configurations without releasing a new app version.
|
|
///
|
|
/// > Tip: We recommend versioning your template IDs (for example, `my-template-v1-0-0`) and using
|
|
/// [Firebase Remote Config](https://firebase.google.com/docs/ai-logic/server-prompt-templates/versioning-with-remote-config)
|
|
/// to dynamically manage template IDs in client requests.
|
|
///
|
|
/// For more details, see the
|
|
/// [Server Prompt Templates
|
|
/// guide](https://firebase.google.com/docs/ai-logic/server-prompt-templates/get-started).
|
|
public final class TemplateGenerativeModel: Sendable {
|
|
let generativeAIService: GenerativeAIService
|
|
let apiConfig: APIConfig
|
|
|
|
/// A list of tools the model may use to generate the next response.
|
|
let tools: [TemplateTool]?
|
|
|
|
/// Tool configuration for any ``TemplateTool`` specified in the request.
|
|
let toolConfig: TemplateToolConfig?
|
|
|
|
/// Configuration parameters for sending requests to the backend.
|
|
let requestOptions: RequestOptions
|
|
|
|
init(firebaseInfo: FirebaseInfo, apiConfig: APIConfig, tools: [TemplateTool]?,
|
|
toolConfig: TemplateToolConfig?, requestOptions: RequestOptions,
|
|
urlSession: URLSession = GenAIURLSession.default) {
|
|
generativeAIService = GenerativeAIService(
|
|
firebaseInfo: firebaseInfo,
|
|
urlSession: urlSession
|
|
)
|
|
self.apiConfig = apiConfig
|
|
self.tools = tools
|
|
self.toolConfig = toolConfig
|
|
self.requestOptions = requestOptions
|
|
}
|
|
|
|
/// **[Public Preview]** Generates content from a prompt template and inputs.
|
|
///
|
|
/// > Warning: This API is a public preview and may be subject to change.
|
|
///
|
|
/// - Parameters:
|
|
/// - templateID: The ID of the server prompt template to use (for example,
|
|
/// `"my-template-v1-0-0"`).
|
|
/// - inputs: A dictionary of variable names and values to substitute into the template's
|
|
/// Handlebars placeholders (such as `{{variable}}`) or `input.schema`. Supported value types
|
|
/// include `String`, `Int`, `Double`, `Float`, `Bool`, arrays, and nested dictionaries;
|
|
/// defaults to no inputs.
|
|
/// - Returns: The content generated by the model.
|
|
/// - Throws: A ``GenerateContentError`` if the request failed, or an `EncodingError` if `inputs`
|
|
/// cannot be encoded.
|
|
public func generateContent(templateID: String,
|
|
inputs: [String: Any] = [:]) async throws
|
|
-> GenerateContentResponse {
|
|
return try await generateContentWithHistory(
|
|
history: [],
|
|
template: templateID,
|
|
inputs: TemplateInput.inputs(from: inputs)
|
|
)
|
|
}
|
|
|
|
/// **[Public Preview]** Generates content from a prompt template and inputs, with streaming
|
|
/// responses.
|
|
///
|
|
/// > Warning: This API is a public preview and may be subject to change.
|
|
///
|
|
/// - Parameters:
|
|
/// - templateID: The ID of the server prompt template to use (for example,
|
|
/// `"my-template-v1-0-0"`).
|
|
/// - inputs: A dictionary of variable names and values to substitute into the template's
|
|
/// Handlebars placeholders (such as `{{variable}}`) or `input.schema`. Supported value types
|
|
/// include `String`, `Int`, `Double`, `Float`, `Bool`, arrays, and nested dictionaries;
|
|
/// defaults to no inputs.
|
|
/// - Returns: An `AsyncThrowingStream` that yields `GenerateContentResponse` objects.
|
|
/// - Throws: A ``GenerateContentError`` if the request failed, or an `EncodingError` if `inputs`
|
|
/// cannot be encoded.
|
|
@available(macOS 12.0, watchOS 8.0, *)
|
|
public func generateContentStream(templateID: String, inputs: [String: Any] = [:]) throws
|
|
-> AsyncThrowingStream<GenerateContentResponse, Error> {
|
|
return try generateContentStreamWithHistory(
|
|
history: [],
|
|
template: templateID,
|
|
inputs: TemplateInput.inputs(from: inputs)
|
|
)
|
|
}
|
|
|
|
/// **[Public Preview]** Creates a new chat conversation using this model with the provided
|
|
/// template, inputs, and history.
|
|
///
|
|
/// > Warning: This API is a public preview and may be subject to change.
|
|
///
|
|
/// The template's model, system instructions, and configurations apply to every turn
|
|
/// automatically, while the returned ``TemplateChat`` tracks conversation history.
|
|
///
|
|
/// > Important: The referenced server prompt template must include the `{{history}}` tag in its
|
|
/// content, which indicates where the conversation turns managed by the client SDK should be
|
|
/// injected.
|
|
///
|
|
/// For more details, see
|
|
/// [Multi-turn interactions with server prompt templates](https://firebase.google.com/docs/ai-logic/server-prompt-templates/multi-turn-interactions).
|
|
///
|
|
/// - Parameters:
|
|
/// - templateID: The ID of the server prompt template to use.
|
|
/// - inputs: A dictionary of variable names and values to substitute into the template; the
|
|
/// same inputs are sent with every turn of the conversation. Defaults to no inputs.
|
|
/// - history: The previous conversation history to seed the chat session with.
|
|
/// - Returns: A new ``TemplateChat`` instance.
|
|
public func startChat(templateID: String,
|
|
inputs: [String: Any] = [:],
|
|
history: [ModelContent] = []) -> TemplateChat {
|
|
return TemplateChat(
|
|
model: self,
|
|
templateID: templateID,
|
|
inputs: inputs,
|
|
history: history
|
|
)
|
|
}
|
|
|
|
// MARK: - Internal
|
|
|
|
func templateGenerateContentRequest(template: String, inputs: [String: TemplateInput],
|
|
history: [ModelContent],
|
|
stream: Bool) throws -> TemplateGenerateContentRequest {
|
|
try history.throwIfError()
|
|
// Normalize an empty tools array to `nil` so that an empty `"tools"` array is not sent.
|
|
let internalTools = try tools?.map { try $0.toInternal() }
|
|
return TemplateGenerateContentRequest(
|
|
template: template,
|
|
inputs: inputs,
|
|
history: history,
|
|
projectID: generativeAIService.firebaseInfo.projectID,
|
|
stream: stream,
|
|
apiConfig: apiConfig,
|
|
options: requestOptions,
|
|
tools: (internalTools?.isEmpty ?? true) ? nil : internalTools,
|
|
toolConfig: toolConfig
|
|
)
|
|
}
|
|
|
|
/// Generates content from a prompt template, inputs, and history.
|
|
///
|
|
/// - Parameters:
|
|
/// - history: The conversation history to use.
|
|
/// - template: The prompt template to use.
|
|
/// - inputs: The variables to substitute into the template.
|
|
/// - Returns: The content generated by the model.
|
|
/// - Throws: A ``GenerateContentError`` if the request failed.
|
|
func generateContentWithHistory(history: [ModelContent], template: String,
|
|
inputs: [String: TemplateInput]) async throws
|
|
-> GenerateContentResponse {
|
|
let request = try templateGenerateContentRequest(
|
|
template: template,
|
|
inputs: inputs,
|
|
history: history,
|
|
stream: false
|
|
)
|
|
|
|
return try await generativeAIService.loadRequest(request: request)
|
|
}
|
|
|
|
/// Generates a stream of content from a prompt template, inputs, and history.
|
|
///
|
|
/// - Parameters:
|
|
/// - history: The conversation history to use.
|
|
/// - template: The prompt template to use.
|
|
/// - inputs: The variables to substitute into the template.
|
|
/// - Returns: An `AsyncThrowingStream` that yields `GenerateContentResponse` objects.
|
|
/// - Throws: A ``GenerateContentError`` if the request failed.
|
|
@available(macOS 12.0, watchOS 8.0, *)
|
|
func generateContentStreamWithHistory(history: [ModelContent], template: String,
|
|
inputs: [String: TemplateInput]) throws
|
|
-> AsyncThrowingStream<GenerateContentResponse, Error> {
|
|
let request = try templateGenerateContentRequest(
|
|
template: template,
|
|
inputs: inputs,
|
|
history: history,
|
|
stream: true
|
|
)
|
|
|
|
return generativeAIService.loadRequestStream(request: request)
|
|
}
|
|
}
|