【本日解禁】Gemini Proを体験してみよう
Gemini Pro
本日Googleが企業と開発者向けに新しい生成AIモデル「Gemini」のミドルサイズ「Gemini Pro」の提供を開始しました。
私自身、AIに関して詳しくはありませんが、軽くですが触ってみたので、体験してみたい人に向け記事を残そうと思います。
まずはGoogle AI StudioでAPIキーを作成してください。
「Create API key in new project」でOKです。
次にXcodeでプロジェクトを作成し、SPMで以下のパッケージを追加してください。
https://github.com/google/generative-ai-swift
その後は以下のコードのAPI keyをご自身のものに置き換えることでGemini Proを体験できます。
Modelを作成し、generateContentでプロンプトを渡すだけで簡単にレスポンスが取得できます。
※ レスポンスの取得まで数秒かかります。
import SwiftUI
import GoogleGenerativeAI
struct ContentView: View {
let model = GenerativeModel(name: "gemini-pro", apiKey: "APIキー")
@State private var promptText = ""
@State private var responseText = ""
var body: some View {
VStack {
Text(responseText)
.frame(height: 100)
.frame(maxWidth: .infinity)
.border(Color(.systemGray4))
TextField("prompt", text: $promptText)
.textFieldStyle(.roundedBorder)
Button("Generate") {
Task {
let response = try await model.generateContent(promptText)
if let text = response.text {
responseText = text
}
}
}
.buttonStyle(.borderedProminent)
}
.padding(.horizontal)
}
}
#Preview {
ContentView()
}
試しに質問をしてみた時の回答がこちらです。
同じ質問をChatGPTに投げた時の回答はこちらです。
Geminiの回答はChatGPTに比べてかなり淡白なものでした。
今回はGoogleのクイックスタートで説明されている「テキストのみの入力からテキストを生成する(Generate text from text-only input)」というやり方でテキストを生成したので、その影響かもしれません。
明確な答えのある質問に対しては、一問一答のような答えを提示します。「〇〇とはなんですか?」や「〇〇について教えてください。」と質問すると、丁寧な答えを提示してくれます。
追記1
Twitterに載せた動画のコードはこちらです。少しだけそれっぽくしてあります。
struct Chat: Identifiable {
let id = UUID()
let question: String
let answer: String
init(question: String, answer: String) {
self.question = "Q. " + question
self.answer = "A. " + answer
}
}
struct ContentView: View {
let model = GenerativeModel(name: "gemini-pro", apiKey: apiKey)
@State private var chats: [Chat] = []
@State private var text = ""
@State private var isGenerating = false
var body: some View {
NavigationStack {
ZStack {
Color(.systemGray6).ignoresSafeArea()
ScrollView {
VStack(alignment: .leading) {
ForEach(chats) { chat in
Text(chat.question)
.fontWeight(.semibold)
Text(chat.answer)
.padding(.top, 5)
Divider()
.padding(.vertical)
}
if isGenerating {
ProgressView("generating...")
.frame(maxWidth: .infinity)
}
}
.padding()
}
TextField("Placeholder", text: $text)
.textFieldStyle(.roundedBorder)
.padding(.horizontal)
.padding(.bottom)
.frame(maxHeight: .infinity, alignment: .bottom)
.onSubmit {
guard !text.isEmpty else { return }
Task {
isGenerating = true
defer {
isGenerating = false
}
let question = text
text.removeAll()
let response = try? await model.generateContent(question)
guard let answer = response?.text else {
print("response is nil.")
return
}
withAnimation {
chats.append(Chat(question: question, answer: answer))
}
}
}
}
.navigationTitle("Q & A")
.navigationBarTitleDisplayMode(.inline)
}
}
}
追記2
チャットモード?はこんな感じです。
struct ContentView: View {
private let model: GenerativeModel
@State private var chat: Chat
@State private var text = ""
@State private var isGenerating = false
init() {
self.model = GenerativeModel(name: "gemini-pro", apiKey: apiKey)
self.chat = model.startChat()
}
var body: some View {
NavigationStack {
ZStack {
Color(.systemGray6).ignoresSafeArea()
ScrollView {
VStack(alignment: .leading) {
ForEach(chat.history.indices, id: \.self) { i in
Text(chat.history[i].role ?? "unknown")
.fontWeight(.semibold)
Text(chat.history[i].parts[0].text ?? "text is nil.")
.padding(.top, 5)
Divider()
.padding(.vertical)
}
if isGenerating {
ProgressView("generating...")
.frame(maxWidth: .infinity)
}
}
.padding()
}
TextField("message", text: $text)
.textFieldStyle(.roundedBorder)
.disabled(isGenerating)
.padding(.horizontal)
.padding(.bottom)
.frame(maxHeight: .infinity, alignment: .bottom)
.onSubmit {
guard !text.isEmpty else { return }
Task {
isGenerating = true
defer {
isGenerating = false
text.removeAll()
}
let _ = try? await chat.sendMessage(text)
}
}
}
.navigationTitle("Chat with Gemini Pro")
.navigationBarTitleDisplayMode(.inline)
}
}
}
Discussion