見出し画像

自分用にカスタムした簡易的なGemini 2.0 Flash(Experimental) APIを作ってみる


動機

こんにちは、Koshiishiです。
私はよく、軽い正規表現の質問やLinuxコマンドのオプションについてGPTに尋ねています。しかし簡単な質問のために毎回ブラウザを開くのは手間がかかるため、自分用にAPIを作成したり、Slackから呼び出したくなりました。
そこで応答が速くコストの低いLLMのAPIを探していたところ、Gemini APIを見つけました。

Gemini APIの料金 見る限りでは、無料枠が大きく、応答の精度はGPTほどではないにしろ、早くレスポンスが帰ってくると伺ったため試してみました。
また、2.0 Flashは試験段階のためかAI Studio上で確認する限りは0$となっている点も非常に魅力的です。
上限は一分あたり10リクエスト、一日あたり1500リクエストのようです。

※ 学習に関して
Vertex Ai Studio でGeminiを使用する場合はモデルのトレーニングや強化に使用されることはないという記述がありましたが、API経由でGemini2.0を呼び出す際のデータが学習に使われるかの記載は見つかりませんでした(ありましたらコメントください)
※ 機微な情報を扱う場合はご注意ください
※ こちらの投稿時点で料金体系が変わっている可能性もありますので、ご利用の際はご自身で今一度料金 をご確認いただければと思います。

最終的なコード
こちらの投稿ではhonoで作ったgemini apiを呼び出すAPIをCloudflare Workersにデプロイするところまでをご紹介いたします。
ヘッダーによるバリデーションもつけてみました。
次回の投稿ではSlackとの繋ぎこみを紹介させていたこうと思っています。

余談:なぜ今回honoを選んだのか

hono は軽量かつ高速なWebフレームワークでCloudflareにもデプロイしやすく愛用しています。公式GitHub
Cloudflare用のテンプレートがある点が自分には非常に助かっています。
個人でさっとAPI生やしたいときはhonoをCloudflareにデプロイするか、無料DB枠があるshuttle で済ませることが多いです。
参考: Rustのフレームワーク色々試したい時はShuttleがおすすめです

準備

  • Google AI StudioのGet API key でAPI keyを作成

  • Cloudflare のアカウント

  • wranglerのインストールと設定

    • npm install -g wranglerしたのち、wrangler loginでブラウザが起動するので、ログインしてください。

  • 作成するhono用のAPIキーを作成(おこのみで)

honoのプロジェクト作成

hono-geminiという名前でプロジェクトを作成します。

❯ bun create hono@latest hono-gemini
create-hono version 0.14.3
✔ Using target directory … hono-gemini
? Which template do you want to use? cloudflare-workers
? Do you want to install project dependencies? yes
? Which package manager do you want to use? bun
✔ Cloning the template
✔ Installing project dependencies
🎉 Copied project files
Get started with: cd hono-gemini

honoでGeminiAPIを呼び出すAPIを実装

bun add @google/generative-ai

src/index.tsを編集

...
import { GoogleGenerativeAI } from '@google/generative-ai'
...
app.post('/ask', async (c) => {
  try {
    const { question } = await c.req.json<{ question: string }>()
    const genAI = new GoogleGenerativeAI(c.env.GEMINI_API_KEY)
    const model = genAI.getGenerativeModel({ model: "gemini-2.0-flash-exp" })
    const result = await model.generateContent(question)
    const response = result.response
    return c.json({ answer: response.text() })
  } catch (error) {
    return c.json({ error: 'error occurred' }, 500)
  }
})

環境変数にGeminiのAPI key設定

ローカル環境でGEMINI_API_KEYを設定
.dev.varsの編集
wranglerでは、ローカルでの実行時には.dev.varsが読み込まれます

GEMINI_API_KEY = "生成したGeminiのAPI_KEY"

Cloudflare環境上でGEMINI_API_KEYを設定
対話的に尋ねられるので、入力してエンターを押します。

wrangler secret put Cloudflare環境上でGEMINI_API_KEYを設定

 ⛅️ wrangler 3.95.0
-------------------

? Enter a secret value: › ************

ローカルでの起動と動作確認

ローカルでの起動

❯ bun run dev
$ wrangler dev

 ⛅️ wrangler 3.95.0
-------------------

Using vars defined in .dev.vars
Your worker has access to the following bindings:
- Vars:
  - GEMINI_API_KEY: "(hidden)"
⎔ Starting local server...
[wrangler:inf] Ready on http://localhost:8787

動作確認

❯ curl -X POST http://localhost:8787/ask -H "Content-Type: application/json" -d '{"question": "whats your name?"}'
{"answer":"I am a large language model, trained by Google.\n"}

Cloudflareへのデプロイと動作確認

❯ wrangler deploy

 ⛅️ wrangler 3.95.0
-------------------

Total Upload: 90.94 KiB / gzip: 20.16 KiB
Worker Startup Time: 1 ms
Uploaded hono-gemini (2.43 sec)
Deployed hono-gemini triggers (0.22 sec)
  https://hono-gemini.[CloudflareのアカウントID].workers.dev
Current Version ID: [version id]
# 隠しています
❯ curl -X POST https://hono-gemini.[CloudflareのアカウントID].workers.dev/ask -H "Content-Type: application/json" -d '{"question": "whats your name?"}'
{"answer":"I am a large language model, trained by Google.\n"}

x-api-keyでのバリデーションを追加

wrangler deployでCloudflare Workerにデプロイしたところ、結構規則性のあるURLで公開されました。
念の為、x-api-keyでのバリデーションも追加したくなったので、追加してみました。
honoのValidation の項を参考に
src/middleware/validateApiKey.ts を追加して編集します。

import { MiddlewareHandler, Context } from 'hono'

export const validateApiKey = (getApiKey: (c: Context) => string): MiddlewareHandler => {
  return async (c, next) => {
    const authKey = c.req.header('x-api-key')
    const expectedKey = getApiKey(c)
    if (!authKey || authKey !== expectedKey) {
      return c.json({ error: 'Invalid API key' }, 401)
    }
    await next()
  }
}

src/index.tsで、それを呼び出すようにしました
今回は雑にすべてのAPIでvalidationするようにしました

import { validateApiKey } from './middleware/validateApiKey'

interface Env {
  GEMINI_API_KEY: string
  API_KEY: string
}

const app = new Hono<{ Bindings: Env }>()

app.use('*', validateApiKey(c => c.env.API_KEY))

API_KEYを、GEMINI_API_KEYと同様に.dev.varsと、wrangler secret putでローカルとCloudflare両方に適用した後に再度wrangler deployして完成です

デプロイ後の動作確認

# キー設定で通ることを確認
❯ curl -X POST [デプロイ先のAPI]/ask -H "Content-Type: application/json" -H "x-api-key:[自分で決めたAPI_KEY]" -d '{"question": 
"who are you?"}'
{"answer":"I am a large language model, trained by Google.\n"}
# 誤ったAPI_KEYで弾かれることを確認
❯ curl -X POST [デプロイ先のAPI]/ask -H "Content-Type: application/json" -H "x-api-key:FALSE_API_KEY" -d '{"question": 
"who are you?"}'
{"error":"Invalid API key"}
# キー無しで弾かれることを確認
❯ curl -X POST [デプロイ先のAPI]/ask -H "Content-Type: application/json" -d '{"question": 
"who are you?"}'
{"error":"Invalid API key"}

おわりに

Gemini 2.0 Flash(Experimental)を利用したAPIをhonoで作成し、Cloudflare Workers上で公開する方法を紹介しました。

次回の投稿で、SlackのコマンドからこちらのAPIを呼び出す手順を紹介します。


執筆者プロフィール:Kenta Koshiishi
スタートアップ企業でFigmaを使用したUI設計から、Rustでのバックエンド開発、Reactでのフロントエンド開発まで、一気通貫で手掛けてきた。 SHIFTではシニアエンジニアとして入社し、既存のWebアプリに触れ始めた。

この筆者のおすすめ記事

✅SHIFTへのご相談、お問合せはお気軽に

SHIFTについて(コーポレートサイト)
https://www.shiftinc.jp/

SHIFTのサービスについて(サービスサイト)
https://service.shiftinc.jp/

SHIFTの導入事例
https://service.shiftinc.jp/case/

お役立ち資料はこちら
https://service.shiftinc.jp/resources/

SHIFTの採用情報はこちら
https://recruit.shiftinc.jp/career/

PHOTO:UnsplashAndrew W