ai.google.dev で表示 | Google Colab で実行 | GitHub でソースを表示 |
Gemini モデルに関数の説明を提供できます。クエリを処理できるよう、関数を呼び出して結果を送り返すよう、モデルから求められる場合があります。
設定
Python SDK をインストールする
Gemini API 用の Python SDK は、google-generativeai
パッケージに含まれています。pip を使用して依存関係をインストールします。
pip install -U -q google-generativeai
パッケージをインポートする
必要なパッケージをインポートします。
import pathlib
import textwrap
import time
import google.generativeai as genai
from IPython import display
from IPython.display import Markdown
def to_markdown(text):
text = text.replace('•', ' *')
return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
API キーを設定する
Gemini API を使用するには、まず API キーを取得する必要があります。まだ作成していない場合は、Google AI Studio でワンクリックでキーを作成できます。
Colab で、左側のパネルにある [↘] の下にあるシークレット マネージャーにキーを追加します。API_KEY
という名前を付けます。
API キーを取得したら、SDK に渡します。作成する方法は次の 2 つです。
- キーを
GOOGLE_API_KEY
環境変数に設定します(SDK は自動的にそこからキーを取得します)。 - 鍵を
genai.configure(api_key=...)
に渡す
try:
# Used to securely store your API key
from google.colab import userdata
# Or use `os.getenv('API_KEY')` to fetch an environment variable.
GOOGLE_API_KEY=userdata.get('GOOGLE_API_KEY')
except ImportError:
import os
GOOGLE_API_KEY = os.environ['GOOGLE_API_KEY']
genai.configure(api_key=GOOGLE_API_KEY)
関数の基本
genai.GenerativeModel
を作成するときに、tools
引数に関数のリストを渡すことができます。
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.0-pro',
tools=[multiply])
model
genai.GenerativeModel( model_name='models/gemini-1.0-pro', generation_config={}, safety_settings={}, tools=<google.generativeai.types.content_types.FunctionLibrary object at 0x10e73fe90>, )
関数呼び出しのおすすめの方法は、チャット インターフェースを使用することです。主な理由は、FunctionCalls
がチャットのマルチターン構造にうまく適合するためです。
chat = model.start_chat(enable_automatic_function_calling=True)
自動関数呼び出しを有効にすると、chat.send_message
はモデルから要求された場合に自動的に関数を呼び出します。
単に正解を含むテキスト レスポンスを返すように見えます。
response = chat.send_message('I have 57 cats, each owns 44 mittens, how many mittens is that in total?')
response.text
'The total number of mittens is 2508.'
57*44
2508
ChatSession.history
を見ると、一連のイベントを確認できます。
- 質問を送信しました。
- モデルは
glm.FunctionCall
で応答しました。 genai.ChatSession
は関数をローカルで実行し、モデルにglm.FunctionResponse
を返しました。- モデルは回答に関数の出力を使用しました。
for content in chat.history:
part = content.parts[0]
print(content.role, "->", type(part).to_dict(part))
print('-'*80)
user -> {'text': 'I have 57 cats, each owns 44 mittens, how many mittens is that in total?'} -------------------------------------------------------------------------------- model -> {'function_call': {'name': 'multiply', 'args': {'a': 57.0, 'b': 44.0} } } -------------------------------------------------------------------------------- user -> {'function_response': {'name': 'multiply', 'response': {'result': 2508.0} } } -------------------------------------------------------------------------------- model -> {'text': 'The total number of mittens is 2508.'} --------------------------------------------------------------------------------
一般に、状態図は次のようになります。
このモデルは、テキストのレスポンスを返す前に複数の関数呼び出しで応答できます。また、関数呼び出しはテキスト レスポンスの前に来ます。
この処理はすべて自動的に行われますが、より詳細に管理する必要がある場合は、次の方法があります。
- デフォルトの
enable_automatic_function_calling=False
のままにして、glm.FunctionCall
レスポンスを自分で処理します。 - または、
GenerativeModel.generate_content
を使用します。この場合、チャットの履歴の管理も必要になります。
[省略可] 低レベルのアクセス権
Python 関数からのスキーマの自動抽出は、すべての場合で機能しない場合があります。たとえば、ネストされた辞書オブジェクトのフィールドを記述するケースは処理されませんが、API はこれをサポートしています。この API では、次のタイプのいずれかを記述できます。
AllowedType = (int | float | bool | str | list['AllowedType'] | dict[str, AllowedType]
google.ai.generativelanguage
クライアント ライブラリを使用すると、低レベルのタイプにアクセスして、すべてを管理できます。
import google.ai.generativelanguage as glm
まず、モデルの _tools
属性の内部を見ると、モデルに渡した関数がどのように記述されているかを確認できます。
def multiply(a:float, b:float):
"""returns a * b."""
return a*b
model = genai.GenerativeModel(model_name='gemini-1.0-pro',
tools=[multiply])
model._tools.to_proto()
[function_declarations { name: "multiply" description: "returns a * b." parameters { type_: OBJECT properties { key: "b" value { type_: NUMBER } } properties { key: "a" value { type_: NUMBER } } required: "a" required: "b" } }]
API に送信される glm.Tool
オブジェクトのリストが返されます。印刷形式に馴染みがないのは、これらが Google の protobuf クラスだからです。各 glm.Tool
(この場合は 1)には、関数とその引数を記述する glm.FunctionDeclarations
のリストが含まれます。
以下に、glm
クラスを使用して記述した同じ乗算関数の宣言を示します。
これらのクラスは API の関数を記述するだけで、関数の実装は含まれていません。そのため、これを使用しても自動関数呼び出しでは機能しませんが、関数には常に実装が必要になるとは限りません。
calculator = glm.Tool(
function_declarations=[
glm.FunctionDeclaration(
name='multiply',
description="Returns the product of two numbers.",
parameters=glm.Schema(
type=glm.Type.OBJECT,
properties={
'a':glm.Schema(type=glm.Type.NUMBER),
'b':glm.Schema(type=glm.Type.NUMBER)
},
required=['a','b']
)
)
])
同様に、これは JSON 互換オブジェクトとして記述できます。
calculator = {'function_declarations': [
{'name': 'multiply',
'description': 'Returns the product of two numbers.',
'parameters': {'type_': 'OBJECT',
'properties': {
'a': {'type_': 'NUMBER'},
'b': {'type_': 'NUMBER'} },
'required': ['a', 'b']} }]}
glm.Tool(calculator)
function_declarations { name: "multiply" description: "Returns the product of two numbers." parameters { type_: OBJECT properties { key: "b" value { type_: NUMBER } } properties { key: "a" value { type_: NUMBER } } required: "a" required: "b" } }
どちらの場合も、glm.Tool
またはツールのリストの表現を
model = genai.GenerativeModel('gemini-pro', tools=calculator)
chat = model.start_chat()
response = chat.send_message(
f"What's 234551 X 325552 ?",
)
前の例と同様に、モデルは計算機の multiply
関数を呼び出す glm.FunctionCall
を返します。
response.candidates
[index: 0 content { parts { function_call { name: "multiply" args { fields { key: "b" value { number_value: 325552 } } fields { key: "a" value { number_value: 234551 } } } } } role: "model" } finish_reason: STOP ]
自分で関数を実行します。
fc = response.candidates[0].content.parts[0].function_call
assert fc.name == 'multiply'
result = fc.args['a'] * fc.args['b']
result
76358547152.0
結果をモデルに送信して、会話を続けます。
response = chat.send_message(
glm.Content(
parts=[glm.Part(
function_response = glm.FunctionResponse(
name='multiply',
response={'result': result}))]))
まとめ
基本的な関数呼び出しは SDK でサポートされています。チャット モードを使用すると、やり取りが自然に行われるので管理しやすくなります。実際に関数を呼び出して結果をモデルに送り返し、テキスト レスポンスを生成する必要があります。