Agentic RAGが気になったので、Azure AI Agent ServiceとSemantic Kernel で実装してみました。基本的に以下の内容に従っています。
私が実行したプログラムはこちら。
処理
0. 前提
Azure AI Foundryの基本的なリソースはAzure Portalから作成済です。AI Projectも作成済。その中で(gpt-4.1.-miniでやろうとしたら、プログラム上でエラー発生したので)gpt-4o-miniをデプロイ。
SQLiteがコメントアウトされてコードにありますが、特に使っていません。
環境
最初はWindowsで動かそうとしたのですが、Pythonパッケージazure-ai-projects
が古くて動かなかったので、WSLで動かしています。
種類 | バージョン | 備考 |
---|---|---|
Python(Pyenv) | 3.10.12 | 古いのに特に意味はないです。たまたますぐ使えた環境 |
Ubuntu(WSL2) | 22.04.5 LTS | WSL |
Poetry | 1.7.1 |
Python 追加パッケージ
種類 | バージョン | 備考 |
---|---|---|
azure-ai-projects | 1.0.0b10 | |
azure-ai-inference | 1.0.0b9 | |
azure-identity | 1.21.0 | |
azure-monitor-opentelemetry | 1.6.8 | トレース出力目的 |
jupyterlab | 4.4.1 | |
semantic-kernel | 1.29.0 | |
python-dotenv | 1.1.0 |
1. 事前準備
1.1. RAG用ファイル作成
ローカルファイルdocument.md
を置いておきます。このファイルがRAGで使われます。
- **Contoso Travel** offers luxury vacation packages to exotic destinations worldwide.
- Our premium travel services include personalized itinerary planning and 24/7 concierge support.
- Contoso's travel insurance covers medical emergencies, trip cancellations, and lost baggage.
- Popular destinations include the Maldives, Swiss Alps, and African safaris.
- Contoso Travel provides exclusive access to boutique hotels and private guided tours.
1.2. 環境変数設定
.env
に環境変数を設定しておきます。
AZURE_AI_AGENT_PROJECT_CONNECTION_STRING=プロジェクト接続文字列
AZURE_AI_AGENT_MODEL_DEPLOYMENT_NAME=gpt-4o-mini
AZURE_TRACING_GEN_AI_CONTENT_RECORDING_ENABLED=true
こちらの内容を参考にしています。
2. Python Script
2.1. パッケージインポート
import os
from azure.ai.projects import AIProjectClient
from azure.ai.projects.models import FileSearchTool, OpenAIFile, VectorStore
from azure.identity import DefaultAzureCredential
from azure.monitor.opentelemetry import configure_azure_monitor
from dotenv import load_dotenv
from semantic_kernel.agents import AzureAIAgent, AzureAIAgentThread
2.2. トレースON
以下を参考にトレースONにしました。単純なChatと違ってAgentは自動で処理が走るので、トレースで動きを確認します。
load_dotenv(override=True)
project_client = AIProjectClient.from_connection_string(
credential=DefaultAzureCredential(), conn_str=os.environ["AZURE_AI_AGENT_PROJECT_CONNECTION_STRING"]
)
application_insights_connection_string = project_client.telemetry.get_connection_string()
if not application_insights_connection_string:
print("Application Insights was not enabled for this project.")
print("Enable it via the 'Tracing' tab in your Azure AI Foundry project page.")
exit()
configure_azure_monitor(connection_string=application_insights_connection_string)
2.3. 主処理
主処理は大きく以下の流れ。
- Agentの作成
- ファイルアップロード
- Vector Storeの作成
- Agentの作成
- Agentの実行
- Agent削除
- Vector Storeの削除
- ファイルの削除
- Agentの削除
from azure.identity.aio import DefaultAzureCredential
async def main():
async with (
DefaultAzureCredential() as creds,
AzureAIAgent.create_client(credential=creds) as client,
):
file: OpenAIFile = await client.agents.upload_file_and_poll(file_path="document.md", purpose="assistants")
vector_store: VectorStore = await client.agents.create_vector_store_and_poll(
file_ids=[file.id], name="my_vectorstore"
)
# Define agent name and instructions tailored for RAG.
AGENT_NAME = "RAGAgent"
AGENT_INSTRUCTIONS = """
You are an AI assistant designed to answer user questions using only the information retrieved from the provided document(s).
- If a user's question cannot be answered using the retrieved context, **you must clearly respond**:
"I'm sorry, but the uploaded document does not contain the necessary information to answer that question."
- Do not answer from general knowledge or reasoning. Do not make assumptions or generate hypothetical explanations.
- Do not provide definitions, tutorials, or commentary that is not explicitly grounded in the content of the uploaded file(s).
- If a user asks a question like "What is a Neural Network?", and this is not discussed in the uploaded document, respond as instructed above.
- For questions that do have relevant content in the document (e.g., Contoso's travel insurance coverage), respond accurately, and cite the document explicitly.
You must behave as if you have no external knowledge beyond what is retrieved from the uploaded document.
"""
# Create file search tool with uploaded resources
file_search = FileSearchTool(vector_store_ids=[vector_store.id])
# 3. Create an agent on the Azure AI agent service with the file search tool
agent_definition = await client.agents.create_agent(
model="gpt-4o-mini", # This model should match your Azure OpenAI deployment.
name=AGENT_NAME,
instructions=AGENT_INSTRUCTIONS,
tools=file_search.definitions,
tool_resources=file_search.resources,
)
# Create the Azure AI Agent using the client and definition.
agent = AzureAIAgent(
client=client,
definition=agent_definition,
)
# Create a thread to hold the conversation
# If no thread is provided, a new thread will be
# created and returned with the initial response
thread: AzureAIAgentThread | None = None
# Example user queries.
user_inputs = [
"Can you explain Contoso's travel insurance coverage?", # Relevant context.
"What is a Neural Network?" # No relevant context from the document. Will not contain a source annotation.
]
try:
for user_input in user_inputs:
print(f"# User: '{user_input}'")
# Invoke the agent for the specified thread for response
async for response in agent.invoke(messages=user_input, thread=thread):
print(f"# {response.name}: {response}")
thread = response.thread
finally:
# Clean up resources.
await thread.delete() if thread else None
await client.agents.delete_vector_store(vector_store.id)
await client.agents.delete_file(file.id)
await client.agents.delete_agent(agent.id)
print("\nCleaned up agent, thread, file, and vector store.")
await main()
# User: 'Can you explain Contoso's travel insurance coverage?'
# RAGAgent: I'm sorry, but the uploaded document does not contain the necessary information to answer that question.
# User: 'What is a Neural Network?'
# RAGAgent: I'm sorry, but the uploaded document does not contain the necessary information to answer that question.
Cleaned up agent, thread, file, and vector store.
Agentの定義など
Agent 定義
Azure AI Foundryで作成されたAgentを見てみます(Agent削除処理をコメントアウトして実行)。
画面の右側に「手順」や「ナレッジ」があるのがわかります。
ちなみに、BASICエージェントの場合、ナレッジは「ファイル検索」で別途Azure AI Searchなどのリソースが作成されるわけではなく、Microsoftマネージドの検索リソースが使われるようです。Standardエージェントだと、以下の通り。
ファイル検索ツールは、利用者がエージェントのセットアップ中に接続した Azure AI 検索リソースと Azure Blob Storage リソースを使用します。
- アップロードされたファイルは、接続された Azure Blob Storage アカウント内に保存されます
- 接続された Azure AI 検索リソースを使用してベクトル ストアが作成されます
スレッド
トレース
全体的に以下のトレースが取れています。Agent作成や削除なども含んでいます。
実際にAgentをInvokeしているトーレス。outputやvector storeからの検索内容は見えないです。トレースに含める方法があるかは調べていません。