-
Notifications
You must be signed in to change notification settings - Fork 1.7k
[Vertex AI] Add code snippets for use in docs #13653
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from 7 commits
Commits
Show all changes
8 commits
Select commit
Hold shift + click to select a range
d5b5abe
Copy snippets from `generative-ai-swift`
andrewheard 9686048
Update snippets for Vertex AI
andrewheard d91cfb1
Fix FirebaseCore import
andrewheard 9503456
Fix availability annotations
andrewheard f839eaf
Add JSON generation and function calling snippets; remove others.
andrewheard ca43d7a
Remove trailing whitespace
andrewheard 6bd5e8a
Adjust line length
andrewheard f832e8a
Fix formatting
andrewheard File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
46 changes: 46 additions & 0 deletions
46
FirebaseVertexAI/Tests/Unit/Snippets/FirebaseAppSnippetsUtil.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
// Copyright 2024 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 FirebaseCore | ||
import Foundation | ||
import XCTest | ||
|
||
extension FirebaseApp { | ||
static let projectIDEnvVar = "PROJECT_ID" | ||
static let appIDEnvVar = "APP_ID" | ||
static let apiKeyEnvVar = "API_KEY" | ||
|
||
static func configureForSnippets() throws { | ||
let environment = ProcessInfo.processInfo.environment | ||
guard let projectID = environment[projectIDEnvVar] else { | ||
throw XCTSkip("No Firebase Project ID specified in environment variable \(projectIDEnvVar).") | ||
} | ||
guard let appID = environment[appIDEnvVar] else { | ||
throw XCTSkip("No Google App ID specified in environment variable \(appIDEnvVar).") | ||
} | ||
guard let apiKey = environment[apiKeyEnvVar] else { | ||
throw XCTSkip("No API key specified in environment variable \(apiKeyEnvVar).") | ||
} | ||
|
||
let options = FirebaseOptions(googleAppID: appID, gcmSenderID: "") | ||
options.projectID = projectID | ||
options.apiKey = apiKey | ||
|
||
FirebaseApp.configure(options: options) | ||
guard FirebaseApp.isDefaultAppConfigured() else { | ||
XCTFail("Default Firebase app not configured.") | ||
return | ||
} | ||
} | ||
} |
108 changes: 108 additions & 0 deletions
108
FirebaseVertexAI/Tests/Unit/Snippets/FunctionCallingSnippets.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,108 @@ | ||
// Copyright 2024 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 FirebaseCore | ||
import FirebaseVertexAI | ||
import XCTest | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
final class FunctionCallingSnippets: XCTestCase { | ||
override func setUpWithError() throws { | ||
try FirebaseApp.configureForSnippets() | ||
} | ||
|
||
override func tearDown() async throws { | ||
if let app = FirebaseApp.app() { | ||
await app.delete() | ||
} | ||
} | ||
|
||
func testFunctionCalling() async throws { | ||
// This function calls a hypothetical external API that returns | ||
// a collection of weather information for a given location on a given date. | ||
func fetchWeather(city: String, state: String, date: String) -> JSONObject { | ||
// TODO(developer): Write a standard function that would call an external weather API. | ||
|
||
// For demo purposes, this hypothetical response is hardcoded here in the expected format. | ||
return [ | ||
"temperature": .number(38), | ||
"chancePrecipitation": .string("56%"), | ||
"cloudConditions": .string("partlyCloudy"), | ||
] | ||
} | ||
|
||
let fetchWeatherTool = FunctionDeclaration( | ||
name: "fetchWeather", | ||
description: "Get the weather conditions for a specific city on a specific date.", | ||
parameters: [ | ||
"location": .object( | ||
properties: [ | ||
"city": .string(description: "The city of the location."), | ||
"state": .string(description: "The US state of the location."), | ||
], | ||
description: """ | ||
The name of the city and its state for which to get the weather. Only cities in the | ||
USA are supported. | ||
""" | ||
), | ||
"date": .string(description: """ | ||
The date for which to get the weather. Date must be in the format: YYYY-MM-DD. | ||
""" | ||
), | ||
] | ||
) | ||
|
||
// Initialize the Vertex AI service and the generative model. | ||
// Use a model that supports function calling, like a Gemini 1.5 model. | ||
let model = VertexAI.vertexAI().generativeModel( | ||
modelName: "gemini-1.5-flash", | ||
// Provide the function declaration to the model. | ||
tools: [.functionDeclarations([fetchWeatherTool])] | ||
) | ||
|
||
let chat = model.startChat() | ||
let prompt = "What was the weather in Boston on October 17, 2024?" | ||
|
||
// Send the user's question (the prompt) to the model using multi-turn chat. | ||
let response = try await chat.sendMessage(prompt) | ||
|
||
var functionResponses = [FunctionResponsePart]() | ||
|
||
// When the model responds with one or more function calls, invoke the function(s). | ||
for functionCall in response.functionCalls { | ||
if functionCall.name == "fetchWeather" { | ||
// TODO(developer): Handle invalid arguments. | ||
guard case let .object(location) = functionCall.args["location"] else { fatalError() } | ||
guard case let .string(city) = location["city"] else { fatalError() } | ||
guard case let .string(state) = location["state"] else { fatalError() } | ||
guard case let .string(date) = functionCall.args["date"] else { fatalError() } | ||
|
||
functionResponses.append(FunctionResponsePart( | ||
name: functionCall.name, | ||
response: fetchWeather(city: city, state: state, date: date) | ||
)) | ||
} | ||
// TODO(developer): Handle other potential function calls, if any. | ||
} | ||
|
||
// Send the response(s) from the function back to the model so that the model can use it | ||
// to generate its final response. | ||
let finalResponse = try await chat.sendMessage( | ||
[ModelContent(role: "function", parts: functionResponses)] | ||
) | ||
|
||
// Log the text response. | ||
print(finalResponse.text ?? "No text in response.") | ||
} | ||
} |
95 changes: 95 additions & 0 deletions
95
FirebaseVertexAI/Tests/Unit/Snippets/StructuredOutputSnippets.swift
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,95 @@ | ||
// Copyright 2024 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 FirebaseCore | ||
import FirebaseVertexAI | ||
import XCTest | ||
|
||
@available(iOS 15.0, macOS 12.0, macCatalyst 15.0, tvOS 15.0, watchOS 8.0, *) | ||
final class StructuredOutputSnippets: XCTestCase { | ||
override func setUpWithError() throws { | ||
try FirebaseApp.configureForSnippets() | ||
} | ||
|
||
override func tearDown() async throws { | ||
if let app = FirebaseApp.app() { | ||
await app.delete() | ||
} | ||
} | ||
|
||
func testStructuredOutputJSONBasic() async throws { | ||
// Provide a JSON schema object using a standard format. | ||
// Later, pass this schema object into `responseSchema` in the generation config. | ||
let jsonSchema = Schema.object( | ||
properties: [ | ||
"characters": Schema.array( | ||
items: .object( | ||
properties: [ | ||
"name": .string(), | ||
"age": .integer(), | ||
"species": .string(), | ||
"accessory": .enumeration(values: ["hat", "belt", "shoes"]), | ||
], | ||
optionalProperties: ["accessory"] | ||
) | ||
), | ||
] | ||
) | ||
|
||
// Initialize the Vertex AI service and the generative model. | ||
// Use a model that supports `responseSchema`, like one of the Gemini 1.5 models. | ||
let model = VertexAI.vertexAI().generativeModel( | ||
modelName: "gemini-1.5-flash", | ||
// In the generation config, set the `responseMimeType` to `application/json` | ||
// and pass the JSON schema object into `responseSchema`. | ||
generationConfig: GenerationConfig( | ||
responseMIMEType: "application/json", | ||
responseSchema: jsonSchema | ||
) | ||
) | ||
|
||
let prompt = "For use in a children's card game, generate 10 animal-based characters." | ||
|
||
let response = try await model.generateContent(prompt) | ||
print(response.text ?? "No text in response.") | ||
} | ||
|
||
func testStructuredOutputEnumBasic() async throws { | ||
// Provide an enum schema object using a standard format. | ||
// Later, pass this schema object into `responseSchema` in the generation config. | ||
let enumSchema = Schema.enumeration(values: ["drama", "comedy", "documentary"]) | ||
|
||
// Initialize the Vertex AI service and the generative model. | ||
// Use a model that supports `responseSchema`, like one of the Gemini 1.5 models. | ||
let model = VertexAI.vertexAI().generativeModel( | ||
modelName: "gemini-1.5-flash", | ||
// In the generation config, set the `responseMimeType` to `text/x.enum` | ||
// and pass the enum schema object into `responseSchema`. | ||
generationConfig: GenerationConfig( | ||
responseMIMEType: "text/x.enum", | ||
responseSchema: enumSchema | ||
) | ||
) | ||
|
||
let prompt = """ | ||
The film aims to educate and inform viewers about real-life subjects, events, or people. | ||
It offers a factual record of a particular topic by combining interviews, historical footage, | ||
and narration. The primary purpose of a film is to present information and provide insights | ||
into various aspects of reality. | ||
""" | ||
|
||
let response = try await model.generateContent(prompt) | ||
print(response.text ?? "No text in response.") | ||
} | ||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.