项目文件夹

文件
2026-07-13 12:59:43 +08:00

474 行
22 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "2b91961c",
"metadata": {},
"source": [
"## دو نماینده متوالی:\n",
"\n",
"1. **نماینده میز پذیرش**: پیشنهادهای اولیه جاذبه‌های شهر را ارائه می‌دهد \n",
"2. **نماینده کنسیرج**: پیشنهاد نماینده میز پذیرش را بر اساس محبوبیت بررسی و ارزیابی می‌کند\n",
"\n",
"## مزایای کلیدی ارکستراسیون متوالی:\n",
"\n",
"- **بازبینی تکراری**: نماینده دوم کار نماینده اول را بهبود می‌بخشد \n",
"- **تخصصی‌سازی**: هر نماینده نقش مشخصی در فرآیند دارد \n",
"- **کنترل کیفیت**: مرحله بازبینی و اعتبارسنجی داخلی \n",
"- **جریان اطلاعات شفاف**: انتقال منظم و ساختارمند بین نمایندگان\n",
"\n",
"## ملزومات:\n",
"- نصب Microsoft Agent Framework \n",
"- پیکربندی نقطه انتهایی پروژه Azure AI Foundry و استقرار مدل (`AZURE_AI_PROJECT_ENDPOINT`، `AZURE_AI_MODEL_DEPLOYMENT_NAME`) \n",
"- احراز هویت از طریق Azure CLI (`az login`) \n",
"- درک مفاهیم پایه نماینده‌ها\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "0981c0bb",
"metadata": {},
"outputs": [],
"source": [
"import asyncio\n",
"import json\n",
"import os\n",
"from typing import Any, cast\n",
"\n",
"from agent_framework import Message, WorkflowBuilder\n",
"from agent_framework.azure import AzureAIProjectAgentProvider\n",
"from azure.identity import AzureCliCredential\n",
"from dotenv import load_dotenv\n",
"from IPython.display import HTML, display\n",
"from pydantic import BaseModel\n",
"\n",
"print(\"All imports successful!\")"
]
},
{
"cell_type": "markdown",
"id": "790b74bd",
"metadata": {},
"source": [
"## مرحله ۱: تعریف مدل‌های Pydantic برای خروجی‌های ساختاریافته\n",
"\n",
"این مدل‌ها طرحی را تعریف می‌کنند که هر عامل بازمی‌گرداند. عامل پذیرش یک توصیه ارائه می‌دهد و عامل کنسیرج یک بازبینی و امتیاز‌دهی ارائه می‌کند.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3436dc8d",
"metadata": {},
"outputs": [],
"source": [
"class AttractionRecommendation(BaseModel):\n",
" \"\"\"Attraction recommendation from the front desk agent.\"\"\"\n",
"\n",
" city: str\n",
" attraction_name: str\n",
" description: str\n",
" category: str # e.g., \"museum\", \"landmark\", \"park\", \"entertainment\"\n",
" recommended_duration: str # e.g., \"2-3 hours\", \"half day\"\n",
" why_recommended: str\n",
" best_time_to_visit: str\n",
"\n",
"\n",
"class AttractionReview(BaseModel):\n",
" \"\"\"Expert review and rating from the concierge agent.\"\"\"\n",
"\n",
" attraction_name: str\n",
" city: str\n",
" popularity_score: int # 1-10 scale\n",
" popularity_reasoning: str\n",
" visitor_rating: float # 1.0-5.0 scale\n",
" pros: list[str]\n",
" cons: list[str]\n",
" concierge_recommendation: str\n",
" alternative_suggestions: list[str]"
]
},
{
"cell_type": "markdown",
"id": "f4269b29",
"metadata": {},
"source": [
"## مرحله ۲: بارگذاری متغیرهای محیطی و پیکربندی ارائه‌دهنده Foundry\n",
"\n",
"از `AzureAIProjectAgentProvider` با احراز هویت بدون کلید `AzureCliCredential` استفاده کنید، به‌گونه‌ای که با الگوی استفاده‌شده در درس‌های ۰۱–۱۳ مطابقت داشته باشد.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "2152c7d3",
"metadata": {},
"outputs": [],
"source": [
"# Load environment variables\n",
"load_dotenv()\n",
"\n",
"# Configure the Azure AI Foundry provider with keyless authentication\n",
"provider = AzureAIProjectAgentProvider(credential=AzureCliCredential())\n",
"\n",
"print(\"Azure AI Foundry provider configured successfully!\")"
]
},
{
"cell_type": "markdown",
"id": "e63c63dd",
"metadata": {},
"source": [
"## مرحله ۳: ایجاد دو عامل متوالی\n",
"\n",
"هر عامل نقش خاصی در جریان کاری متوالی دارد. عامل پذیرش توصیه‌هایی ارائه می‌دهد و عامل کانسیرج آنها را بررسی و ارزیابی می‌کند.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "3f862eee",
"metadata": {},
"outputs": [],
"source": [
"# Agent 1: Front Desk Agent (Makes initial recommendations)\n",
"front_desk_agent = await provider.create_agent(\n",
" name=\"front-desk-agent\",\n",
" instructions=(\n",
" \"You are a knowledgeable hotel front desk agent who specializes in local attractions. \"\n",
" \"When a guest asks about attractions in a city, provide a single, well-researched recommendation \"\n",
" \"for a popular tourist attraction. Focus on giving practical information including what makes \"\n",
" \"this attraction special, how long to spend there, and the best time to visit. \"\n",
" \"Be helpful and enthusiastic about your recommendation. \"\n",
" \"Return structured JSON matching the AttractionRecommendation schema.\"\n",
" ),\n",
")\n",
"\n",
"# Agent 2: Concierge Agent (Reviews and rates recommendations)\n",
"concierge_agent = await provider.create_agent(\n",
" name=\"concierge-agent\",\n",
" instructions=(\n",
" \"You are an expert concierge with extensive knowledge of tourist attractions worldwide. \"\n",
" \"You will receive an attraction recommendation and must provide an expert review and rating. \"\n",
" \"Evaluate the recommendation based on the attraction's popularity, visitor satisfaction, \"\n",
" \"and overall quality. Provide a popularity score (1-10), visitor rating (1.0-5.0), \"\n",
" \"list pros and cons, and give your professional assessment. \"\n",
" \"Also suggest alternative attractions if appropriate. \"\n",
" \"Return structured JSON matching the AttractionReview schema.\"\n",
" ),\n",
")\n"
]
},
{
"cell_type": "markdown",
"id": "0afa99f5",
"metadata": {},
"source": [
"## مرحله ۴: ایجاد جریان کاری ترتیبی\n",
"\n",
"`WorkflowBuilder` یک جریان کاری ایجاد می‌کند که در آن:\n",
"1. **نماینده میز پذیرش** ورودی کاربر را دریافت کرده و یک پیشنهاد ارائه می‌دهد\n",
"2. **نماینده کنسیرج** پیشنهاد میز پذیرش را دریافت کرده و بازبینی تخصصی انجام می‌دهد\n",
"3. **خروجی** شامل هر دو پیشنهاد اصلی و بازبینی تخصصی است\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d76c5b11",
"metadata": {},
"outputs": [],
"source": [
"# Build the sequential workflow with WorkflowBuilder\n",
"workflow = (\n",
" WorkflowBuilder(\n",
" start_executor=front_desk_agent,\n",
" output_executors=[front_desk_agent, concierge_agent],\n",
" )\n",
" .add_edge(front_desk_agent, concierge_agent)\n",
" .build()\n",
")\n",
"\n",
"display(HTML(\"\"\"\n",
"<div style='padding: 20px; background: linear-gradient(135deg, #ff7043 0%, #ff5722 100%); color: white; border-radius: 8px; margin: 10px 0;'>\n",
" <h3 style='margin: 0 0 15px 0;'>Sequential Workflow Built Successfully!</h3>\n",
" <p style='margin: 0; line-height: 1.6;'>\n",
" <strong>Flow:</strong><br>\n",
" • User Input → <strong>Front Desk Agent</strong> (recommendation)<br>\n",
" • Front Desk Output → <strong>Concierge Agent</strong> (review & rating)<br>\n",
" • Final Output → Combined recommendation + expert review\n",
" </p>\n",
"</div>\n",
"\"\"\"))"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "27a52679",
"metadata": {},
"outputs": [],
"source": [
"async def display_attraction_recommendation(city: str):\n",
" \"\"\"Run the sequential workflow and display formatted results.\"\"\"\n",
"\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 20px; background: #fff3e0; border-left: 4px solid #ff9800; border-radius: 8px; margin: 20px 0;'>\n",
" <h3 style='margin: 0 0 10px 0; color: #e65100;'>Processing Attraction Recommendation for {city}</h3>\n",
" <p style='margin: 0;'><strong>Status:</strong> Running sequential workflow...</p>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" # Run the workflow. With WorkflowBuilder(output_executors=[a1, a2]),\n",
" # outputs is a list of AgentResponse objects, one per output executor.\n",
" events = await workflow.run(f\"I want to visit an attraction in {city}\")\n",
" outputs = events.get_outputs()\n",
"\n",
" front_desk_response = outputs[0].text if len(outputs) > 0 else None\n",
" concierge_response = outputs[1].text if len(outputs) > 1 else None\n",
"\n",
" # Display results\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 25px; background: linear-gradient(135deg, #4caf50 0%, #8bc34a 100%); color: white; border-radius: 12px;\n",
" box-shadow: 0 4px 12px rgba(76,175,80,0.3); margin: 20px 0;'>\n",
" <h2 style='margin: 0 0 20px 0;'>Attraction Recommendation for {city}</h2>\n",
" <p style='margin: 0; font-size: 14px; opacity: 0.9;'>Generated by sequential agent workflow</p>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" # Process and display responses\n",
" if front_desk_response:\n",
" try:\n",
" recommendation_data = AttractionRecommendation.model_validate_json(front_desk_response)\n",
" display_front_desk_section(recommendation_data)\n",
" except Exception as e:\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 15px; background: #ffcdd2; border-left: 4px solid #f44336; border-radius: 4px; margin: 10px 0;'>\n",
" <strong>Error parsing front desk response:</strong> {str(e)}\n",
" <details><summary>Raw response</summary>{front_desk_response}</details>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" if concierge_response:\n",
" try:\n",
" review_data = AttractionReview.model_validate_json(concierge_response)\n",
" display_concierge_section(review_data)\n",
" except Exception as e:\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 15px; background: #ffcdd2; border-left: 4px solid #f44336; border-radius: 4px; margin: 10px 0;'>\n",
" <strong>Error parsing concierge response:</strong> {str(e)}\n",
" <details><summary>Raw response</summary>{concierge_response}</details>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
"\n",
"def display_front_desk_section(data: AttractionRecommendation):\n",
" \"\"\"Display front desk recommendation in a formatted section.\"\"\"\n",
"\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 20px; background: #e3f2fd; border-radius: 8px; margin: 15px 0; border-left: 4px solid #2196f3;'>\n",
" <h3 style='margin: 0 0 15px 0; color: #1976d2;'>🏨 Front Desk Recommendation</h3>\n",
" <div style='margin-bottom: 15px;'>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>{data.attraction_name}</h4>\n",
" <span style='background: #2196f3; color: white; padding: 4px 8px; border-radius: 12px; font-size: 12px;'>{data.category}</span>\n",
" </div>\n",
" <div style='margin-bottom: 15px;'>\n",
" <strong style='color: #333;'>Description:</strong> {data.description}\n",
" </div>\n",
" <div style='margin-bottom: 10px;'>\n",
" <strong style='color: #333;'>Why Recommended:</strong> {data.why_recommended}\n",
" </div>\n",
" <div style='margin-bottom: 10px;'>\n",
" <strong style='color: #333;'>Recommended Duration:</strong> {data.recommended_duration}\n",
" </div>\n",
" <div>\n",
" <strong style='color: #333;'>Best Time to Visit:</strong> {data.best_time_to_visit}\n",
" </div>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
"\n",
"def display_concierge_section(data: AttractionReview):\n",
" \"\"\"Display concierge review in a formatted section.\"\"\"\n",
"\n",
" # Create star rating display\n",
" star_rating = \"⭐\" * int(data.visitor_rating) + \"☆\" * (5 - int(data.visitor_rating))\n",
"\n",
" # Create popularity bar\n",
" popularity_bar = \"🟩\" * data.popularity_score + \"⬜\" * (10 - data.popularity_score)\n",
"\n",
" pros_list = \"\".join([f\"<li style='color: #4caf50;'>✓ {pro}</li>\" for pro in data.pros])\n",
" cons_list = \"\".join([f\"<li style='color: #f44336;'>✗ {con}</li>\" for con in data.cons])\n",
" alternatives_list = \"\".join([f\"<li>{alt}</li>\" for alt in data.alternative_suggestions])\n",
"\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 20px; background: #fff3e0; border-radius: 8px; margin: 15px 0; border-left: 4px solid #ff9800;'>\n",
" <h3 style='margin: 0 0 15px 0; color: #f57c00;'>🎩 Concierge Expert Review</h3>\n",
"\n",
" <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;'>\n",
" <div style='background: rgba(255,152,0,0.1); padding: 15px; border-radius: 8px;'>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>Popularity Score</h4>\n",
" <div style='font-size: 24px; font-weight: bold; color: #f57c00;'>{data.popularity_score}/10</div>\n",
" <div style='font-size: 12px; margin-top: 5px;'>{popularity_bar}</div>\n",
" </div>\n",
" <div style='background: rgba(255,152,0,0.1); padding: 15px; border-radius: 8px;'>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>Visitor Rating</h4>\n",
" <div style='font-size: 20px; font-weight: bold; color: #f57c00;'>{data.visitor_rating}/5.0</div>\n",
" <div style='font-size: 16px; margin-top: 5px;'>{star_rating}</div>\n",
" </div>\n",
" </div>\n",
"\n",
" <div style='margin-bottom: 15px;'>\n",
" <strong style='color: #333;'>Popularity Reasoning:</strong> {data.popularity_reasoning}\n",
" </div>\n",
"\n",
" <div style='display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 15px;'>\n",
" <div>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>Pros:</h4>\n",
" <ul style='margin: 0; padding-left: 20px;'>{pros_list}</ul>\n",
" </div>\n",
" <div>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>Cons:</h4>\n",
" <ul style='margin: 0; padding-left: 20px;'>{cons_list}</ul>\n",
" </div>\n",
" </div>\n",
" <div style='margin-bottom: 15px;'>\n",
" <strong style='color: #333;'>Concierge Recommendation:</strong> {data.concierge_recommendation}\n",
" </div>\n",
"\n",
" <div>\n",
" <h4 style='margin: 0 0 8px 0; color: #333;'>Alternative Suggestions:</h4>\n",
" <ul style='margin: 0; padding-left: 20px; color: #555;'>{alternatives_list}</ul>\n",
" </div>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
"\n",
"# Test with Stockholm\n",
"await display_attraction_recommendation(\"Stockholm\")\n"
]
},
{
"cell_type": "markdown",
"id": "1840d000",
"metadata": {},
"source": [
"## مرحله ۸: تحلیل جریان کاری - درک جریان ترتیبی\n",
"\n",
"بیایید بررسی کنیم که چگونه اطلاعات بین عامل‌ها جریان می‌یابد و تاریخچه مکالمه را تحلیل کنیم.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "86e1bcc3",
"metadata": {},
"outputs": [],
"source": [
"async def analyze_sequential_flow(city: str):\n",
" \"\"\"Analyze the sequential flow between agents.\"\"\"\n",
"\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 20px; background: #f3e5f5; border-left: 4px solid #9c27b0; border-radius: 8px; margin: 20px 0;'>\n",
" <h3 style='margin: 0 0 10px 0; color: #7b1fa2;'>Sequential Flow Analysis for {city}</h3>\n",
" <p style='margin: 0;'>Examining agent interactions and information handoff...</p>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" # Run the workflow\n",
" user_input = f\"I want to visit an attraction in {city}\"\n",
" events = await workflow.run(user_input)\n",
" outputs = events.get_outputs()\n",
"\n",
" # Reconstruct the conversation flow as a list of (author, text) steps.\n",
" # outputs is a list of AgentResponse objects, ordered to match output_executors.\n",
" steps = [(\"user\", user_input)]\n",
" if len(outputs) > 0:\n",
" steps.append((\"front-desk-agent\", outputs[0].text))\n",
" if len(outputs) > 1:\n",
" steps.append((\"concierge-agent\", outputs[1].text))\n",
"\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 25px; background: #f3e5f5; border-radius: 12px; margin: 20px 0;'>\n",
" <h2 style='margin: 0 0 20px 0; color: #7b1fa2;'>Conversation Flow Analysis</h2>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" # Display each step in the sequence\n",
" for i, (author, text) in enumerate(steps, 1):\n",
" role_color = {\n",
" \"user\": \"#2196f3\",\n",
" \"front-desk-agent\": \"#4caf50\",\n",
" \"concierge-agent\": \"#ff9800\"\n",
" }.get(author, \"#666666\")\n",
"\n",
" role_name = {\n",
" \"user\": \"👤 User\",\n",
" \"front-desk-agent\": \"🏨 Front Desk Agent\",\n",
" \"concierge-agent\": \"🎩 Concierge Agent\"\n",
" }.get(author, \"Unknown\")\n",
"\n",
" # Truncate long messages for flow analysis\n",
" content_preview = text[:200] + \"...\" if len(text) > 200 else text\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 15px; background: white; border-left: 4px solid {role_color}; border-radius: 4px; margin: 10px 0; box-shadow: 0 2px 4px rgba(0,0,0,0.1);'>\n",
" <div style='display: flex; align-items: center; margin-bottom: 10px;'>\n",
" <span style='font-weight: bold; color: {role_color}; margin-right: 10px;'>Step {i}:</span>\n",
" <span style='font-weight: bold; color: {role_color};'>{role_name}</span>\n",
" </div>\n",
" <div style='color: #555; font-size: 14px; line-height: 1.4;'>\n",
" {content_preview}\n",
" </div>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
" # Analyze the flow\n",
" display(HTML(f\"\"\"\n",
" <div style='padding: 20px; background: linear-gradient(135deg, #9c27b0 0%, #673ab7 100%); color: white; border-radius: 8px; margin: 20px 0;'>\n",
" <h3 style='margin: 0 0 15px 0;'>Flow Analysis Summary</h3>\n",
" <ul style='margin: 0; padding-left: 20px; line-height: 1.6;'>\n",
" <li><strong>Total Steps:</strong> {len(steps)}</li>\n",
" <li><strong>Agents Involved:</strong> 2 (Front Desk + Concierge)</li>\n",
" <li><strong>Flow Pattern:</strong> Linear sequential (User → Agent 1 → Agent 2)</li>\n",
" <li><strong>Information Handoff:</strong> Front desk recommendation becomes concierge input</li>\n",
" <li><strong>Output Quality:</strong> Enhanced through expert review and rating</li>\n",
" </ul>\n",
" </div>\n",
" \"\"\"))\n",
"\n",
"\n",
"# Analyze the flow for Barcelona\n",
"await analyze_sequential_flow(\"Barcelona\")\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**سلب مسئولیت**:\nاین سند با استفاده از سرویس ترجمه هوش مصنوعی [Co-op Translator](https://github.com/Azure/co-op-translator) ترجمه شده است. در حالی که ما در تلاش برای دقت هستیم، لطفاً توجه داشته باشید که ترجمه‌های خودکار ممکن است شامل خطاها یا نادرستی‌هایی باشند. سند اصلی به زبان مادری خود باید به عنوان منبع معتبر در نظر گرفته شود. برای اطلاعات حیاتی، ترجمه حرفه‌ای انسانی توصیه می‌شود. ما در قبال هرگونه سوء تفاهم یا برداشت نادرست ناشی از استفاده از این ترجمه مسئولیتی نداریم.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv (3.12.12)",
"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.12.12"
}
},
"nbformat": 4,
"nbformat_minor": 5
}