09-04-05 — Desafio: agente customer support com RAG sobre FAQs
TL;DR
Desafio prático de fechamento do Módulo 09: construa um agente de customer support com RAG sobre FAQs usando o AI Foundry Agent Service, com tracing habilitado e evaluation automatizada. Tudo em Python com o SDK azure-ai-projects. Tempo estimado: 2–4 horas. Ao final você tem um agente funcionando que pode ser estendido para qualquer cliente .NET da Impar.
O que você vai construir
"""
ARQUITETURA DO DESAFIO:
FAQs (Markdown/PDF)
│
▼
Vector Store (Foundry)
│
▼
Agent com file_search + system prompt personalizado
│
▼
FastAPI endpoint → conversas com histórico por session
│
▼
Tracing no Azure Monitor
Evaluation semanal automatizada
"""
Pré-requisitos
- Conta Azure com subscription ativa
- AI Foundry Hub + Projeto criados (ver 09-01-02)
- Azure OpenAI GPT-4o deployado no Hub
- Python 3.11+ com:
pip install azure-ai-projects azure-identity fastapi uvicorn azure-ai-evaluation
Passo 1: Preparar FAQs e criar Vector Store
import os
from pathlib import Path
from azure.ai.projects import AIProjectClient
from azure.identity import DefaultAzureCredential
client = AIProjectClient.from_connection_string(
os.environ["AZURE_AI_FOUNDRY_CONNECTION_STRING"],
DefaultAzureCredential()
)
# Upload dos arquivos de FAQ
faq_files = list(Path("./faqs").glob("*.md"))
file_ids = []
for faq_path in faq_files:
print(f"Uploading: {faq_path.name}")
with open(faq_path, "rb") as f:
uploaded = client.agents.upload_file_and_poll(
file=f, purpose="assistants"
)
file_ids.append(uploaded.id)
# Criar Vector Store com todos os FAQs
vector_store = client.agents.create_vector_store_and_poll(
file_ids=file_ids,
name="faq-customer-support"
)
print(f"Vector Store criado: {vector_store.id}")
# Salve este ID! Vai usar nos próximos passos.
Passo 2: Criar o agente
from azure.ai.projects.models import FileSearchTool
SYSTEM_PROMPT = """Você é um assistente de suporte ao cliente especializado.
REGRAS:
- Responda APENAS com base nos documentos de FAQ fornecidos
- Se não encontrar a resposta nos FAQs, diga claramente: "Não encontrei essa informação nos nossos FAQs. Posso conectar você com um especialista?"
- Tom: profissional e direto, em português
- Não invente informações, mesmo que pareça óbvio
- Para perguntas técnicas complexas, ofereça escalar para time técnico"""
agent = client.agents.create_agent(
model="gpt-4o",
name="support-agent-v1",
instructions=SYSTEM_PROMPT,
tools=[FileSearchTool().as_dict()],
tool_resources={
"file_search": {
"vector_store_ids": [vector_store.id]
}
}
)
print(f"Agente criado: {agent.id}")
Passo 3: API FastAPI com sessões
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
import asyncio
app = FastAPI(title="Customer Support Agent API")
# Cache de threads por session_id
thread_cache: dict[str, str] = {}
class ChatRequest(BaseModel):
session_id: str
message: str
class ChatResponse(BaseModel):
session_id: str
response: str
thread_id: str
@app.post("/chat", response_model=ChatResponse)
async def chat(request: ChatRequest):
# Reutiliza thread existente ou cria nova
if request.session_id not in thread_cache:
thread = client.agents.create_thread()
thread_cache[request.session_id] = thread.id
thread_id = thread_cache[request.session_id]
# Adiciona mensagem do usuário
client.agents.create_message(
thread_id=thread_id,
role="user",
content=request.message
)
# Executa o agente (aguarda conclusão)
run = client.agents.create_and_process_run(
thread_id=thread_id,
assistant_id=agent.id
)
if run.status == "failed":
raise HTTPException(500, f"Agent run failed: {run.last_error}")
# Pega última mensagem do agente
messages = client.agents.list_messages(thread_id=thread_id)
last_response = messages.data[0].content[0].text.value
return ChatResponse(
session_id=request.session_id,
response=last_response,
thread_id=thread_id
)
# Rodar: uvicorn solution:app --reload --port 8000
Passo 4: Habilitar tracing
# Adicionar ao início do app (antes de criar o client)
from azure.monitor.opentelemetry import configure_azure_monitor
from opentelemetry import trace
configure_azure_monitor(
connection_string=os.environ["APPLICATIONINSIGHTS_CONNECTION_STRING"]
)
# Habilitar instrumentação automática do Foundry
client.telemetry.enable(
destination=client.telemetry.get_connection_string()
)
Passo 5: Evaluation automatizada (semanal)
# eval_weekly.py — rode via cron ou Azure Functions
from azure.ai.evaluation import evaluate, GroundednessEvaluator, RelevanceEvaluator
import json
# Coleta amostra de conversas da semana (do seu banco de logs)
eval_dataset = [
{"query": q, "response": r, "context": c}
for q, r, c in get_weekly_sample()
]
model_config = {
"azure_endpoint": os.environ["AZURE_AI_FOUNDRY_ENDPOINT"],
"azure_deployment": "gpt-4o",
"api_version": "2025-01-01-preview",
"credential": DefaultAzureCredential()
}
results = evaluate(
data=eval_dataset,
evaluators={
"groundedness": GroundednessEvaluator(model_config),
"relevance": RelevanceEvaluator(model_config)
}
)
# Alerta se qualidade caiu
grnd_avg = results["metrics"]["groundedness.groundedness"]
if grnd_avg < 3.5:
send_alert(f"⚠️ Qualidade caiu! Groundedness: {grnd_avg:.2f}")
print(f"Weekly eval: Groundedness={grnd_avg:.2f}")
Checklist de conclusão do desafio
- ☐ FAQs indexados no Vector Store
- ☐ Agente criado com file_search e system prompt
- ☐ API FastAPI respondendo em
localhost:8000/chat - ☐ Teste com 5 perguntas — respostas fundamentadas nos FAQs?
- ☐ Teste com 1 pergunta fora dos FAQs — agente confessa que não sabe?
- ☐ Tracing visível em ai.azure.com → Tracing
- ☐ Script de evaluation executando sem erros
✅ Próximos passos (extensões): (1) Adicionar autenticação à API via Entra; (2) Deploy no Azure App Service com Managed Identity; (3) Adicionar Content Safety (prompt shields); (4) Publicar como endpoint para Copilot Studio; (5) Substituir GPT-4o mini para reduzir custo.