Gemini 1.5 で制御生成をマスターする: デベロッパー向けのスキーマ準拠

9月 03, 2024
Lewis Liu Group Product Manager Gemini
Terry Koo Research Scientist Google Deepmind

生成 AI の話題は盛り上がりを見せていますが、その多くは「何ができるのか」、すなわち基礎モデルによる実験や革新の可能性に注目したものです。しかし Google は、AI エコシステム全体を提供することに取り組み続けています。この点は、最高水準のモデルを試すことだけでなく、実用的なアプリケーションに AI を採用することにも役立っています。

その道のりの一環として、今年の Google I/O では、Gemini 1.5 Pro の「制御生成」を紹介しました。うれしいことに、急速に採用が広がり、前向きなフィードバックが寄せられています。本日は、その取り組みを一歩進め、Gemini 1.5 Flash に制御生成を導入し、「列挙型」のサポートを追加します。これはデベロッパーにとって堅牢なツールであり、定義済みのスキーマに準拠した応答を確実に生成できるようになります。また、Gemini 1.5 で関数呼び出しを使うときは、モードにかかわらず、自動的に制御生成が有効になります。


制御生成とは何か、なぜ重要なのか

制御生成は、モデルの出力の設計図を提供するようなものだと考えてください。応答スキーマを定義することで、AI の応答の正確な形式と構造を伝達します。これは、JSON 形式でエンティティを抽出して下流の処理をシームレスに行いたい場合や、独自の分類法によってニュース記事を分類したい場合などに役立ちます。制御生成によって一貫性が確保され、時間をかけて後処理を行う必要性を減らすことができます。

AI をソフトウェア開発に完全に組み込むには、2 つのことが必要です。1 つは、データ サイエンス チームおよび機械学習チームからアプリケーション デベロッパーへのシームレスな引き継ぎ。もう 1 つは、モデルの出力を既存のシステムにシームレスに組み込むことです。制御生成によって、次のことが可能になります。

  • AI が機械で読み取れる使いやすいデータを生成できるようになるので、手間のかかる後処理や解析を行う必要性を減らすことができます。

  • JSON などの形式で出力を生成できるので、AI が API エコノミーの第一級市民になります。既存のワークフローにシームレスに追加できます。

  • AI の出力に一定の予測可能性がもたらされます。AI モデルが生成するデータのフォーマットと構造が確実に予測可能なものになります。

初期テスターの 1 社である The Estée Lauder Companies のプリンシパル機械学習エンジニアである Chris Curro 氏は、次のように述べています。「Gemini 1.5 で複雑な推論ワークフローを設計し、消費者向けと従業員向けのエクスペリエンスを構築しています。これは、ほかの方法では実現できないものです。デベロッパー フレンドリーな制御生成を利用することで、チームが短時間で作業を進め、ビジネス価値を向上させることができました」

この機能は、Google チームが開発した制御デコードと呼ばれる最新の技術進展がベースとなっています。こちらの論文では、基礎となる技術を詳しく説明しています。

Gemini API と Vertex AI API には、「応答スキーマ」の概念が導入されています。応答スキーマは、AI 出力の要素、データ型、全体的な構造を指示するテンプレートです。スキーマは OpenAPI 3.0 スキーマ定義に基づいているので、常にオープンで互換性のある標準に従って開発することになります。プロンプトに応答スキーマを含めることで、定義されたルールに従うようにモデルに指示することができ、予測可能で構造化された結果が得られます。


Google「秘伝のタレ」

  • Gemini の制御生成は、既存の API 呼び出しで利用しても、最小限の待ち時間しか増加しません。この点は、初回の API 呼び出しでも変わりません

  • Gemini は型として列挙型をサポートしており、さらに多くの機能が追加される予定です

  • Gemini にスキーマを強制しても、皆さんのデータが保存されることはありません


使ってみるには

制御生成機能は、Google AI StudioVertex AI の Gemini 1.5 Pro と Gemini 1.5 Flash の両方で利用できます。


例: JSON スキーマを使って食事計画アプリを作成する

さまざまなシナリオのレシピを提案するアプリを開発しているとしましょう。アプリで簡単に取り込んだり、ユーザーに視覚的に提示したりできるように、構造化された形式でレシピを生成する必要があります。次の例では、制御生成を使ってコース料理の一連のレシピを生成する方法を示しています。

from vertexai.generative_models import GenerationConfig, GenerativeModel
vertexai.init(project=project_id, location="us-central1")
 
response_schema = {
    "type": "array",
    "items": {
        "type": "object",
        "properties": {
            "course": {
                "type": "string",
                "enum": [
                    "appetizer",
                    "salad",
                    "soup",
                    "main",
                    "dessert",
                ],
            },
            "name": {
                "type": "string",
            },
            "ingredients": {
                "type": "array",
                "items": {
                    "type": "object",
                    "properties": {
                        "unit": {
                            "type": "string",
                            "enum": [
                                "count",
                                "cup",
                                "tablespoon",
                                "teaspoon",
                                "pound",
                                "ounce",
                            ],
                        },
                        "amount": {
                            "type": "number",
                        },
                        "name": {
                            "type": "string",
                        },
                    },
                    "required": ["name"],
                },
            },
            "steps": {
                "type": "array",
                "items": {
                    "type": "string",
                },
            },
        },
        "required": ["course", "name"],
    },
}
 
prompt = (
    "Some friends are in town and I want to host them for dinner.  "
    "Can you plan a three-course meal for me?  "
    "I'm not an experienced cook so I need simple recipes."
)
 
model = GenerativeModel("gemini-1.5-pro-001")
 
response = model.generate_content(
    prompt,
    generation_config=GenerationConfig(
        response_mime_type="application/json",
        response_schema=response_schema
    ),
)

モデルは、実際にリクエスト本体で指定されたスキーマに準拠し、アプリケーションで直接利用できる形で出力を生成します。

[
    {
        "course": "appetizer",
        "name": "Caprese Skewers",
        "ingredients": [
            {
                "name": "cherry tomatoes",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "fresh mozzarella balls",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "fresh basil leaves",
                "amount": 12,
                "unit": "count"
            },
            {
                "name": "olive oil",
                "amount": 2,
                "unit": "tablespoon"
            },
            {
                "name": "balsamic glaze",
                "amount": 2,
                "unit": "tablespoon"
            },
            {
                "name": "salt",
                "amount": 1,
                "unit": "teaspoon"
            },
            {
                "name": "black pepper",
                "amount": 1,
                "unit": "teaspoon"
            }
        ],
        "steps": [
            "Thread cherry tomatoes, mozzarella balls, and basil leaves onto skewers.",
            "Drizzle with olive oil and balsamic glaze.",
            "Season with salt and pepper to taste."
        ]
    },
    {
        "course": "main",
        "name": "One-Pan Lemon Herb Salmon",
        "ingredients": [
            {
                "name": "salmon fillets",
                "amount": 4,
                "unit": "count"
            },
            {
                "name": "asparagus",
                "amount": 1,
                "unit": "pound"
            },
            {
                "name": "cherry tomatoes",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "lemon",
                "amount": 1,
                "unit": "count"
            },
            {
                "name": "dried oregano",
                "amount": 1,
                "unit": "teaspoon"
            },
            {
                "name": "dried thyme",
                "amount": 1,
                "unit": "teaspoon"
            },
            {
                "name": "salt",
                "amount": 1,
                "unit": "teaspoon"
            },
            {
                "name": "black pepper",
                "amount": 1,
                "unit": "teaspoon"
            },
            {
                "name": "olive oil",
                "amount": 2,
                "unit": "tablespoon"
            }
        ],
        "steps": [
            "Preheat oven to 400 degrees F (200 degrees C).",
            "Line a baking sheet with parchment paper.",
            "Place salmon fillets on one side of the baking sheet and spread asparagus and cherry tomatoes on the other side.",
            "Squeeze lemon juice over the salmon and vegetables.",
            "Sprinkle with oregano, thyme, salt, and pepper.",
            "Drizzle with olive oil.",
            "Bake for 15-20 minutes, or until salmon is cooked through and vegetables are tender."
        ]
    },
    {
        "course": "dessert",
        "name": "Fruit Salad with Honey Yogurt",
        "ingredients": [
            {
                "name": "strawberries",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "blueberries",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "raspberries",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "greek yogurt",
                "amount": 1,
                "unit": "cup"
            },
            {
                "name": "honey",
                "amount": 2,
                "unit": "tablespoon"
            }
        ],
        "steps": [
            "In a large bowl, combine strawberries, blueberries, and raspberries.",
            "In a separate bowl, mix together greek yogurt and honey.",
            "Serve fruit salad with a dollop of honey yogurt."
        ]
    }
]

列挙型スキーマを使ってプロダクトの状態を分類する

モデルの出力に制約をかけ、あらかじめ定義された一連の値に制限するには、「text/x.enum」を使います。

import vertexai
from vertexai.generative_models import GenerationConfig, GenerativeModel
 
vertexai.init(project=project_id, location="us-central1")
model = GenerativeModel("gemini-1.5-flash-001")
 
response_schema = {
     "type": "STRING",
     "enum": ["new in package", "like new", "gently used", "used", "damaged", "soiled"]
}
 
prompt = [
     "Item description: The item is a long winter coat that has many tears all around the seams and is falling apart. It has large questionable stains on it."
]
 
 
response = model.generate_content(
     prompt,
     generation_config=GenerationConfig(
         response_mime_type="text/x.enum", response_schema=response_schema
     ),
)
print(response.candidates[0])

モデルの出力には、「damaged」(損傷)という簡単なプロダクトの分類が含まれています。

content {
  role: "model"
  parts {
    text: "damaged"
  }
}

制限事項

  • 制御生成は、OpenAPI 3.0 スキーマのサブセットをサポートします。

  • 出力内容がモデルの推論と抽出能力に依存する点は変わりません。制御生成を使うと、出力形式は強制されますが、実際の応答が強制されるわけではありません

  • 制御生成でプロンプトの必須フィールド情報が不十分である場合、トレーニング データに基づく応答が出力される場合があります。フィールドで nullable を True に設定すると、この制限を緩和できます。


まとめ

制御生成は堅牢なツールであり、定義済みのスキーマに準拠した応答を生成できます。さまざまな既存ワークフローに適用し、信頼性と予測性を高めることができます。私たちは、デベロッパーが使いやすい API 機能を提供し、モデルの動作を制御しやすくする取り組みを進めています。制御生成はその始まりに過ぎません。

この機能を使ってみたい方は、Google AI StudioVertex AI のドキュメント ページで詳細をご覧ください。