iOS (Swift) で Gemini API を試す
「iOS (Swift)」で「Gemini API」を試したので、まとめました。
1. Gemini API
「Gemini API」は、「Google DeepMind」が開発したマルチモーダル大規模言語モデル「Gemini」を利用するためのAPIです。
2. Gemini API の利用料金
「Gemini API」の利用料金は、以下を参照。
3. Gemini API の準備
「iOS (Swift)」での「Gemini API」の準備手順は、次のとおりです。
3-1. プロジェクトの作成
(1) XcodeでiOSのプロジェクトを作成。
「iOS」の「App」テンプレートでプロジェクトを作成します。
3-2. APIキーの準備
「APIキー」はバージョン管理システム (gitなど) に入れないことが推奨されています。「GenerativeAI-Info.plist」に保存して、バージョン管理から除外してください。
(1) プロジェクトに「GenerativeAI-Info.plist」(Propaty List) を追加。
(2) 「GenerativeAI-Info.plist」を右クリック「Open As → Source Code」で開き、以下のように記述。
_API_KEY_ には「Google AI Studio」から取得したAPIキーを指定してください。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>API_KEY</key>
<string>_API_KEY_</string>
</dict>
</plist>
(3) プロジェクトに「APIKey.swift」を追加。
「GenerativeAI-Info.plist」からAPIキーを取得するコードになります。
・APIKey.swift
import Foundation
// APIキー
enum APIKey {
static var `default`: String {
guard let filePath = Bundle.main.path(forResource: "GenerativeAI-Info", ofType: "plist")
else {
fatalError("Couldn't find file 'GenerativeAI-Info.plist'.")
}
let plist = NSDictionary(contentsOfFile: filePath)
guard let value = plist?.object(forKey: "API_KEY") as? String else {
fatalError("Couldn't find key 'API_KEY' in 'GenerativeAI-Info.plist'.")
}
if value.starts(with: "_") {
fatalError(
"Follow the instructions at https://ai.google.dev/tutorials/setup to get an API key."
)
}
return value
}
}
3-3. generative-ai-swiftパッケージの追加
(1) プロジェクトナビゲータのプロジェクト名を右クリックし、「Add Package Dependencies」をクリック。
(2) 左上の検索ボックスで「https://github.com/google/generative-ai-swift」を検索し、「Add Package」ボタンを押す。
(3) 「Add Package」ボタンを押す。
4. テキスト生成の実行
4-1. テキスト生成
(1) 「ContentView.swift」を以下のようにコード編集。
・ContentView.swift
import SwiftUI
import GoogleGenerativeAI // パッケージの追加
struct ContentView: View {
var body: some View {
VStack {
Image(systemName: "globe")
.imageScale(.large)
.foregroundStyle(.tint)
Text("Hello, world!")
}
.padding()
.onAppear() {
Task {
await runGemini()
}
}
}
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default
)
// 推論の実行
do {
let response = try await model.generateContent("日本一高い山は?")
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
}
#Preview {
ContentView()
}
(2) アプリの実行。
推論の実行結果がコンソールに出力されます。
4-2. ストリーミング
(1) 「ContentView.swift」を以下のようにコード編集。
・ContentView.swift の一部
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default
)
// 推論の実行
do {
let contentStream = model.generateContentStream("富士山を説明してください")
for try await chunk in contentStream {
if let text = chunk.text {
print(text)
print("----")
}
}
} catch {
print("Error: \(error)")
}
}
(2) アプリの実行。
4-3. チャット
(1) 「ContentView.swift」を以下のようにコード編集。
・ContentView.swift の一部
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default
)
// チャットの準備
let chat = model.startChat(history: [])
do {
// 質問応答 (1ターン目)
let response1 = try await chat.sendMessage("日本一高い山は?")
if let text = response1.text {
print(text)
}
// 質問応答 (2ターン目)
let response2 = try await chat.sendMessage("その山は何県にある?")
if let text = response2.text {
print(text)
}
// 会話履歴の表示
print(chat.history)
} catch {
print("Error: \(error)")
}
}
(2) アプリの実行。
5. Visionの実行
5-1. Visionの実行 (画像入力)
(1) 画像を「Assets.xcassets」に「cat.jpg」を追加。
・cat.jpg
(2) 「ContentView.swift」を以下のようにコード編集。
・ContentView.swift の一部
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro-vision",
apiKey: APIKey.default
)
// 画像の準備
let image = UIImage(named: "cat")!
// 推論の実行
do {
let response = try await model.generateContent(image)
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
(3) アプリの実行。
5-2. Visionの実行 (テキスト・画像入力)
(1) 「ContentView.swift」を以下のようにコード編集。
・ContentView.swift の一部
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro-vision",
apiKey: APIKey.default
)
// 画像の準備
let image = UIImage(named: "cat")!
// 推論の実行
do {
let response = try await model.generateContent(
"これは何の画像ですか?",
image
)
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
(2) アプリの実行。
6. 生成パラメータ
GenerativeModel()、model.generateContent()、chat.sendMessage()で、生成パラメータとセーフティセッティングを指定できます。
(1) 推論の実行 (生成パラメータあり)
func runGemini() async {
// モデルの準備
let config = GenerationConfig(
temperature: 1.0,
topP: 0.1,
topK: 16,
maxOutputTokens: 400,
stopSequences: ["x"]
)
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default,
generationConfig: config
)
// 推論の実行
do {
let response = try await model.generateContent("魔法のアンパンの話をしてください。")
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
7. セーフティセッティング
(1) 推論の実行 (セーフティセッティングなし)。
ユーザー入力が不適切と判断された場合、ブロックされます。
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default
)
// 推論の実行
do {
let response = try await model.generateContent("お前は愚か者だ")
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
Error: promptBlocked(
response: GoogleGenerativeAI.GenerateContentResponse(
candidates: [],
promptFeedback: Optional(GoogleGenerativeAI.PromptFeedback(blockReason: Optional(GoogleGenerativeAI.PromptFeedback.BlockReason.safety),
safetyRatings: [
GoogleGenerativeAI.SafetyRating(category: GoogleGenerativeAI.SafetySetting.HarmCategory.sexuallyExplicit, probability: GoogleGenerativeAI.SafetyRating.HarmProbability.negligible),
GoogleGenerativeAI.SafetyRating(category: GoogleGenerativeAI.SafetySetting.HarmCategory.hateSpeech, probability: GoogleGenerativeAI.SafetyRating.HarmProbability.negligible),
GoogleGenerativeAI.SafetyRating(category: GoogleGenerativeAI.SafetySetting.HarmCategory.harassment, probability: GoogleGenerativeAI.SafetyRating.HarmProbability.high),
GoogleGenerativeAI.SafetyRating(category: GoogleGenerativeAI.SafetySetting.HarmCategory.dangerousContent, probability: GoogleGenerativeAI.SafetyRating.HarmProbability.negligible)
]
)))
)
(2) セーフティセッティング付きの質問応答
「block_none」を指定することで、応答が返される場合があります。
func runGemini() async {
// モデルの準備
let model = GenerativeModel(
name: "models/gemini-pro",
apiKey: APIKey.default,
safetySettings: [
SafetySetting(harmCategory: .harassment, threshold: .blockNone)
]
)
// 推論の実行 (セーフティセッティングあり)
do {
let response = try await model.generateContent("お前は愚か者だ")
if let text = response.text {
print(text)
}
} catch {
print("Error: \(error)")
}
}
8. サンプルアプリ
関連
この記事が気に入ったらサポートをしてみませんか?