Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 9 additions & 3 deletions FirebaseVertexAI/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,10 @@
renamed to `inlineData`; no functionality changes. (#13700)
- [changed] **Breaking Change**: The property `citationSources` of
`CitationMetadata` has been renamed to `citations`. (#13702)
- [changed] **Breaking Change**: The constructor for `Schema` is now internal;
use the new static methods `Schema.string(...)`, `Schema.object(...)`, etc.,
- [changed] **Breaking Change**: The initializer for `Schema` is now internal;
use the new type methods `Schema.string(...)`, `Schema.object(...)`, etc.,
instead. (#13852)
- [changed] **Breaking Change**: The constructor for `FunctionDeclaration` now
- [changed] **Breaking Change**: The initializer for `FunctionDeclaration` now
accepts an array of *optional* parameters instead of a list of *required*
parameters; if a parameter is not listed as optional it is assumed to be
required. (#13616)
Expand All @@ -44,6 +44,12 @@
`FinishReason` are now structs instead of enums types and the `unknown` cases
have been removed; in a `switch` statement, use the `default:` case to cover
unknown or unhandled values. (#13728, #13854, #13860)
- [changed] **Breaking Change**: The `Tool` initializer is now internal; use the
new type method `functionDeclarations(_:)` to create a `Tool` for function
calling. (#13873)
- [changed] **Breaking Change**: The `FunctionCallingConfig` initializer and
`Mode` enum are now internal; use one of the new type methods `auto()`,
`any(allowedFunctionNames:)`, or `none()` to create a config. (#13873)
- [changed] The default request timeout is now 180 seconds instead of the
platform-default value of 60 seconds for a `URLRequest`; this timeout may
still be customized in `RequestOptions`. (#13722)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class FunctionCallingViewModel: ObservableObject {
init() {
model = VertexAI.vertexAI().generativeModel(
modelName: "gemini-1.5-flash",
tools: [Tool(functionDeclarations: [
tools: [.functionDeclarations([
FunctionDeclaration(
name: "get_exchange_rate",
description: "Get the exchange rate for currencies between countries",
Expand Down
98 changes: 53 additions & 45 deletions FirebaseVertexAI/Sources/FunctionCalling.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public struct FunctionDeclaration {
/// A brief description of the function.
let description: String

/// Describes the parameters to this function; must be of type ``DataType/object``.
/// Describes the parameters to this function; must be of type `"OBJECT"`.
let parameters: Schema?

/// Constructs a new `FunctionDeclaration`.
Expand All @@ -47,55 +47,49 @@ public struct FunctionDeclaration {
}
}

/// Helper tools that the model may use to generate response.
/// A helper tool that the model may use when generating responses.
///
/// A `Tool` is a piece of code that enables the system to interact with external systems to
/// perform an action, or set of actions, outside of knowledge and scope of the model.
/// A `Tool` is a piece of code that enables the system to interact with external systems to perform
/// an action, or set of actions, outside of knowledge and scope of the model.
public struct Tool {
/// A list of `FunctionDeclarations` available to the model.
let functionDeclarations: [FunctionDeclaration]?

/// Constructs a new `Tool`.
init(functionDeclarations: [FunctionDeclaration]?) {
self.functionDeclarations = functionDeclarations
}

/// Creates a tool that allows the model to perform function calling.
///
/// Function calling can be used to provide data to the model that was not known at the time it
/// was trained (for example, the current date or weather conditions) or to allow it to interact
/// with external systems (for example, making an API request or querying/updating a database).
/// For more details and use cases, see [Introduction to function
/// calling](https://cloud.google.com/vertex-ai/generative-ai/docs/multimodal/function-calling).
///
/// - Parameters:
/// - functionDeclarations: A list of `FunctionDeclarations` available to the model that can be
/// used for function calling.
/// The model or system does not execute the function. Instead the defined function may be
/// returned as a ``FunctionCall`` in ``ModelContent/Part/functionCall(_:)`` with arguments to
/// the client side for execution. The model may decide to call a subset of these functions by
/// populating ``FunctionCall`` in the response. The next conversation turn may contain a
/// ``FunctionResponse`` in ``ModelContent/Part/functionResponse(_:)`` with the
/// ``ModelContent/role`` "function", providing generation context for the next model turn.
public init(functionDeclarations: [FunctionDeclaration]?) {
self.functionDeclarations = functionDeclarations
/// returned as a ``FunctionCallPart`` with arguments to the client side for execution. The
/// model may decide to call none, some or all of the declared functions; this behavior may be
/// configured by specifying a ``ToolConfig`` when instantiating the model. When a
/// ``FunctionCallPart`` is received, the next conversation turn may contain a
/// ``FunctionResponsePart`` in ``ModelContent/parts`` with a ``ModelContent/role`` of
/// `"function"`; this response contains the result of executing the function on the client,
/// providing generation context for the model's next turn.
public static func functionDeclarations(_ functionDeclarations: [FunctionDeclaration]) -> Tool {
return self.init(functionDeclarations: functionDeclarations)
}
}

/// Configuration for specifying function calling behavior.
public struct FunctionCallingConfig {
/// Defines the execution behavior for function calling by defining the execution mode.
public struct Mode: EncodableProtoEnum {
enum Kind: String {
case auto = "AUTO"
case any = "ANY"
case none = "NONE"
}

/// The default behavior for function calling.
///
/// The model calls functions to answer queries at its discretion.
public static let auto = Mode(kind: .auto)

/// The model always predicts a provided function call to answer every query.
public static let any = Mode(kind: .any)

/// The model will never predict a function call to answer a query.
///
/// > Note: This can also be achieved by not passing any ``FunctionDeclaration`` tools
/// > when instantiating the model.
public static let none = Mode(kind: .none)

let rawValue: String
enum Mode: String {
case auto = "AUTO"
case any = "ANY"
case none = "NONE"
}

/// Specifies the mode in which function calling should execute.
Expand All @@ -104,20 +98,34 @@ public struct FunctionCallingConfig {
/// A set of function names that, when provided, limits the functions the model will call.
let allowedFunctionNames: [String]?

/// Creates a new `FunctionCallingConfig`.
///
/// - Parameters:
/// - mode: Specifies the mode in which function calling should execute; if unspecified, the
/// default behavior will be ``Mode/auto``.
/// - allowedFunctionNames: A set of function names that, when provided, limits the functions
/// the model will call.
/// Note: This should only be set when the ``Mode`` is ``Mode/any``. Function names should match
/// `[FunctionDeclaration.name]`. With mode set to ``Mode/any``, the model will predict a
/// function call from the set of function names provided.
public init(mode: FunctionCallingConfig.Mode? = nil, allowedFunctionNames: [String]? = nil) {
init(mode: FunctionCallingConfig.Mode? = nil, allowedFunctionNames: [String]? = nil) {
self.mode = mode
self.allowedFunctionNames = allowedFunctionNames
}

/// Creates a function calling config where the model calls functions at its discretion.
///
/// > Note: This is the default behavior.
public static func auto() -> FunctionCallingConfig {
return FunctionCallingConfig(mode: .auto)
}

/// Creates a function calling config where the model will always call a provided function.
///
/// - Parameters:
/// - allowedFunctionNames: A set of function names that, when provided, limits the functions
/// that the model will call.
public static func any(allowedFunctionNames: [String]? = nil) -> FunctionCallingConfig {
return FunctionCallingConfig(mode: .any, allowedFunctionNames: allowedFunctionNames)
}

/// Creates a function calling config where the model will never call a function.
///
/// > Note: This can also be achieved by not passing any ``FunctionDeclaration`` tools when
/// > instantiating the model.
public static func none() -> FunctionCallingConfig {
return FunctionCallingConfig(mode: FunctionCallingConfig.Mode.none)
}
}

/// Tool configuration for any `Tool` specified in the request.
Expand Down
8 changes: 4 additions & 4 deletions FirebaseVertexAI/Tests/Integration/IntegrationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ final class IntegrationTests: XCTestCase {
generationConfig: generationConfig,
safetySettings: safetySettings,
tools: [],
toolConfig: .init(functionCallingConfig: .init(mode: FunctionCallingConfig.Mode.none)),
toolConfig: .init(functionCallingConfig: .none()),
systemInstruction: systemInstruction
)
}
Expand Down Expand Up @@ -95,7 +95,7 @@ final class IntegrationTests: XCTestCase {
SafetySetting(harmCategory: .dangerousContent, threshold: .blockNone),
SafetySetting(harmCategory: .civicIntegrity, threshold: .off),
],
toolConfig: .init(functionCallingConfig: .init(mode: .auto)),
toolConfig: .init(functionCallingConfig: .auto()),
systemInstruction: systemInstruction
)

Expand Down Expand Up @@ -137,8 +137,8 @@ final class IntegrationTests: XCTestCase {
)
model = vertex.generativeModel(
modelName: "gemini-1.5-flash",
tools: [Tool(functionDeclarations: [sumDeclaration])],
toolConfig: .init(functionCallingConfig: .init(mode: .any, allowedFunctionNames: ["sum"]))
tools: [.functionDeclarations([sumDeclaration])],
toolConfig: .init(functionCallingConfig: .any(allowedFunctionNames: ["sum"]))
)
let prompt = "What is 10 + 32?"
let sumCall = FunctionCallPart(name: "sum", args: ["x": .number(10), "y": .number(32)])
Expand Down
Loading