このハンズオンでは Genkit の初期セットアップからはじめて、 Code Execution や Function Calling などの機能をローカル環境で動作させます。非常に簡単な内容になっていますが、このハンズオンを通して Genkit を用いた開発がいかに効率的に行えるか体験していただけると思います。

前提条件

以下のサイトにアクセスし、 Gemini の API キーを取得してください。

2024 年 11 月現在では、 Gemini API の無料プランでもこのハンズオンを試すのに十分なので、有料プランでなくても問題ありません。

ターミナルで以下の curl コマンドを貼り付けて YOUR_API_KEY 部分を置き換えて実行してみます。正常にレスポンスが返ってくることを確認しましょう。

curl \
  -H 'Content-Type: application/json' \
  -d '{"contents":[{"parts":[{"text":"Explain Firebase in under 100 words."}]}]}' \
  -X POST 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=YOUR_API_KEY'

Windows の場合は PowerShell 上で以下のコマンドを実行して確認しましょう。

curl `
  -H "Content-Type: application/json" `
  -d '{"contents":[{"parts":[{"text":"Explain Firebase in under 100 words."}]}]}' `
  -X POST 'https://generativelanguage.googleapis.com/v1beta/models/gemini-1.5-flash-latest:generateContent?key=YOUR_API_KEY'

以下のコマンドを実行してプロジェクトの初期設定を行います。

mkdir hello-genkit && cd hello-genkit
npm init -y
npm i -D genkit-cli
npm i genkit @genkit-ai/googleai @genkit-ai/express

先ほど取得した Gemini の API キーを環境変数にセットします。

export GOOGLE_GENAI_API_KEY=<your API key>

Windows の場合は PowerShell で以下のコマンドを実行し、Gemini の API キーを環境変数にセットします。

$env:GOOGLE_GENAI_API_KEY=<your API key>

ファイル src/index.ts を作成し、以下のコードを貼り付けます。

import { genkit, z } from 'genkit'
import { googleAI, gemini15Flash } from '@genkit-ai/googleai'
import { startFlowServer } from '@genkit-ai/express'
import { logger } from 'genkit/logging'
logger.setLogLevel('debug')

const ai = genkit({
  plugins: [googleAI()],
  model: gemini15Flash,
})

const mainFlow = ai.defineFlow({
  name: 'mainFlow',
  inputSchema: z.string(),
}, async (input) => {
  const { text } = await ai.generate(input)
  return text
})

startFlowServer({ flows: [mainFlow] })

以下のコマンドで Genkit が起動し、 Developer Tools が自動的に立ち上がります。

npx genkit start -o -- npx tsx --watch src/index.ts

Flows メニューに上記のコードで指定した mainFlow を選択します。文字列を入力し Run ボタンを選択すると Gemini に対してプロンプトを投げることができます。

Hello Genkit! | Flow

View trace ボタンを押すと Gemini API に対する Input, Output を詳細に確認することができます。 Hello Genkit! | Trace

Gemini の Code Execution を用いると、 Python コードを生成・実行することが可能になります。コードの変更は 1 行だけです。

-  model: gemini15Flash,
+  model: gemini15Flash.withConfig({ codeExecution: true }),

Developer Tools を開いて mainFlow にプログラミングを要するプロンプトを入力しましょう。以下にリクエスト例を挙げます。

結果は以下のようになりました。 Code Execution | Flows

View trace メニューを見ると実際に実行された Python コードを確認することができます。 Code Execution | Trace

チャレンジ

余裕のある方は Code Execution が必要なプロンプトを考えて実際に試してみましょう。

Function Calling は生成 AI が事前に定義された関数を必要に応じて呼び出し、ユーザーの要求に合致する処理を実行します。例えば以下のようなユースケースがあります。

このハンズオンでは URL の中身を抽出するツールを実装して Function Calling を体験してもらいます。HTML parser として Cheerio を利用します。

npm i cheerio

Code Execution は一度削除しておきます。

-  model: gemini15Flash.withConfig({ codeExecution: true }),
+  model: gemini15Flash,

cheerio を import します。

  import { genkit, z } from 'genkit'
  import { googleAI, gemini15Flash } from '@genkit-ai/googleai'
+ import * as cheerio from 'cheerio'

src/index.ts の ai 変数定義の下に以下の関数を追加します。第一引数に tool の設定値を指定し、第二引数に実行する処理を記載します。

const webLoader = ai.defineTool(
  {
    name: "webLoader",
    description:
      "When a URL is received, it accesses the URL and retrieves the content inside.",
    inputSchema: z.object({ url: z.string() }),
    outputSchema: z.string(),
  },
  async ({ url }) => {
    const res = await fetch(url)
    const html = await res.text()
    const $ = cheerio.load(html)
    $("script, style, noscript").remove()
    if ($("article")) {
      return $("article").text()
    }
    return $("body").text()
  },
)

generate メソッドのパラメータに tools を指定して、配列の中身に webLoader を指定します。 tools は配列で指定できるので複数のツールを設定することができます。その中から必要なツールを生成 AI が選択して実行します。必要かどうかの判断は defineTooldescription をもとに行われます。そのためプロンプトエンジニアリングと同様に description のチューニングは重要です。

-  const { text } = await ai.generate(input)
+  const { text } = await ai.generate({ prompt: input, tools: [webLoader] })

最終的なソースコードは以下の GitHub で確認できます。

https://github.com/tanabee/genkit-codelab/blob/main/steps/function-calling/src/index.ts

それでは、コードが完成したので Developer Tools を開いてみます。 Tools メニューに webLoader が追加されていることが分かります。 webLoader を選択し、以下の URL を挿入して実行します。

URL: https://zenn.dev/tanabee/articles/e05f722c7cbc6c

Function Calling | Tool

URL の中身のコンテンツを抽出できました。このように Genkit の Deleloper Tools では tool 単体で検証することができます。tool が実際に動作することが分かって Flow に組み込むことができるので効率よく開発を進められます。

次に Flow メニューから mainFlow を選択します。以下のようにプロンプトを入力して実行してみます。

プロンプト: 以下の URL の内容を 200 文字以内で要約してください。https://zenn.dev/tanabee/articles/e05f722c7cbc6c

抽出された内容をもとに要約されていることが分かります。

Function Calling | Flow

View trace を見てみます。すると Gemini API リクエストが 2 回行われている間に webLoader の呼び出しがあり、実際に tool が呼び出されたことが分かります。

Function Calling | Trace

チャレンジ

余裕のある方は自分で tool を定義して Function Calling を実装してみましょう。

以上でこのハンズオンは終わりです。少量のコードでこれだけのことが実現できるのは素晴らしいことだと思います。もっと深堀りしたい方向けに Next Action を提示しておきます。

Next steps