项目文件夹

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

284 行
11 KiB
Plaintext

{
"cells": [
{
"cell_type": "markdown",
"id": "lesson-intro",
"metadata": {},
"source": [
"# Lekcija 03 - Agentni obrasci dizajna\n",
"\n",
"U ovoj lekciji proučavamo tri temeljna obrasca dizajna za izgradnju učinkovitih AI agenata:\n",
"\n",
"1. **Jasne upute za agente** — Izrada preciznih, uloge definirajućih upita koji usmjeravaju ponašanje agenata \n",
"2. **Strukturirani izlaz s Pydantic modelima** — Osiguravanje da agenti vraćaju predvidljive, validirane podatke \n",
"3. **Agenti s jednom odgovornošću** — Dizajniranje fokusiranih agenata koji dobro obavljaju jednu zadaću\n",
"\n",
"Svaki ćemo obrazac primijeniti na scenarij **preporučitelja turističkih destinacija**, postupno gradeći sustav koji može predlagati destinacije, provjeravati dostupnost i rješavati logistiku.\n"
]
},
{
"cell_type": "markdown",
"id": "setup-header",
"metadata": {},
"source": [
"## Instalacija\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "setup-code",
"metadata": {},
"outputs": [],
"source": [
"%pip install agent-framework azure-ai-projects azure-identity pydantic python-dotenv --quiet"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "imports",
"metadata": {},
"outputs": [],
"source": [
"import logging\n",
"logging.getLogger(\"agent_framework.foundry\").setLevel(logging.ERROR)\n",
"\n",
"import os\n",
"import asyncio\n",
"import dotenv\n",
"from typing import Annotated\n",
"from pydantic import BaseModel\n",
"from agent_framework import tool\n",
"from agent_framework.foundry import FoundryChatClient\n",
"from azure.identity import DefaultAzureCredential\n",
"\n",
"dotenv.load_dotenv(dotenv.find_dotenv())\n",
"\n",
"endpoint = os.getenv(\"AZURE_AI_PROJECT_ENDPOINT\")\n",
"deployment_name = os.getenv(\"AZURE_AI_MODEL_DEPLOYMENT_NAME\")\n",
"\n",
"missing = [k for k, v in {\n",
" \"AZURE_AI_PROJECT_ENDPOINT\": endpoint,\n",
" \"AZURE_AI_MODEL_DEPLOYMENT_NAME\": deployment_name\n",
"}.items() if not v]\n",
"\n",
"if missing:\n",
" raise ValueError(\n",
" f\"Missing required environment variables: {', '.join(missing)}. \"\n",
" \"Please set them as environment variables (e.g., in your .env file or shell environment).\"\n",
" )\n",
"\n",
"provider = FoundryChatClient(\n",
" project_endpoint=endpoint,\n",
" model=deployment_name,\n",
" credential=DefaultAzureCredential()\n",
")"
]
},
{
"cell_type": "markdown",
"id": "pattern1-header",
"metadata": {},
"source": [
"## Uzorak 1: Jasne Upute za Agenta\n",
"\n",
"Najjači uzorak je također i najjednostavniji: pisanje jasnih, detaljnih uputa za vašeg agenta.\n",
"\n",
"Dobre upute definiraju:\n",
"- **Tko** je agent (persona i ton)\n",
"- **Što** treba raditi (odgovornosti korak po korak)\n",
"- **Kako** se treba ponašati (ograničenja i stil)\n",
"\n",
"Ispod kreiramo agenta turističkog conciergea s eksplicitnim uputama koje oblikuju svaki odgovor koji daje.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "pattern1-code",
"metadata": {},
"outputs": [],
"source": [
"agent = provider.as_agent(\n",
" name=\"TravelConcierge\",\n",
" instructions=\"\"\"You are a luxury travel concierge named Alex. Your role is to:\n",
"1. Understand the traveler's preferences (budget, climate, activities)\n",
"2. Check destination availability before making recommendations\n",
"3. Provide detailed, personalized travel suggestions\n",
"4. Always mention visa requirements and best travel seasons\n",
"Be warm, professional, and enthusiastic about travel.\"\"\",\n",
")\n",
"\n",
"response = await agent.run(\n",
" \"I'd love a week-long vacation somewhere with great food and history. Budget around $2500.\"\n",
")\n",
"print(response)"
]
},
{
"cell_type": "markdown",
"id": "pattern2-header",
"metadata": {},
"source": [
"## Obrasac 2: Strukturirani Izlaz s Pydantic Modelima\n",
"\n",
"Tekst slobodnog oblika koristan je za razgovor, ali sustavi u nastavku trebaju strukturirane podatke.\n",
"Povezujući **Pydantic modele** s **funkcijom alata**, možemo:\n",
"\n",
"- Definirati točan obrazac za izlaz agenta\n",
"- Automatski provjeravati valjanost odgovora\n",
"- Pouzdano integrirati rezultate agenta u logiku aplikacije\n",
"\n",
"Također uvodimo alat koji vraća podatke o odredištu kako bi agent svoje preporuke temeljio na stvarnim podacima.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "pattern2-code",
"metadata": {},
"outputs": [],
"source": [
"class DestinationRecommendation(BaseModel):\n",
" destination: str\n",
" available: bool\n",
" best_season: str\n",
" highlights: list[str]\n",
" estimated_budget_usd: int\n",
"\n",
"\n",
"class TravelRecommendations(BaseModel):\n",
" recommendations: list[DestinationRecommendation]\n",
" personalized_note: str\n",
"\n",
"\n",
"@tool(approval_mode=\"never_require\")\n",
"def get_destination_details(destination: Annotated[str, \"The destination to look up\"]) -> str:\n",
" \"\"\"Get details about a vacation destination.\"\"\"\n",
" details = {\n",
" \"Barcelona\": \"Available. Best: May-Jun. Beach, architecture, nightlife. ~$2000/week\",\n",
" \"Tokyo\": \"Available. Best: Mar-Apr. Culture, food, technology. ~$2500/week\",\n",
" \"Cape Town\": \"Not available. Best: Nov-Mar. Nature, wine, adventure. ~$1800/week\",\n",
" }\n",
" return details.get(destination, f\"{destination}: No information available.\")\n",
"\n",
"\n",
"structured_agent = provider.as_agent(\n",
" name=\"StructuredTravelExpert\",\n",
" instructions=\"You are a travel expert. Recommend destinations based on traveler preferences. Use the get_destination_details tool.\",\n",
" tools=[get_destination_details],\n",
")\n",
"\n",
"response = await structured_agent.run(\n",
" \"Recommend 3 destinations for a culture-loving traveler with a $2500 budget\"\n",
")\n",
"\n",
"if response:\n",
" print(response)"
]
},
{
"cell_type": "markdown",
"id": "pattern3-header",
"metadata": {},
"source": [
"## Obrasac 3: Agent s Jednom Odgovornošću\n",
"\n",
"Složeni zadaci imaju koristi od podjele rada na više fokusiranih agenata, od kojih svaki ima jednu odgovornost:\n",
"\n",
"- **Stručnjak za odredište** koji zna o mjestima i dostupnosti\n",
"- **Planer logistike** koji upravlja letovima, hotelima i itinererima\n",
"\n",
"Ovo odražava načelo softverskog inženjerstva *odvajanja briga* — svaki agent je lakše testirati, održavati i poboljšavati neovisno.\n"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "pattern3-code",
"metadata": {},
"outputs": [],
"source": [
"destination_agent = provider.as_agent(\n",
" name=\"DestinationExpert\",\n",
" tools=[get_destination_details],\n",
" instructions=\"\"\"You are a destination research specialist. Your only job is to:\n",
"1. Evaluate destinations based on traveler preferences\n",
"2. Check availability using the provided tool\n",
"3. Return a short ranked list with pros/cons\n",
"Do NOT discuss flights, hotels, or logistics — another agent handles that.\"\"\",\n",
")\n",
"\n",
"logistics_agent = provider.as_agent(\n",
" name=\"LogisticsPlanner\",\n",
" instructions=\"\"\"You are a travel logistics planner. Your only job is to:\n",
"1. Create a day-by-day itinerary for the chosen destination\n",
"2. Suggest flight and hotel options within the stated budget\n",
"3. Note visa requirements and travel insurance recommendations\n",
"Do NOT recommend destinations — another agent handles that.\"\"\",\n",
")\n",
"\n",
"# Step 1: Destination Expert picks the best options\n",
"dest_response = await destination_agent.run(\n",
" \"I want a week of culture and food for under $2500. Where should I go?\"\n",
")\n",
"print(\"=== Destination Expert ===\")\n",
"print(dest_response)\n",
"\n",
"# Step 2: Logistics Planner builds the trip plan\n",
"logistics_response = await logistics_agent.run(\n",
" f\"Plan a week-long trip based on this recommendation:\\n{dest_response}\"\n",
")\n",
"print(\"\\n=== Logistics Planner ===\")\n",
"print(logistics_response)"
]
},
{
"cell_type": "markdown",
"id": "summary",
"metadata": {},
"source": [
"## Sažetak\n",
"\n",
"U ovoj lekciji primijenili smo tri obrazca agentnog dizajna na scenarij preporučitelja putovanja:\n",
"\n",
"| Obrazac | Ključna ideja | Prednost |\n",
"|---|---|---|\n",
"| **Jasne upute** | Definirati osobu, odgovornosti i ograničenja unaprijed | Dosljedno, u skladu s brendom ponašanje agenta |\n",
"| **Strukturirani izlaz** | Koristiti Pydantic modele kao format odgovora | Validirani, strojno čitljivi rezultati |\n",
"| **Pojedinačna odgovornost** | Svakom agentu dati jedan usmjeren zadatak | Lakše testiranje, održavanje i sastavljanje |\n",
"\n",
"Ovi se obrasci prirodno nadopunjuju — možete kombinirati jasne upute sa strukturiranim izlazom unutar agenta s pojedinačnom odgovornošću za izgradnju robusnih sustava spremnih za proizvodnju.\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"---\n\n<!-- CO-OP TRANSLATOR DISCLAIMER START -->\n**Napomena**:\nOvaj dokument je preveden korištenjem AI prevoditeljskog servisa [Co-op Translator](https://github.com/Azure/co-op-translator). Iako težimo točnosti, imajte na umu da automatski prijevodi mogu sadržavati greške ili netočnosti. Izvorni dokument na izvornom jeziku treba smatrati autoritativnim izvorom. Za važne informacije preporuča se profesionalni ljudski prijevod. Nismo odgovorni za bilo kakva nesporazumevanja ili pogrešne interpretacije koje proizlaze iz korištenja ovog prijevoda.\n<!-- CO-OP TRANSLATOR DISCLAIMER END -->\n"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3",
"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.13"
}
},
"nbformat": 4,
"nbformat_minor": 5
}