404 lines
23 KiB
Plaintext
404 lines
23 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b8c57858",
|
|
"metadata": {},
|
|
"source": [
|
|
"# ตัวแทน AI ของ Azure พร้อมการสนับสนุน Model Context Protocol (MCP) - Python\n",
|
|
"\n",
|
|
"สมุดบันทึกนี้แสดงวิธีการใช้ตัวแทน AI ของ Azure พร้อมเครื่องมือ Model Context Protocol (MCP) ใน Python โดยแสดงวิธีการสร้างตัวแทนอัจฉริยะที่สามารถใช้เซิร์ฟเวอร์ MCP ภายนอก (เช่น Microsoft Learn) เพื่อเพิ่มความสามารถโดยใช้การตรวจสอบสิทธิ์แบบไม่ใช้คีย์\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "2e6e4234",
|
|
"metadata": {},
|
|
"source": [
|
|
"## ติดตั้งแพ็กเกจ Python ที่จำเป็น\n",
|
|
"\n",
|
|
"ก่อนอื่น เราต้องติดตั้งแพ็กเกจ Python ที่จำเป็น:\n",
|
|
"- **azure-ai-projects**: SDK หลักสำหรับ Azure AI Projects\n",
|
|
"- **azure-ai-agents**: SDK สำหรับ Azure AI Agents เพื่อสร้างและจัดการเอเจนต์\n",
|
|
"- **azure-identity**: ให้การรับรองความถูกต้องแบบไม่ใช้คีย์ด้วย DefaultAzureCredential\n",
|
|
"- **mcp**: การใช้งาน Model Context Protocol สำหรับ Python\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6a2e9a05",
|
|
"metadata": {},
|
|
"source": [
|
|
"## ข้อดีของการยืนยันตัวตนแบบไม่ใช้คีย์\n",
|
|
"\n",
|
|
"สมุดบันทึกนี้แสดงตัวอย่างของ **การยืนยันตัวตนแบบไม่ใช้คีย์** ซึ่งมีข้อดีหลายประการ:\n",
|
|
"- ✅ **ไม่ต้องจัดการ API keys** - ใช้การยืนยันตัวตนตาม Azure identity\n",
|
|
"- ✅ **เพิ่มความปลอดภัย** - ไม่มีการเก็บข้อมูลลับในโค้ดหรือไฟล์การตั้งค่า\n",
|
|
"- ✅ **การหมุนเวียนข้อมูลรับรองอัตโนมัติ** - Azure จัดการวงจรชีวิตของข้อมูลรับรองให้\n",
|
|
"- ✅ **การควบคุมการเข้าถึงตามบทบาท** - ใช้ Azure RBAC เพื่อกำหนดสิทธิ์อย่างละเอียด\n",
|
|
"- ✅ **รองรับหลายสภาพแวดล้อม** - ทำงานได้อย่างราบรื่นทั้งในสภาพแวดล้อมการพัฒนาและการใช้งานจริง\n",
|
|
"\n",
|
|
"`DefaultAzureCredential` จะเลือกแหล่งข้อมูลรับรองที่เหมาะสมที่สุดโดยอัตโนมัติ:\n",
|
|
"1. **Managed Identity** (เมื่อทำงานใน Azure)\n",
|
|
"2. **ข้อมูลรับรองจาก Azure CLI** (ในระหว่างการพัฒนาในเครื่อง)\n",
|
|
"3. **ข้อมูลรับรองจาก Visual Studio**\n",
|
|
"4. **ตัวแปรสภาพแวดล้อม** (ถ้ากำหนดค่าไว้)\n",
|
|
"5. **การยืนยันตัวตนผ่านเบราว์เซอร์แบบโต้ตอบ** (เป็นตัวเลือกสำรอง)\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "43efa94d",
|
|
"metadata": {},
|
|
"source": [
|
|
"## การตั้งค่าการตรวจสอบสิทธิ์แบบไม่ใช้คีย์\n",
|
|
"\n",
|
|
"**ข้อกำหนดเบื้องต้นสำหรับการตรวจสอบสิทธิ์แบบไม่ใช้คีย์:**\n",
|
|
"\n",
|
|
"### สำหรับการพัฒนาบนเครื่อง:\n",
|
|
"```bash\n",
|
|
"# Install Azure CLI and login\n",
|
|
"az login\n",
|
|
"# Verify your identity\n",
|
|
"az account show\n",
|
|
"```\n",
|
|
"\n",
|
|
"### สำหรับสภาพแวดล้อมของ Azure:\n",
|
|
"- เปิดใช้งาน **System-assigned Managed Identity** บนทรัพยากร Azure ของคุณ\n",
|
|
"- กำหนด **RBAC roles** ที่เหมาะสมให้กับ Managed Identity:\n",
|
|
" - `Cognitive Services OpenAI User` สำหรับการเข้าถึง Azure OpenAI\n",
|
|
" - `AI Developer` สำหรับการเข้าถึงโครงการ Azure AI\n",
|
|
"\n",
|
|
"### ตัวแปรสภาพแวดล้อม (ไม่บังคับ):\n",
|
|
"```python\n",
|
|
"# These are automatically detected by DefaultAzureCredential\n",
|
|
"# AZURE_CLIENT_ID=<your-client-id>\n",
|
|
"# AZURE_CLIENT_SECRET=<your-client-secret>\n",
|
|
"# AZURE_TENANT_ID=<your-tenant-id>\n",
|
|
"```\n",
|
|
"\n",
|
|
"**ไม่ต้องใช้ API keys หรือ connection strings!** 🔐\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "2e21387d",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"! pip install azure-ai-projects -U\n",
|
|
"! pip install azure-ai-agents==1.1.0b4 -U\n",
|
|
"! pip install azure-identity -U\n",
|
|
"! pip install mcp==1.11.0 -U"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b31c8873",
|
|
"metadata": {},
|
|
"source": [
|
|
"## นำเข้าห้องสมุดที่จำเป็น\n",
|
|
"\n",
|
|
"นำเข้าโมดูล Python ที่จำเป็น:\n",
|
|
"- **os, time**: ห้องสมุดมาตรฐานของ Python สำหรับตัวแปรสภาพแวดล้อมและการหน่วงเวลา\n",
|
|
"- **AIProjectClient**: ไคลเอนต์หลักสำหรับ Azure AI Projects\n",
|
|
"- **DefaultAzureCredential**: การรับรองความถูกต้องแบบไม่ใช้กุญแจสำหรับบริการ Azure\n",
|
|
"- **MCP-related classes**: สำหรับการสร้างและจัดการเครื่องมือ MCP และการจัดการการอนุมัติ\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "43667b32",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"import os, time\n",
|
|
"from azure.ai.projects import AIProjectClient\n",
|
|
"from azure.identity import DefaultAzureCredential\n",
|
|
"from azure.ai.agents.models import McpTool, RequiredMcpToolCall, SubmitToolApprovalAction, ToolApproval\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "721355e5",
|
|
"metadata": {},
|
|
"source": [
|
|
"## กำหนดค่าการตั้งค่าเซิร์ฟเวอร์ MCP\n",
|
|
"\n",
|
|
"ตั้งค่าการกำหนดค่าเซิร์ฟเวอร์ MCP โดยใช้ตัวแปรสภาพแวดล้อมพร้อมค่าเริ่มต้นสำรอง:\n",
|
|
"- **MCP_SERVER_URL**: URL ของเซิร์ฟเวอร์ MCP (ค่าเริ่มต้นคือ Microsoft Learn API)\n",
|
|
"- **MCP_SERVER_LABEL**: ป้ายกำกับเพื่อระบุเซิร์ฟเวอร์ MCP (ค่าเริ่มต้นคือ \"mslearn\")\n",
|
|
"\n",
|
|
"วิธีนี้ช่วยให้สามารถกำหนดค่าได้อย่างยืดหยุ่นในสภาพแวดล้อมที่แตกต่างกัน\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "189f3d55",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"mcp_server_url = os.environ.get(\"MCP_SERVER_URL\", \"https://learn.microsoft.com/api/mcp\")\n",
|
|
"mcp_server_label = os.environ.get(\"MCP_SERVER_LABEL\", \"mslearn\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "20612d9a",
|
|
"metadata": {},
|
|
"source": [
|
|
"## สร้าง Azure AI Project Client (การยืนยันตัวตนแบบไม่ใช้คีย์)\n",
|
|
"\n",
|
|
"เริ่มต้นใช้งาน Azure AI Project client ด้วย **การยืนยันตัวตนแบบไม่ใช้คีย์**:\n",
|
|
"- **endpoint**: URL ของ Azure AI Foundry project endpoint\n",
|
|
"- **credential**: ใช้ `DefaultAzureCredential()` เพื่อการยืนยันตัวตนที่ปลอดภัยและไม่ต้องใช้คีย์\n",
|
|
"- **ไม่ต้องใช้ API keys**: ระบบจะค้นหาและใช้ credential ที่เหมาะสมที่สุดโดยอัตโนมัติ\n",
|
|
"\n",
|
|
"**ขั้นตอนการยืนยันตัวตน:**\n",
|
|
"1. ตรวจสอบ Managed Identity (ในสภาพแวดล้อมของ Azure)\n",
|
|
"2. หากไม่มี จะใช้ Azure CLI credentials (สำหรับการพัฒนาบนเครื่องท้องถิ่น)\n",
|
|
"3. ใช้แหล่งข้อมูล credential อื่น ๆ ตามความจำเป็น\n",
|
|
"\n",
|
|
"วิธีนี้ช่วยลดความยุ่งยากในการจัดการ API keys หรือ connection strings ในโค้ดของคุณ\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "36b1dbd8",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"project_client = AIProjectClient(\n",
|
|
" endpoint=\"Your Azure AI Foundry Endpoint\",\n",
|
|
" credential=DefaultAzureCredential(),\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "cdb6ab8c",
|
|
"metadata": {},
|
|
"source": [
|
|
"## สร้างคำจำกัดความเครื่องมือ MCP\n",
|
|
"\n",
|
|
"สร้างเครื่องมือ MCP ที่เชื่อมต่อกับเซิร์ฟเวอร์ Microsoft Learn MCP:\n",
|
|
"- **server_label**: ตัวระบุสำหรับเซิร์ฟเวอร์ MCP\n",
|
|
"- **server_url**: จุดเชื่อมต่อ URL ของเซิร์ฟเวอร์ MCP\n",
|
|
"- **allowed_tools**: รายการตัวเลือกเพื่อจำกัดเครื่องมือที่สามารถใช้งานได้ (รายการว่างหมายถึงอนุญาตให้ใช้เครื่องมือทั้งหมด)\n",
|
|
"\n",
|
|
"เครื่องมือนี้จะช่วยให้ตัวแทนสามารถเข้าถึงเอกสารและทรัพยากรของ Microsoft Learn ได้\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "51e7e136",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"mcp_tool = McpTool(\n",
|
|
" server_label=mcp_server_label,\n",
|
|
" server_url=mcp_server_url,\n",
|
|
" allowed_tools=[], # Optional: specify allowed tools\n",
|
|
")\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "6e894b0b",
|
|
"metadata": {},
|
|
"source": [
|
|
"## สร้างเอเจนต์และดำเนินการสนทนา (เวิร์กโฟลว์แบบไม่ใช้คีย์)\n",
|
|
"\n",
|
|
"ส่วนนี้แสดงขั้นตอนทั้งหมดของ **เวิร์กโฟลว์เอเจนต์แบบไม่ใช้คีย์**:\n",
|
|
"\n",
|
|
"1. **สร้าง AI Agent**: ตั้งค่าเอเจนต์ด้วยโมเดล GPT-4.1 nano และเครื่องมือ MCP \n",
|
|
"2. **สร้างเธรด**: สร้างเธรดสำหรับการสนทนา \n",
|
|
"3. **ส่งข้อความ**: ถามเอเจนต์เกี่ยวกับความแตกต่างระหว่าง Azure OpenAI และ OpenAI \n",
|
|
"4. **จัดการการอนุมัติเครื่องมือ**: อนุมัติการเรียกใช้เครื่องมือ MCP โดยอัตโนมัติเมื่อจำเป็น \n",
|
|
"5. **ติดตามการดำเนินการ**: ตรวจสอบความคืบหน้าของเอเจนต์และจัดการการดำเนินการที่จำเป็น \n",
|
|
"6. **แสดงผลลัพธ์**: แสดงรายละเอียดการสนทนาและการใช้งานเครื่องมือ \n",
|
|
"\n",
|
|
"**คุณสมบัติของเวิร์กโฟลว์แบบไม่ใช้คีย์:**\n",
|
|
"- ✅ **ไม่มีความลับที่ฮาร์ดโค้ด** - การยืนยันตัวตนทั้งหมดจัดการโดย Azure identity \n",
|
|
"- ✅ **ปลอดภัยโดยค่าเริ่มต้น** - ใช้การควบคุมการเข้าถึงตามบทบาท \n",
|
|
"- ✅ **การปรับใช้ง่าย** - ไม่ต้องจัดการข้อมูลรับรอง \n",
|
|
"- ✅ **เหมาะสำหรับการตรวจสอบ** - การเข้าถึงทั้งหมดถูกติดตามผ่าน Azure identity \n",
|
|
"\n",
|
|
"เอเจนต์จะใช้เครื่องมือ MCP เพื่อเข้าถึงทรัพยากร Microsoft Learn ด้วยความปลอดภัยเต็มรูปแบบและไม่ต้องจัดการ API key\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "68c49af5",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"with project_client:\n",
|
|
" agents_client = project_client.agents\n",
|
|
"\n",
|
|
" # Create a new agent with keyless authentication\n",
|
|
" # NOTE: To reuse existing agent, fetch it with get_agent(agent_id)\n",
|
|
" agent = agents_client.create_agent(\n",
|
|
" model=\"Your Azure OpenAI Model Deployment Name\",\n",
|
|
" name=\"my-mcp-agent\",\n",
|
|
" instructions=\"You are a helpful agent that can use MCP tools to assist users. Use the available MCP tools to answer questions and perform tasks.\",\n",
|
|
" tools=mcp_tool.definitions,\n",
|
|
" )\n",
|
|
" print(f\"Created agent, ID: {agent.id}\")\n",
|
|
" print(f\"MCP Server: {mcp_tool.server_label} at {mcp_tool.server_url}\")\n",
|
|
"\n",
|
|
" # Create thread for communication\n",
|
|
" thread = agents_client.threads.create()\n",
|
|
" print(f\"Created thread, ID: {thread.id}\")\n",
|
|
"\n",
|
|
" # Create message to thread\n",
|
|
" message = agents_client.messages.create(\n",
|
|
" thread_id=thread.id,\n",
|
|
" role=\"user\",\n",
|
|
" content=\"What's difference between Azure OpenAI and OpenAI?\",\n",
|
|
" )\n",
|
|
" print(f\"Created message, ID: {message.id}\")\n",
|
|
"\n",
|
|
" # KEYLESS APPROACH: Handle tool approvals without hardcoded secrets\n",
|
|
" \n",
|
|
" # Option 1: Completely keyless (recommended for Azure identity-enabled MCP servers)\n",
|
|
" # run = agents_client.runs.create(thread_id=thread.id, agent_id=agent.id, tool_resources=mcp_tool.resources)\n",
|
|
" \n",
|
|
" # Option 2: With minimal headers (if MCP server requires specific headers)\n",
|
|
" # For demonstration purposes, using a placeholder header\n",
|
|
" mcp_tool.update_headers(\"SuperSecret\", \"123456\") # Replace with actual auth if needed\n",
|
|
" \n",
|
|
" # Set approval mode - uncomment next line to disable approval requirement completely\n",
|
|
" # mcp_tool.set_approval_mode(\"never\") # Fully automated, no approval needed\n",
|
|
" \n",
|
|
" run = agents_client.runs.create(thread_id=thread.id, agent_id=agent.id, tool_resources=mcp_tool.resources)\n",
|
|
" print(f\"Created run, ID: {run.id}\")\n",
|
|
"\n",
|
|
" while run.status in [\"queued\", \"in_progress\", \"requires_action\"]:\n",
|
|
" time.sleep(1)\n",
|
|
" run = agents_client.runs.get(thread_id=thread.id, run_id=run.id)\n",
|
|
"\n",
|
|
" if run.status == \"requires_action\" and isinstance(run.required_action, SubmitToolApprovalAction):\n",
|
|
" tool_calls = run.required_action.submit_tool_approval.tool_calls\n",
|
|
" if not tool_calls:\n",
|
|
" print(\"No tool calls provided - cancelling run\")\n",
|
|
" agents_client.runs.cancel(thread_id=thread.id, run_id=run.id)\n",
|
|
" break\n",
|
|
"\n",
|
|
" tool_approvals = []\n",
|
|
" for tool_call in tool_calls:\n",
|
|
" if isinstance(tool_call, RequiredMcpToolCall):\n",
|
|
" try:\n",
|
|
" print(f\"Approving tool call: {tool_call}\")\n",
|
|
" \n",
|
|
" # KEYLESS APPROVAL OPTIONS:\n",
|
|
" \n",
|
|
" # Option 1: No headers (fully keyless)\n",
|
|
" # tool_approvals.append(\n",
|
|
" # ToolApproval(\n",
|
|
" # tool_call_id=tool_call.id,\n",
|
|
" # approve=True,\n",
|
|
" # headers={} # No headers needed for keyless\n",
|
|
" # )\n",
|
|
" # )\n",
|
|
" \n",
|
|
" # Option 2: With headers (if MCP server requires them)\n",
|
|
" tool_approvals.append(\n",
|
|
" ToolApproval(\n",
|
|
" tool_call_id=tool_call.id,\n",
|
|
" approve=True,\n",
|
|
" headers=mcp_tool.headers, # Uses configured headers if needed\n",
|
|
" )\n",
|
|
" )\n",
|
|
" except Exception as e:\n",
|
|
" print(f\"Error approving tool_call {tool_call.id}: {e}\")\n",
|
|
"\n",
|
|
" print(f\"tool_approvals: {tool_approvals}\")\n",
|
|
" if tool_approvals:\n",
|
|
" agents_client.runs.submit_tool_outputs(\n",
|
|
" thread_id=thread.id, run_id=run.id, tool_approvals=tool_approvals\n",
|
|
" )\n",
|
|
"\n",
|
|
" print(f\"Current run status: {run.status}\")\n",
|
|
"\n",
|
|
" print(f\"Run completed with status: {run.status}\")\n",
|
|
" if run.status == \"failed\":\n",
|
|
" print(f\"Run failed: {run.last_error}\")\n",
|
|
"\n",
|
|
" # Display run steps and tool calls\n",
|
|
" run_steps = agents_client.run_steps.list(thread_id=thread.id, run_id=run.id)\n",
|
|
"\n",
|
|
" # Loop through each step\n",
|
|
" for step in run_steps:\n",
|
|
" print(f\"Step {step['id']} status: {step['status']}\")\n",
|
|
"\n",
|
|
" # Check if there are tool calls in the step details\n",
|
|
" step_details = step.get(\"step_details\", {})\n",
|
|
" tool_calls = step_details.get(\"tool_calls\", [])\n",
|
|
"\n",
|
|
" if tool_calls:\n",
|
|
" print(\" MCP Tool calls:\")\n",
|
|
" for call in tool_calls:\n",
|
|
" print(f\" Tool Call ID: {call.get('id')}\")\n",
|
|
" print(f\" Type: {call.get('type')}\")\n",
|
|
"\n",
|
|
" print() # add an extra newline between steps\n",
|
|
"\n",
|
|
" # Fetch and log all messages\n",
|
|
" messages = agents_client.messages.list(thread_id=thread.id)\n",
|
|
" print(\"\\nConversation:\")\n",
|
|
" print(\"-\" * 50)\n",
|
|
" for msg in messages:\n",
|
|
" if msg.text_messages:\n",
|
|
" last_text = msg.text_messages[-1]\n",
|
|
" print(f\"{msg.role.upper()}: {last_text.text.value}\")\n",
|
|
" print(\"-\" * 50)\n",
|
|
"\n",
|
|
" # Example of dynamic tool management (keyless)\n",
|
|
" print(f\"\\nDemonstrating keyless dynamic tool management:\")\n",
|
|
" print(f\"Current allowed tools: {mcp_tool.allowed_tools}\")\n",
|
|
" print(\"✅ All operations completed using keyless authentication!\")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"metadata": {},
|
|
"source": [
|
|
"\n---\n\n**ข้อจำกัดความรับผิดชอบ**: \nเอกสารนี้ได้รับการแปลโดยใช้บริการแปลภาษา AI [Co-op Translator](https://github.com/Azure/co-op-translator) แม้ว่าเราจะพยายามให้การแปลมีความถูกต้องมากที่สุด แต่โปรดทราบว่าการแปลอัตโนมัติอาจมีข้อผิดพลาดหรือความไม่ถูกต้อง เอกสารต้นฉบับในภาษาดั้งเดิมควรถือเป็นแหล่งข้อมูลที่เชื่อถือได้ สำหรับข้อมูลที่สำคัญ ขอแนะนำให้ใช้บริการแปลภาษาจากผู้เชี่ยวชาญ เราไม่รับผิดชอบต่อความเข้าใจผิดหรือการตีความที่ผิดพลาดซึ่งเกิดจากการใช้การแปลนี้\n"
|
|
]
|
|
}
|
|
],
|
|
"metadata": {
|
|
"kernelspec": {
|
|
"display_name": "demo",
|
|
"language": "python",
|
|
"name": "python3"
|
|
},
|
|
"language_info": {
|
|
"codemirror_mode": {
|
|
"name": "ipython",
|
|
"version": 3
|
|
},
|
|
"file_extension": ".py",
|
|
"mimetype": "text/x-python",
|
|
"name": "python",
|
|
"nbconvert_exporter": "python",
|
|
"pygments_lexer": "ipython3",
|
|
"version": "3.10.15"
|
|
},
|
|
"coopTranslator": {
|
|
"original_hash": "39a035fea0d10767dfcb0662bd3528fa",
|
|
"translation_date": "2025-08-26T21:33:06+00:00",
|
|
"source_file": "05-AdvancedTopics/mcp-foundry-agent-integration/mcp_support_python.ipynb",
|
|
"language_code": "th"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |