📘
【Azure】- Azure AI Agent Serviceでマルチエージェント実装
執筆日
2025/4/8
やること
Azure AI Agent Seriviceを使ってマルチエージェントを作ってみる。
AIエージェントに大阪の観光名所を決めてもらいます。
好きやねん!Azureで発表した内容です。
エージェントの構成図
Parallelizationをイメージしています
Azure AI Agent Serviceのセットアップについて
- 以下の手順でAzure AI Agent Serviceのプロジェクトを構築
- 以下の手順でOpenWeatherのAPIを取得
- 以下のドキュメントをFile Searchエージェントに使っています
code
import os
import json
from typing import Any, List
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import FunctionTool, FileSearchTool, FilePurpose, ToolSet
from azure.identity import DefaultAzureCredential
import requests
import math
PROJECT_CONN_STR = "Azure AI Agent Serviceのプロジェクト接続キー"
DEFAULT_MODEL_NAME = "モデル名"
FILE_PATH = "ファイルパス"
OPEN_WEATHER_API_KEY = "OpenWeatherのAPIキー"
def init_project_client(conn_str: str) -> AIProjectClient:
credential = DefaultAzureCredential()
return AIProjectClient.from_connection_string(credential=credential, conn_str=conn_str)
def create_agent(
client: AIProjectClient,
model: str,
name: str,
instructions: str,
tools: List[Any] = None,
tool_resources: dict = None,
toolset: Any = None,
headers: dict = None
):
if toolset is not None:
agent = client.agents.create_agent(
model=model,
name=name,
instructions=instructions,
toolset=toolset,
headers=headers
)
else:
agent = client.agents.create_agent(
model=model,
name=name,
instructions=instructions,
tools=tools,
tool_resources=tool_resources,
headers=headers
)
print(f"{name} created, ID: {agent.id}")
return agent
def send_message_and_get_response(client: AIProjectClient, agent_id: str, query: str, headers: dict = None) -> dict:
thread = client.agents.create_thread()
client.agents.create_message(thread_id=thread.id, role="user", content=query)
run = client.agents.create_and_process_run(thread_id=thread.id, agent_id=agent_id, headers=headers)
if run.status == "failed":
error_info = run.last_error if hasattr(run, "last_error") else "unknown error"
client.agents.delete_thread(thread.id)
return {"error": f"Agent {agent_id} failed: {error_info}"}
messages = client.agents.list_messages(thread_id=thread.id)
client.agents.delete_thread(thread.id)
responses = []
if messages.get("data"):
for message in messages["data"]:
if message["role"] != "user":
for content in message.get("content", []):
if content.get("type") == "text":
responses.append(content["text"]["value"])
return {"response": "\n".join(responses)}
def extract_response(client: AIProjectClient, thread_id: str) -> str:
messages = client.agents.list_messages(thread_id=thread_id)
responses = []
if messages.get("data"):
for msg in messages["data"]:
if msg["role"] != "user":
for content in msg.get("content", []):
if content.get("type") == "text":
responses.append(content["text"]["value"])
return "\n".join(responses)
# 天気予報を取得するAPI
def get_current_weather(city_name: str) -> str:
geocoding_response = requests.get(
"http://api.openweathermap.org/geo/1.0/direct",
params={
"q": f"{city_name},jp",
"limit": 1,
"appid": OPEN_WEATHER_API_KEY
}
)
geocodings = geocoding_response.json()
if not geocodings:
return json.dumps({"error": "Geocoding data not found"})
geocoding = geocodings[0]
lat, lon = geocoding["lat"], geocoding["lon"]
current_weather_response = requests.get(
"https://api.openweathermap.org/data/2.5/weather",
params={
"lat": lat,
"lon": lon,
"units": "metric",
"lang": "ja",
"appid": OPEN_WEATHER_API_KEY
}
)
current_weather = current_weather_response.json()
result = {
"city_name": city_name,
"description": current_weather["weather"][0]["description"],
"temperature": math.floor(current_weather["main"]["temp"])
}
return json.dumps(result)
user_functions = {get_current_weather}
def main():
client = init_project_client(PROJECT_CONN_STR)
# 各エージェントの作成(UniqueAgent、CostEffectiveAgent、FileSearchAgent、FunctionCallingAgent)
unique_agent = create_agent(
client,
model=DEFAULT_MODEL_NAME,
name="UniqueAgent",
instructions="あなたはユニークな視点で観光情報を提供するアシスタントです。大阪の観光地を個性的に紹介してください。"
)
cost_agent = create_agent(
client,
model=DEFAULT_MODEL_NAME,
name="CostEffectiveAgent",
instructions="あなたはコスパ重視で観光情報を提供するアシスタントです。お手頃な大阪の観光地を紹介してください。"
)
uploaded_file = client.agents.upload_file_and_poll(file_path=FILE_PATH, purpose=FilePurpose.AGENTS)
print(f"Uploaded file, file ID: {uploaded_file.id}")
vector_store = client.agents.create_vector_store_and_poll(file_ids=[uploaded_file.id], name="tourism_vectorstore")
print(f"Created vector store, vector store ID: {vector_store.id}")
file_search_tool = FileSearchTool(vector_store_ids=[vector_store.id])
file_search_agent = create_agent(
client,
model=DEFAULT_MODEL_NAME,
name="FileSearchAgent",
instructions="あなたはアップロードされた観光情報ファイルから情報を検索して回答するアシスタントです。",
tools=file_search_tool.definitions,
tool_resources=file_search_tool.resources,
headers={"x-ms-enable-preview": "true"}
)
function_tool = FunctionTool(user_functions)
fc_toolset = ToolSet()
fc_toolset.add(function_tool)
function_calling_agent = create_agent(
client,
model=DEFAULT_MODEL_NAME,
name="FunctionCallingAgent",
instructions="あなたは関数呼び出しエージェントです。ユーザー定義関数を活用して、指定された都市の天気情報を取得してください。",
toolset=fc_toolset,
headers={"x-ms-enable-preview": "true"}
)
# --- 各エージェントへの問い合わせ ---
thread_unique = client.agents.create_thread()
client.agents.create_message(thread_id=thread_unique.id, role="user", content="大阪でおすすめの観光地は何ですか?ユニークな観点で選んでください")
run_unique = client.agents.create_and_process_run(thread_id=thread_unique.id, agent_id=unique_agent.id)
response_unique = extract_response(client, thread_unique.id)
print("UniqueAgent response:\n", response_unique)
client.agents.delete_thread(thread_unique.id)
thread_cost = client.agents.create_thread()
client.agents.create_message(thread_id=thread_cost.id, role="user", content="大阪でおすすめの観光地は何ですか?コスパ重視で選んでください")
run_cost = client.agents.create_and_process_run(thread_id=thread_cost.id, agent_id=cost_agent.id)
response_cost = extract_response(client, thread_cost.id)
print("CostEffectiveAgent response:\n", response_cost)
client.agents.delete_thread(thread_cost.id)
thread_fs = client.agents.create_thread()
client.agents.create_message(thread_id=thread_fs.id, role="user", content="このファイルから大阪に関連する情報を教えてください。")
run_fs = client.agents.create_and_process_run(thread_id=thread_fs.id, agent_id=file_search_agent.id, headers={"x-ms-enable-preview": "true"})
response_fs = extract_response(client, thread_fs.id)
print("FileSearchAgent response:\n", response_fs)
client.agents.delete_thread(thread_fs.id)
thread_fc = client.agents.create_thread()
client.agents.create_message(thread_id=thread_fc.id, role="user", content="大阪の天気はどうですか?")
run_fc = client.agents.create_and_process_run(thread_id=thread_fc.id, agent_id=function_calling_agent.id, headers={"x-ms-enable-preview": "true"})
response_fc = extract_response(client, thread_fc.id)
print("FunctionCallingAgent response:\n", response_fc)
client.agents.delete_thread(thread_fc.id)
aggregator_query = (
"以下は4つのエージェントの回答です。\n"
"【UniqueAgent】\n" + response_unique + "\n\n"
"【CostEffectiveAgent】\n" + response_cost + "\n\n"
"【FileSearchAgent】\n" + response_fs + "\n\n"
"【FunctionCallingAgent】\n" + response_fc + "\n\n"
"これらの情報を元に、大阪で今日観光するのにおすすめの観光地を1つだけ挙げ、その理由を簡潔に教えてください。"
)
aggregator_agent = create_agent(
client,
model=DEFAULT_MODEL_NAME,
name="AggregatorAgent",
instructions="あなたは各エージェントの回答を統合し、大阪でおすすめの観光地を1つ挙げ、その理由を簡潔に説明するアシスタントです。"
)
thread_aggr = client.agents.create_thread()
client.agents.create_message(thread_id=thread_aggr.id, role="user", content=aggregator_query)
run_aggr = client.agents.create_and_process_run(thread_id=thread_aggr.id, agent_id=aggregator_agent.id)
response_aggr = extract_response(client, thread_aggr.id)
print("AggregatorAgent response:\n", response_aggr)
if __name__ == "__main__":
main()
出力結果
UniqueAgent created, ID: asst_zKiYF7vYOUcKjEvQqL0dsdO6
CostEffectiveAgent created, ID: asst_5ic6ekUOW125tmTJQ02hqM5I
Uploaded file, file ID: assistant-4LpPQ997R2fmyueoVNnNef
Created vector store, vector store ID: vs_mxQxE9ZE5p3Y5lpnUnnU9TWf
FileSearchAgent created, ID: asst_LA6fjDoO3KDUUbMmc4OXCDEh
FunctionCallingAgent created, ID: asst_yPrvijZGihF5OvNifJSObVLm
UniqueAgent response:
もちろんです!大阪にはさまざまな観光地がありますが、ちょっとユニークな視点でいくつか選んでご紹介します。
### 1. **あべのハルカス**
ただの高層ビルではありません!日本一高いビルの展望台からの眺めは、まるで映画のセットの ようです。特に夕暮れ時に見る大阪の街並みは、まるで光の海が広がっているよう。実は、ここ には「天空の桃源郷」と呼ばれる特別なスイーツビュッフェもあるんです。一口で空に浮いてい るような気分にさせてくれる、最高の甘さです。
### 2. **黒門市場**
大阪の食文化が凝縮された場所ですが、実は「食の宝庫」としてだけではなく、ここで出会える 人々の個性も魅力の一つ。市場内にはユニークなアイデアを持った店主が多く、彼らとの会話に は食材の歴史や料理の秘密が隠されています。食べ物だけでなく、人との交流を楽しむ“フードツアー”としても訪れる価値があります。
### 3. **通天閣**
大阪のシンボルともいえる通天閣ですが、観光の合間に「新世界」を探索する楽しさがあります 。ここでは、おいしい串カツのお店が立ち並ぶだけではなく、懐かしい雰囲気を楽しむことがで きます。特に、通天閣の近くには昭和レトロなゲームセンターがたくさんあり、思わず時間を忘 れること間違いなし!
### 4. **日本橋の電気街**
秋葉原とは一味違う、大阪のオタク文化を体感できるスポット。ここでは、マニアックな店が軒 を連ね、最新のガジェットからレトロなアニメグッズまで何でも揃っています。ただのショッピ ングで終わらず、店員さんとの会話や、他の買い物客のリアクションを観察することで、大阪の オタク社会の深淵に触れることができます。
### 5. **道頓堀**
食べ歩きや観光の定番ですが、ここでは「個性派看板」も見逃せません!たこ焼き屋やラーメン 店など、各店の看板が個性的で、まるでアートギャラリーのような競演が繰り広げられています 。特にグリコの看板は写真スポットとしても有名ですが、その周りにいる観光客のカラフルなフ ァッションも、ひとつのアートといえるでしょう。
このように、大阪には魅力的な観光地がたくさんあります。それぞれの場所を訪れることで、大 阪の独特の文化や人々との出会いを楽しんでください!
CostEffectiveAgent response:
大阪にはコストパフォーマンスが高い観光地がたくさんあります!以下は、お手頃な価格で楽しめるおすすめの観光スポットです。
1. **大阪城公園**
入場無料の公園で、歴史ある大阪城を眺めながら散策できます。桜の季節や紅葉の季節も美しいです。
2. **道頓堀**
大阪の代表的な観光エリアで、グリコの看板やカニ道楽の大きなカニが印象的です。散策するだけでも楽しめますし、安い屋台やカフェも多いです。
3. **心斎橋筋商店街**
長いアーケード街で、ショッピングや食べ歩きが楽しめます。リーズナブルな価格の飲食店も多く、観光客にも人気です。
4. **通天閣**
入場料は必要ですが、リーズナブルな価格で大阪のシンボル的な塔からの眺望が堪能できます。周辺の新世界エリアも雰囲気があります。
5. **天保山マーケットプレース**
海の近くにあり、展望台や水族館があるエリアで、無料で楽しめるオープンスペースや観覧車もあります。
6. **四天王寺**
大阪の歴史的な寺院で、入場が無料のエリアがあり、静かな雰囲気に浸りながら散策できます。
7. **アメリカ村**
おしゃれなショップやカフェが立ち並ぶエリアで、ストリートアートや独特な雰囲気を楽しめます。お財布に優しいスナックもたくさんあります。
これらのスポットは、入場料がかかるところもありますが、全体的にコストパフォーマンスが良 く、楽しい体験ができる場所です。お楽しみください!
FileSearchAgent response:
大阪に関連する観光情報は以下の通りです。
1. **梅田スカイビル(空中庭園展望台)**:
- 大阪・梅田のランドマーク的展望施設で、屋上の「空中庭園展望台」は観光客に人気です【4:0†source】。
2. **グランフロント大阪**:
- JR大阪駅直結の大型複合施設で、ショップ、オフィス、ホテルが集結しています【4:0†source】。
3. **大阪市中央公会堂**:
- 美しいネオ・ルネッサンス様式の外観を持つ集会施設で、コンサートや講演会を多数開催しています【4:0†source】。
4. **難波八阪神社**:
- 大阪最古の神社で、日本列島そのものの神である生島大神・足島大神を祀っています【4:13†source】。
5. **道頓堀**:
- 人気の観光スポットであり、ネオンの美しい水辺の遊歩道はイベントも開催されています【4:13†source】。
6. **黒門市場**:
- 「大阪の台所」として知られ、地元の人々と観光客で賑わいます【4:14†source】。
7. **ユニバーサル・スタジオ・ジャパン**:
- 日本を代表するテーマパークで、多彩なアトラクションが魅力です【4:15†source】。
8. **大阪城**:
- 豊臣秀吉が築城した歴史的な城で、現在の天守閣は1931年に再建されています【4:9†source】。
これらの場所は大阪の多様な魅力を体験するためのおすすめスポットです。観光の際にはぜひ訪 れてみてください。
FunctionCallingAgent response:
大阪の天気は晴れで、気温は14℃です。
AggregatorAgent created, ID: asst_Sp3szvk5Gno86RGRu17Pa4XZ
AggregatorAgent response:
**道頓堀**をおすすめします。理由は、大阪の食文化やエンターテイメントが体験できる場所であり、賑やかな雰囲気の中でたこ焼きや串カツなどの名物を楽しむことができるからです。さら に、グリコの看板など観光名所が多く、訪れるだけで大阪の魅力を堪能できます。
まとめ
Azure AI Agent Serviceを使ったマルチエージェント開発をしました。
サクッと開発できるのでお勧めです。
最近Fabricがナレッジに追加できるようになったので、次はFabricを使ったマルチエージェントを開発しようかなと思います。
Discussion