Pular para o conteúdo principal

Desafio 21: Fundamentos e Arquitetura de Agentes

Tempo Estimado

45-60 min | Custo: $2-5 (estimado) | Domínio: Implementar Soluções Agênticas (5-10%)

Habilidades do exame cobertas

  • Entender o papel e casos de uso de um agente de IA
  • Configurar recursos necessários para soluções de agentes
  • Implementar function calling com Azure OpenAI

Visão Geral

Agentes de IA vão além de chatbots simples ao combinar raciocínio de LLM com a capacidade de tomar ações. Enquanto um chatbot responde perguntas a partir de seus dados de treinamento, um agente pode chamar ferramentas externas, executar código, consultar bancos de dados e orquestrar workflows de múltiplas etapas de forma autônoma.

Conceitos-chave:

  • Tool/Function calling: O modelo decide quais funções invocar com base na intenção do usuário
  • Planejamento: Dividir tarefas complexas em etapas sequenciais
  • Memória: Manter contexto de conversação e estado entre interações
  • Grounding: Conectar o modelo a fontes de dados em tempo real

Este desafio implementa function calling com Azure OpenAI — a base de todas as arquiteturas de agentes.

Arquitetura

┌──────────────┐ ┌──────────────────┐ ┌──────────────────┐
│ User │────▶│ Azure OpenAI │────▶│ Tool Execution │
│ Prompt │◀────│ (GPT-4o) │◀────│ (Functions) │
└──────────────┘ └──────────────────┘ └──────────────────┘
│ │
│ 1. Analyze intent │
│ 2. Select tool │
│ 3. Generate arguments │
│ │
│ 4. Execute ──────┘
│ 5. Return result
│ 6. Synthesize response

Pré-requisitos

  • Assinatura Azure com acesso ao Azure OpenAI
  • Recurso Azure OpenAI com GPT-4o implantado
  • Python 3.9+ ou .NET 8
  • Pacotes: openai>=1.0.0 (Python) ou Azure.AI.OpenAI (C#)

Implementação

Tarefa 1: Implantar Recurso e Modelo Azure OpenAI

# Create resource group
az group create --name rg-ai102-agents --location eastus2

# Create Azure OpenAI resource
az cognitiveservices account create \
--name aoai-ai102-agents \
--resource-group rg-ai102-agents \
--kind OpenAI \
--sku S0 \
--location eastus2

# Deploy GPT-4o model
az cognitiveservices account deployment create \
--name aoai-ai102-agents \
--resource-group rg-ai102-agents \
--deployment-name gpt-4o \
--model-name gpt-4o \
--model-version "2024-08-06" \
--model-format OpenAI \
--sku-capacity 10 \
--sku-name Standard

# Get endpoint and key
az cognitiveservices account show \
--name aoai-ai102-agents \
--resource-group rg-ai102-agents \
--query properties.endpoint -o tsv

az cognitiveservices account keys list \
--name aoai-ai102-agents \
--resource-group rg-ai102-agents \
--query key1 -o tsv

Tarefa 2: Implementar Function Calling

import os
import json
from openai import AzureOpenAI

client = AzureOpenAI(
azure_endpoint=os.environ["AZURE_OPENAI_ENDPOINT"],
api_key=os.environ["AZURE_OPENAI_KEY"],
api_version="2024-10-21"
)

# Define tools the agent can use
tools = [
{
"type": "function",
"function": {
"name": "get_weather",
"description": "Get the current weather for a given location",
"parameters": {
"type": "object",
"properties": {
"location": {
"type": "string",
"description": "City name, e.g. 'Seattle, WA'"
},
"unit": {
"type": "string",
"enum": ["celsius", "fahrenheit"],
"description": "Temperature unit"
}
},
"required": ["location"]
}
}
},
{
"type": "function",
"function": {
"name": "search_products",
"description": "Search for products in the catalog by name or category",
"parameters": {
"type": "object",
"properties": {
"query": {
"type": "string",
"description": "Search query for products"
},
"category": {
"type": "string",
"enum": ["electronics", "clothing", "home", "sports"],
"description": "Product category filter"
},
"max_price": {
"type": "number",
"description": "Maximum price filter"
}
},
"required": ["query"]
}
}
}
]

# Simulated tool implementations
def get_weather(location: str, unit: str = "celsius") -> dict:
"""Simulated weather API call"""
return {
"location": location,
"temperature": 22 if unit == "celsius" else 72,
"unit": unit,
"condition": "Partly cloudy",
"humidity": 65
}

def search_products(query: str, category: str = None, max_price: float = None) -> dict:
"""Simulated product search"""
results = [
{"name": f"{query} Pro", "price": 299.99, "category": category or "electronics"},
{"name": f"{query} Basic", "price": 149.99, "category": category or "electronics"}
]
if max_price:
results = [r for r in results if r["price"] <= max_price]
return {"results": results, "total": len(results)}

# Map function names to implementations
available_functions = {
"get_weather": get_weather,
"search_products": search_products
}

def run_agent(user_message: str):
"""Run the agent loop with function calling"""
messages = [
{"role": "system", "content": "You are a helpful assistant with access to weather and product search tools."},
{"role": "user", "content": user_message}
]

# First call - model decides whether to use tools
response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)

response_message = response.choices[0].message

# Check if the model wants to call functions
if response_message.tool_calls:
messages.append(response_message)

# Execute each tool call
for tool_call in response_message.tool_calls:
function_name = tool_call.function.name
function_args = json.loads(tool_call.function.arguments)

print(f" [Agent] Calling: {function_name}({function_args})")

# Execute the function
function_response = available_functions[function_name](**function_args)

# Add the function result to messages
messages.append({
"tool_call_id": tool_call.id,
"role": "tool",
"name": function_name,
"content": json.dumps(function_response)
})

# Second call - model synthesizes final response
final_response = client.chat.completions.create(
model="gpt-4o",
messages=messages
)
return final_response.choices[0].message.content
else:
return response_message.content

# Test the agent
print("=" * 60)
print("Test 1: Weather query (should trigger get_weather)")
print("=" * 60)
result = run_agent("What's the weather like in Seattle?")
print(f"Agent: {result}\n")

print("=" * 60)
print("Test 2: Product search (should trigger search_products)")
print("=" * 60)
result = run_agent("Find me headphones under $200")
print(f"Agent: {result}\n")

print("=" * 60)
print("Test 3: No tool needed (general knowledge)")
print("=" * 60)
result = run_agent("What is the capital of France?")
print(f"Agent: {result}\n")

Tarefa 3: Implementar Function Calling Paralelo

# The model can call multiple tools in parallel when appropriate
# Test with a query that requires both tools

result = run_agent(
"I'm planning a trip to Miami. What's the weather there? "
"Also, find me some sunglasses under $100."
)
print(f"Agent (parallel calls): {result}")

# Verify parallel execution by checking tool_calls count
messages = [
{"role": "system", "content": "You are a helpful assistant."},
{"role": "user", "content": "What's the weather in NYC and LA simultaneously?"}
]

response = client.chat.completions.create(
model="gpt-4o",
messages=messages,
tools=tools,
tool_choice="auto"
)

if response.choices[0].message.tool_calls:
num_calls = len(response.choices[0].message.tool_calls)
print(f"\nParallel tool calls made: {num_calls}")
for tc in response.choices[0].message.tool_calls:
print(f" - {tc.function.name}({tc.function.arguments})")

Saída Esperada

============================================================
Test 1: Weather query (should trigger get_weather)
============================================================
[Agent] Calling: get_weather({"location": "Seattle, WA", "unit": "celsius"})
Agent: The current weather in Seattle is 22°C and partly cloudy with 65% humidity.

============================================================
Test 2: Product search (should trigger search_products)
============================================================
[Agent] Calling: search_products({"query": "headphones", "max_price": 200})
Agent: I found 2 headphones under $200:
- Headphones Basic: $149.99

============================================================
Test 3: No tool needed (general knowledge)
============================================================
Agent: The capital of France is Paris.

Parallel tool calls made: 2
- get_weather({"location": "New York, NY"})
- get_weather({"location": "Los Angeles, CA"})

Quebra & conserta

CenárioSintomaCausa RaizCorreção
tool_call_id ausente na resposta400 Bad RequestMensagem de resposta da ferramenta deve incluir o tool_call_id correspondenteGaranta que cada resposta de ferramenta referencia o tool_call.id correto
Função retorna não-stringTypeErrorO content da mensagem de ferramenta deve ser uma string JSONSempre use json.dumps() no valor de retorno da função
Loop infinitoAgente continua chamando ferramentasSem condição de saída ou ferramenta retorna erroAdicione contagem máxima de iterações; valide respostas das ferramentas
tool_choice: "required"Modelo sempre chama uma ferramenta mesmo quando desnecessárioForçando uso de ferramentaUse "auto" para deixar o modelo decidir; use "required" apenas para uso garantido de ferramenta
Incompatibilidade de schemaModelo gera tipos de argumento erradosSchema de parâmetros da função muito vagoAdicione descriptions, enums e exemplos ao schema de parâmetros

Verificação de Conhecimento

1. Qual é a principal diferença entre um agente de IA e um chatbot?

2. No function calling do Azure OpenAI, o que acontece quando tool_choice é definido como 'auto'?

3. Quando o modelo retorna tool_calls na resposta, o que você deve incluir na mensagem de ferramenta subsequente?

4. Como o Azure OpenAI lida com múltiplas chamadas de ferramenta em uma única resposta?

5. Qual é o formato correto para definir parâmetros de função no array de tools?

Limpeza

az group delete --name rg-ai102-agents --yes --no-wait

Saiba Mais