microsoft--ai-agents-for-beginners
314 行
11 KiB
Plaintext
314 行
11 KiB
Plaintext
{
|
|
"cells": [
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "8744544f",
|
|
"metadata": {},
|
|
"source": [
|
|
"# Lekcija 04 - Dizajnerski obrazac korištenja alata\n",
|
|
"\n",
|
|
"U ovoj lekciji naučit ćete dizajnerski obrazac **Korištenje alata** za AI agente koristeći Microsoft Agent Framework (Python). Obrađujemo:\n",
|
|
"\n",
|
|
"- Definiranje funkcijskih alata s dekoratorom `@tool` i tipiziranim parametrima\n",
|
|
"- Davanje shema alata kako bi model znao što svaki alat radi\n",
|
|
"- Kontrolu izvršavanja alata s `approval_mode`\n",
|
|
"- Vraćanje **strukturiranog izlaza** putem Pydantic modela i `response_format`\n",
|
|
"\n",
|
|
"Scenarij je **agent za rezervaciju putovanja** koji može pregledavati destinacije, provjeravati dostupnost i dohvaćati informacije o letovima.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "b1a2c3d4",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Postavljanje\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "59c0feeb",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"%pip install agent-framework azure-ai-projects azure-identity python-dotenv -U -q"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "c0df8a52",
|
|
"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",
|
|
"\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",
|
|
" )"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a6141584",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"# Create the Azure AI Foundry client\n",
|
|
"client = FoundryChatClient(\n",
|
|
" project_endpoint=endpoint,\n",
|
|
" model=deployment_name,\n",
|
|
" credential=DefaultAzureCredential()\n",
|
|
")"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "d5e6f7a8",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Definiranje alata s dekoratorom @tool\n",
|
|
"\n",
|
|
"Dekorator `@tool` pretvara običnu Python funkciju u alat koji agent može pozvati. \n",
|
|
"Ključne točke:\n",
|
|
"\n",
|
|
"- **Docstring** postaje opis alata koji model vidi. \n",
|
|
"- **Tipovi anotacija** (uključujući `Annotated` s opisima) definiraju shemu alata. \n",
|
|
"- `approval_mode` kontrolira mora li korisnik odobriti svaki poziv prije nego što se izvrši.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a6507f83",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tool(approval_mode=\"never_require\")\n",
|
|
"def get_destinations() -> list[str]:\n",
|
|
" \"\"\"Get available vacation destinations.\"\"\"\n",
|
|
" return [\"Barcelona\", \"Paris\", \"Berlin\", \"Tokyo\", \"Sydney\", \"New York City\"]\n",
|
|
"\n",
|
|
"\n",
|
|
"@tool(approval_mode=\"never_require\")\n",
|
|
"def check_availability(\n",
|
|
" destination: Annotated[str, \"The destination to check\"],\n",
|
|
") -> str:\n",
|
|
" \"\"\"Check booking availability for a destination.\"\"\"\n",
|
|
" availability = {\n",
|
|
" \"Barcelona\": \"Available - 3 spots left\",\n",
|
|
" \"Paris\": \"Available\",\n",
|
|
" \"Berlin\": \"Sold out\",\n",
|
|
" \"Tokyo\": \"Available - 1 spot left\",\n",
|
|
" \"Sydney\": \"Available\",\n",
|
|
" \"New York City\": \"Available\",\n",
|
|
" }\n",
|
|
" return availability.get(destination, \"Unknown destination\")\n",
|
|
"\n",
|
|
"\n",
|
|
"@tool(approval_mode=\"never_require\")\n",
|
|
"def get_flight_info(\n",
|
|
" origin: Annotated[str, \"Origin airport code\"],\n",
|
|
" destination: Annotated[str, \"Destination airport code\"],\n",
|
|
") -> str:\n",
|
|
" \"\"\"Get flight information between two cities.\"\"\"\n",
|
|
" flights = {\n",
|
|
" \"LHR-BCN\": \"BA 2042, Departs 08:30, Arrives 11:45, $350\",\n",
|
|
" \"LHR-CDG\": \"AF 1081, Departs 09:15, Arrives 11:30, $280\",\n",
|
|
" \"LHR-NRT\": \"JL 044, Departs 11:00, Arrives 07:00+1, $890\",\n",
|
|
" }\n",
|
|
" return flights.get(\n",
|
|
" f\"{origin}-{destination}\",\n",
|
|
" f\"No direct flights from {origin} to {destination}\",\n",
|
|
" )"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "e9f0a1b2",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Izrada agenta s više alata\n",
|
|
"\n",
|
|
"Proslijedite sva tri alata klijentu kako bi model mogao pozvati one koje treba za odgovor na pitanje korisnika.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "be18ac4f",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"travel_tools = [get_destinations, check_availability, get_flight_info]\n",
|
|
"\n",
|
|
"agent = client.as_agent(\n",
|
|
" name=\"TravelToolAgent\",\n",
|
|
" instructions=\"You are a travel agent. Use the available tools to answer questions about destinations, availability, and flights.\",\n",
|
|
" tools=travel_tools,\n",
|
|
")\n",
|
|
"\n",
|
|
"response = await agent.run(\n",
|
|
" \"What destinations do you have? Which ones are still available?\"\n",
|
|
")\n",
|
|
"print(response)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "c3d4e5f6",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Strukturirani izlaz s alatima\n",
|
|
"\n",
|
|
"Postavljanjem `response_format` na Pydantic model, agent je primoran vratiti dobro tipizirani JSON objekt umjesto slobodnog teksta. Ovo je korisno kada kod koji slijedi treba programski konzumirati rezultat.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "772e9481",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"class BookingRecommendation(BaseModel):\n",
|
|
" destination: str\n",
|
|
" available: bool\n",
|
|
" flight_details: str\n",
|
|
" estimated_cost: int\n",
|
|
"\n",
|
|
"\n",
|
|
"class TravelPlan(BaseModel):\n",
|
|
" recommendations: list[BookingRecommendation]\n",
|
|
"\n",
|
|
"\n",
|
|
"structured_agent = client.as_agent(\n",
|
|
" name=\"StructuredTravelAgent\",\n",
|
|
" instructions=(\n",
|
|
" \"You are a travel agent. Use the available tools to find destinations, \"\n",
|
|
" \"check availability, and get flight info. Return structured results.\"\n",
|
|
" ),\n",
|
|
" tools=[get_destinations, check_availability, get_flight_info],\n",
|
|
")\n",
|
|
"\n",
|
|
"response = await structured_agent.run(\n",
|
|
" \"I want to fly from London Heathrow to somewhere warm in Europe. \"\n",
|
|
" \"Check what's available.\"\n",
|
|
")\n",
|
|
"if response:\n",
|
|
" print(response)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "a7b8c9d0",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Obrasci odobravanja alata\n",
|
|
"\n",
|
|
"Parametar `approval_mode` na `@tool` kontrolira zahtijevaju li pozivi alata ljudsko odobrenje prije izvršavanja:\n",
|
|
"\n",
|
|
"| Način | Ponašanje |\n",
|
|
"|---|---|\n",
|
|
"| `\"never_require\"` | Alat se izvršava automatski — nije potrebna potvrda korisnika. |\n",
|
|
"| `\"always_require\"` | Svaki poziv mora biti odobren od strane korisnika prije izvršenja. |\n",
|
|
"\n",
|
|
"Koristite `\"always_require\"` za alate koji imaju nuspojave (npr. rezervacija leta, terećenje kreditne kartice) kako bi čovjek ostao uključen u proces.\n"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "code",
|
|
"execution_count": null,
|
|
"id": "a731b547",
|
|
"metadata": {},
|
|
"outputs": [],
|
|
"source": [
|
|
"@tool(approval_mode=\"always_require\")\n",
|
|
"def book_flight(\n",
|
|
" origin: Annotated[str, \"Origin airport code\"],\n",
|
|
" destination: Annotated[str, \"Destination airport code\"],\n",
|
|
" passenger_name: Annotated[str, \"Full name of the passenger\"],\n",
|
|
") -> str:\n",
|
|
" \"\"\"Book a flight for a passenger. Requires approval before executing.\"\"\"\n",
|
|
" return (\n",
|
|
" f\"Flight booked from {origin} to {destination} \"\n",
|
|
" f\"for {passenger_name}. Confirmation #TRV-2024-{hash(passenger_name) % 10000:04d}\"\n",
|
|
" )\n",
|
|
"\n",
|
|
"\n",
|
|
"print(\"Tool name:\", book_flight.name)\n",
|
|
"print(\"Approval mode:\", book_flight.approval_mode)"
|
|
]
|
|
},
|
|
{
|
|
"cell_type": "markdown",
|
|
"id": "f1e2d3c4",
|
|
"metadata": {},
|
|
"source": [
|
|
"## Sažetak\n",
|
|
"\n",
|
|
"U ovoj lekciji naučili ste kako:\n",
|
|
"\n",
|
|
"1. **Definirati alate** koristeći dekorator `@tool` s tipiziranim parametrima i docstringovima koji služe kao shema alata.\n",
|
|
"2. **Sastaviti više alata** tako da agent može pozivati ih jedan za drugim kako bi odgovorio na složene upite.\n",
|
|
"3. **Vratiti strukturirani izlaz** prosljeđivanjem Pydantic modela kao `response_format`.\n",
|
|
"4. **Kontrolirati odobrenje alata** pomoću `approval_mode` kako bi se zadržala ljudska kontrola u osjetljivim operacijama.\n",
|
|
"\n",
|
|
"Ovi obrasci čine temelj za izgradnju pouzdanih agenata spremnih za proizvodnju koji mogu sigurno komunicirati s vanjskim sustavima.\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.0"
|
|
}
|
|
},
|
|
"nbformat": 4,
|
|
"nbformat_minor": 5
|
|
} |