(上の画像をクリックすると、このレッスンの動画をご覧いただけます)
ツールは、AIエージェントに幅広い能力を与えるため、非常に興味深い存在です。エージェントが実行できるアクションが限られている代わりに、ツールを追加することで、エージェントは多様なアクションを実行できるようになります。この章では、ツール利用デザインパターンについて学び、AIエージェントが特定のツールを使用して目標を達成する方法を説明します。
このレッスンでは、以下の質問に答えることを目指します:
このレッスンを完了すると、以下ができるようになります:
ツール利用デザインパターンは、LLMが外部ツールと連携して特定の目標を達成する能力を与えることに焦点を当てています。ツールとは、エージェントがアクションを実行するために使用できるコードのことです。ツールは、電卓のような単純な関数や、株価検索や天気予報などのサードパーティサービスへのAPI呼び出しなどがあります。AIエージェントの文脈では、ツールはモデル生成関数呼び出しに応じてエージェントによって実行されるように設計されています。
AIエージェントはツールを活用して複雑なタスクを完了したり、情報を取得したり、意思決定を行ったりすることができます。ツール利用デザインパターンは、データベース、Webサービス、コードインタープリターなどの外部システムとの動的なやり取りが必要なシナリオでよく使用されます。この能力は、以下のようなさまざまなユースケースに役立ちます:
これらの構成要素により、AIエージェントは幅広いタスクを実行できるようになります。ツール利用デザインパターンを実装するために必要な主要な要素を見てみましょう:
次に、関数/ツール呼び出しについて詳しく見ていきましょう。
関数呼び出しは、LLMがツールと連携するための主要な方法です。「関数」と「ツール」はしばしば同義で使用されます。なぜなら、「関数」(再利用可能なコードのブロック)がエージェントがタスクを実行するために使用する「ツール」だからです。関数のコードを呼び出すためには、LLMがユーザーのリクエストを関数の説明と比較する必要があります。このため、利用可能なすべての関数の説明を含むスキーマがLLMに送信されます。LLMはタスクに最も適した関数を選択し、その名前と引数を返します。選択された関数が呼び出され、その応答がLLMに送られ、ユーザーのリクエストに応答するために使用されます。
エージェントの関数呼び出しを実装するために、開発者が必要とするもの:
サンフランシスコの現在時刻を取得する例を使って説明します:
関数呼び出しをサポートするLLMを初期化する:
すべてのモデルが関数呼び出しをサポートしているわけではないため、使用しているLLMが対応しているか確認することが重要です。Azure OpenAIは関数呼び出しをサポートしています。Azure OpenAIクライアントを初期化することから始めます。
# Initialize the Azure OpenAI client
client = AzureOpenAI(
azure_endpoint = os.getenv("AZURE_OPENAI_ENDPOINT"),
api_key=os.getenv("AZURE_OPENAI_API_KEY"),
api_version="2024-05-01-preview"
)
関数スキーマを作成する:
次に、関数名、関数の目的、関数パラメータの名前と説明を含むJSONスキーマを定義します。このスキーマを、サンフランシスコの時刻を見つけるためのユーザーリクエストとともに、先ほど作成したクライアントに渡します。重要なのは、ツール呼び出しが返されることであり、質問への最終的な答えではないことです。前述のように、LLMはタスクに選択した関数の名前と渡される引数を返します。
# Function description for the model to read
tools = [
{
"type": "function",
"function": {
"name": "get_current_time",
"description": "Get the current time in a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "The city name, e.g. San Francisco",
},
},
"required": ["location"],
},
}
}
]
# Initial user message
messages = [{"role": "user", "content": "What's the current time in San Francisco"}]
# First API call: Ask the model to use the function
response = client.chat.completions.create(
model=deployment_name,
messages=messages,
tools=tools,
tool_choice="auto",
)
# Process the model's response
response_message = response.choices[0].message
messages.append(response_message)
print("Model's response:")
print(response_message)
Model's response:
ChatCompletionMessage(content=None, role='assistant', function_call=None, tool_calls=[ChatCompletionMessageToolCall(id='call_pOsKdUlqvdyttYB67MOj434b', function=Function(arguments='{"location":"San Francisco"}', name='get_current_time'), type='function')])
タスクを実行するために必要な関数コード:
LLMが実行する必要がある関数を選択した後、タスクを実行するコードを実装して実行する必要があります。Pythonで現在時刻を取得するコードを実装できます。また、response_messageから名前と引数を抽出して最終結果を取得するコードも記述する必要があります。
def get_current_time(location):
"""Get the current time for a given location"""
print(f"get_current_time called with location: {location}")
location_lower = location.lower()
for key, timezone in TIMEZONE_DATA.items():
if key in location_lower:
print(f"Timezone found for {key}")
current_time = datetime.now(ZoneInfo(timezone)).strftime("%I:%M %p")
return json.dumps({
"location": location,
"current_time": current_time
})
print(f"No timezone data found for {location_lower}")
return json.dumps({"location": location, "current_time": "unknown"})
# Handle function calls
if response_message.tool_calls:
for tool_call in response_message.tool_calls:
if tool_call.function.name == "get_current_time":
function_args = json.loads(tool_call.function.arguments)
time_response = get_current_time(
location=function_args.get("location")
)
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": "get_current_time",
"content": time_response,
})
else:
print("No tool calls were made by the model.")
# Second API call: Get the final response from the model
final_response = client.chat.completions.create(
model=deployment_name,
messages=messages,
)
return final_response.choices[0].message.content
get_current_time called with location: San Francisco
Timezone found for san francisco
The current time in San Francisco is 09:24 AM.
関数呼び出しは、ほとんどすべてのエージェントツール利用設計の中心にありますが、ゼロから実装するのは時に困難です。レッスン2で学んだように、エージェントフレームワークはツール利用を実装するための事前構築された構成要素を提供してくれます。
以下は、異なるエージェントフレームワークを使用してツール利用デザインパターンを実装する方法の例です:
Semantic Kernelは、LLMを使用する.NET、Python、Java開発者向けのオープンソースAIフレームワークです。関数呼び出しを簡素化し、関数とそのパラメータをモデルに自動的に説明するシリアル化プロセスを通じて実現します。また、モデルとコード間のやり取りを処理します。Semantic Kernelのようなエージェントフレームワークを使用するもう一つの利点は、ファイル検索やコードインタープリターなどの事前構築されたツールにアクセスできることです。
以下の図は、Semantic Kernelを使用した関数呼び出しのプロセスを示しています:
Semantic Kernelでは、関数/ツールはプラグインと呼ばれます。先ほど見たget_current_time
関数をクラスに変換し、その中に関数を含めることでプラグインに変換できます。また、関数の説明を受け取るkernel_function
デコレーターをインポートすることができます。その後、GetCurrentTimePluginを使用してカーネルを作成すると、カーネルは関数とそのパラメータを自動的にシリアル化し、スキーマを作成してLLMに送信します。
from semantic_kernel.functions import kernel_function
class GetCurrentTimePlugin:
async def __init__(self, location):
self.location = location
@kernel_function(
description="Get the current time for a given location"
)
def get_current_time(location: str = ""):
...
from semantic_kernel import Kernel
# Create the kernel
kernel = Kernel()
# Create the plugin
get_current_time_plugin = GetCurrentTimePlugin(location)
# Add the plugin to the kernel
kernel.add_plugin(get_current_time_plugin)
Azure AI Agent Serviceは、開発者が高品質で拡張性のあるAIエージェントを安全に構築、展開、スケールできるように設計された新しいエージェントフレームワークです。基盤となるコンピュートやストレージリソースを管理する必要がないため、特にエンタープライズアプリケーションに役立ちます。完全に管理されたサービスであり、エンタープライズグレードのセキュリティを備えています。
LLM APIを直接使用して開発する場合と比較して、Azure AI Agent Serviceは以下の利点を提供します:
Azure AI Agent Serviceで利用可能なツールは、以下の2つのカテゴリに分けられます:
Agent Serviceを使用すると、これらのツールをtoolset
として一緒に使用できます。また、特定の会話のメッセージ履歴を追跡するthreads
を利用します。
例えば、Contosoという会社の営業担当者であると仮定します。営業データに関する質問に答える会話型エージェントを開発したいとします。
以下の画像は、Azure AI Agent Serviceを使用して営業データを分析する方法を示しています:
このサービスでツールを使用するには、クライアントを作成し、ツールまたはツールセットを定義します。これを実際に実装するには、以下のPythonコードを使用できます。LLMはツールセットを確認し、ユーザーが作成した関数fetch_sales_data_using_sqlite_query
を使用するか、事前構築されたコードインタープリターを使用するかをユーザーリクエストに応じて判断します。
import os
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
from fetch_sales_data_functions import fetch_sales_data_using_sqlite_query # fetch_sales_data_using_sqlite_query function which can be found in a fetch_sales_data_functions.py file.
from azure.ai.projects.models import ToolSet, FunctionTool, CodeInterpreterTool
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(),
conn_str=os.environ["PROJECT_CONNECTION_STRING"],
)
# Initialize function calling agent with the fetch_sales_data_using_sqlite_query function and adding it to the toolset
fetch_data_function = FunctionTool(fetch_sales_data_using_sqlite_query)
toolset = ToolSet()
toolset.add(fetch_data_function)
# Initialize Code Interpreter tool and adding it to the toolset.
code_interpreter = code_interpreter = CodeInterpreterTool()
toolset = ToolSet()
toolset.add(code_interpreter)
agent = project_client.agents.create_agent(
model="gpt-4o-mini", name="my-agent", instructions="You are helpful agent",
toolset=toolset
)
LLMによって動的に生成されるSQLに関する一般的な懸念は、セキュリティ、特にSQLインジェクションやデータベースの削除や改ざんなどの悪意ある行動のリスクです。これらの懸念は有効ですが、データベースアクセス権限を適切に設定することで効果的に軽減できます。ほとんどのデータベースでは、データベースを読み取り専用に設定することが含まれます。PostgreSQLやAzure SQLのようなデータベースサービスでは、アプリに読み取り専用(SELECT)ロールを割り当てる必要があります。
アプリを安全な環境で実行することで、さらに保護が強化されます。エンタープライズシナリオでは、データは通常、運用システムから抽出され、読み取り専用データベースまたはデータウェア Azure AI Foundry Discordに参加して、他の学習者と交流したり、オフィスアワーに参加したり、AI Agentsに関する質問に答えてもらいましょう。
免責事項:
この文書は、AI翻訳サービス Co-op Translator を使用して翻訳されています。正確性を追求しておりますが、自動翻訳には誤りや不正確な部分が含まれる可能性があることをご承知ください。元の言語で記載された文書が正式な情報源とみなされるべきです。重要な情報については、専門の人間による翻訳を推奨します。この翻訳の使用に起因する誤解や誤解釈について、当社は責任を負いません。