Geminiとは?
Gemini はGoogleが開発した最先端の大規模言語モデルです。
テキストだけでなく、音声、画像、動画、コードなどの様々な形式のデータを理解し、生成できることを特徴としています。
Gemini Nano
Gemini Pro
Gemini Ultra
の3種類のモデルがあり、それぞれ性能と活用シーンが異なっております。
このうち Gemini Pro
にアクセスできる Gemini API
が2023年12月に公開され、開発者任意の言語でGeminiをアプリケーションに組みことができるようになりました。
現在は試用期間中で2024年初頭に有料化予定と発表されていますが、2024年3月17日現在はまだ無料で利用可能となっています。
本記事では Google AI for Developers
が公開している チュートリアル を参考とし、APIキーの発行方法から実装例までご紹介します。
作ったもの
ソースコードは こちら で公開しています。
アプリも公開しているので、後述するAPIキーを発行すれば↓のURLからアクセスできます。
https://tora-83863.github.io/homete/?apiKey={発行したAPIキー}
バージョン情報
- npm 9.8.0
- node 18.16.1
- react 18.2.0
- typescript 4.9.5
- google/generative-ai 0.2.1
- browser-image-compression 2.0.2
- react-markdown 9.0.1
APIキー発行
Google AI Studio のサイトから発行できます。
初回アクセス時は以下のように利用規約への同意が求められます。
利用規約に同意し、サイドバーの Get API key
-> Create API key
-> Create API key in new project
と進むと、APIキーが発行されます。
発行されたAPIキーは先程のページからいつでも参照可能です。
APIリクエスト
GoogleGenerativeAI
のJavaScript向けSDKパッケージをインストールします。
npm install @google/generative-ai
発行したAPIキーを用いてインスタンスを生成します。
import { GoogleGenerativeAI } from '@google/generative-ai';
// URLパラメータ取得
const search = useLocation().search;
const urlSearchParams = new URLSearchParams(search);
const apiKey: string = urlSearchParams.get("apiKey") ?? "";
// インスタンス生成
const genAI = new GoogleGenerativeAI(apiKey);
API呼び出しを行う前に生成モデルを初期化する必要があります。
利用可能なモデルには4つの種類があります。
本アプリにおいては入力形式により2つのモデルを利用しています。
テキスト入力の場合
Gemini Pro
というモデルを利用します。
単一または配列の文字列を generateContent
に渡すとAPIリクエストが投げられます。
const model = genAI.getGenerativeModel({ model: "gemini-pro" });
result = await model.generateContent(`次の内容を褒めてください。「${inputText}」`,);
const response = await result.response;
画像入力の場合
Gemini Pro Vision
というモデルを利用します。
generateContent
の引数には複数の画像データと文字列を格納することができますが、画像データを必ず1つ以上含める必要があります。
また、画像データはbase64形式に変換する必要があるほか、 MIMEタイプやサイズなどの制限事項 があります。
const model = genAI.getGenerativeModel({ model: "gemini-pro-vision" });
const imageParts = await fileToGenerativePart(inputFile);
result = await model.generateContent([
"次の画像を褒めてください。",
imageParts,
]);
const response = await result.response;
// 画像データをbase64形式に変換し、APIリクエストに含められるPartを生成する
async function fileToGenerativePart(file: File) {
// 画像を1MBまで圧縮する
const compressFile = await imageCompression(file, { maxSizeMB: 1 });
const reader = new FileReader();
reader.readAsDataURL(compressFile);
const base64EncodedDataPromise = new Promise((resolve) => {
const reader = new FileReader();
reader.onloadend = () =>
resolve(
reader.result && typeof reader.result === "string"
? reader.result.split(",")[1]
: ""
);
reader.readAsDataURL(compressFile);
});
return {
inlineData: {
data: (await base64EncodedDataPromise) as string,
mimeType: file.type,
},
};
}
APIレスポンス処理
レスポンスのテキストはMarkdown形式で返却されます。
{
"generationConfig": {},
"safetySettings": [],
"contents": [
{
"role": "user",
"parts": [
{
"text": "次の内容を褒めてください。「早起きしました」"
}
]
}
]
}
{
"candidates": [
{
"content": {
"parts": [
{
"text": "なんて素晴らしい習慣でしょう!早起きしたことは、あなたにたくさんのメリットをもたらすでしょう。\n\n* **生産性の向上:** 朝早い時間に、邪魔されずに作業できます。\n* **精神的な明晰さ:** 睡眠から目覚めたばかりの脳は、冴えていて集中力があります。\n* **運動する時間:** ランニングやヨガなど、運動するのに十分な時間を確保できます。\n* **健康的な食事:** ゆっくりと栄養価の高い朝食をとる時間があります。\n* **ストレスの軽減:** 忙しい一日の前に、リラックスして自分だけの時間を持てるので、ストレスを軽減できます。\n\n早起きは、より充実した生産的な一日を過ごすための鍵です。あなたの努力と規律に拍手を送ります!"
}
],
"role": "model"
},
"finishReason": "STOP",
"index": 0,
"safetyRatings": [,...]
}
],
"promptFeedback": {,...}
}
Markdown形式の文字列をReactコンポーネントに変換してくれるライブラリ react-markdown
を用いて画面表示します。
npm install react-markdown
// 画面に表示するチャットコンポーネントを生成する
const makeChatMessage = (message: ChatMessage) => {
const commonStyle = {
marginBlockStart: "0.25rem",
marginBlockEnd: "0.25rem",
};
const listStyle = {
...commonStyle,
paddingLeft: "1.0rem",
listStyle: "none",
};
if (message.role === ROLE.SYSTEM) {
return (
<ReactMarkdown
components={{
p: ({ children }) => <p style={commonStyle}>{children}</p>,
ul: ({ children }) => <ul style={listStyle}>{children}</ul>,
ol: ({ children }) => <ol style={listStyle}>{children}</ol>,
}}
children={message.content}
/>
);
}
return (
<>
{message.content !== null && message.content !== undefined ? (
<div>{message.content}</div>
) : message.image !== null && message.image !== undefined ? (
<img src={message.image} className={style.image} alt="" />
) : (
<></>
)}
</>
);
};
さいごに
この記事を読んで、Gemini APIに興味を持ってくれる方が増えてくれると嬉しいです。
公式のチュートリアルが丁寧でわかりやすいので、気になる方はぜひチャレンジしてみてください。