← Voltar a AI Engineer — DEUS.ai

🟡 B — APIs e Backend para AI

AI Engineer — DEUS.ai

Apresentação

🔌 APIs e Backend para AI

AI Engineers constroem serviços, não apenas modelos. A API é a interface entre o sistema de AI e os consumidores.


🎯 Frase que impressiona

Quando desenho APIs de AI, penso em três coisas: contratos claros com Pydantic, streaming para casos de uso sensíveis à latência, e degradação graciosa quando o LLM subjacente falha.


Estrutura típica de uma API de AI

Client → API Gateway / Load Balancer → FastAPI Backend
                                            ↓
                                    Auth / Rate Limit
                                            ↓
                                    /v1/chat (streaming)
                                    /v1/embed (batch)
                                    /v1/ingest (async)
                                            ↓
                                    LLM Service | Embedding Service | Queue

1️⃣ Frameworks — FastAPI vs Flask

FastAPIFlask
AsyncNativoSíncrono (ou gevent)
ValidaçãoPydantic automáticoManual
OpenAPI/docs, /redoc geradosAdd-on
PerformanceMelhor para I/O bound (LLM calls)Adequado para load baixo

Para LLMs: FastAPI — chamadas a APIs externas são I/O bound; async aproveita melhor.


2️⃣ Endpoints típicos para AI

  • POST /v1/chat — Chat completo; suporta streaming (SSE ou chunked)
  • POST /v1/embed — Embedding; aceita batch (array de textos)
  • POST /v1/ingest — Ingestão de documentos; async, retorna job_id
  • GET /v1/health — Liveness: está vivo? Readiness: consegue servir? (DB, LLM API)

3️⃣ Validação com Pydantic

class ChatRequest(BaseModel):
    messages: list[dict]
    model: str = "gpt-4o-mini"
    temperature: float = Field(ge=0, le=2)
    max_tokens: int = Field(ge=1, le=4096)

class ChatResponse(BaseModel):
    content: str
    usage: TokenUsage

Validação automática: 422 se formato errado. Schemas no OpenAPI para clientes.


4️⃣ Streaming — Server-Sent Events (SSE)

Para LLMs: devolver tokens à medida que o modelo gera. Melhor UX (TTFT).

from fastapi.responses import StreamingResponse

async def stream_chat(request: ChatRequest):
    async def generate():
        async for token in llm.astream(request.messages):
            yield f"data: {json.dumps({'token': token})}\n\n"
    return StreamingResponse(generate(), media_type="text/event-stream")

Alternativa: StreamingResponse com text/plain e chunked encoding. Cliente processa linha a linha.


5️⃣ Dependency Injection

def get_llm() -> LLM:
    return llm_client  # singleton ou pool

@app.post("/chat")
async def chat(req: ChatRequest, llm: LLM = Depends(get_llm)):
    return await llm.ainvoke(req.messages)

Uso: Injetar DB, auth, config, serviços externos. Facilita testes (mock do Depends).


6️⃣ Background Tasks vs Queue

BackgroundTasksQueue (Celery, Kafka)
QuandoTarefas rápidas (<30s)Tarefas longas, retry
OndeMesmo processoWorker separado
RetryManualAutomático
EscalaLimitado ao processoEscala workers

Exemplo: Ingestão de documento → Queue. Logging pós-response → BackgroundTasks.


7️⃣ Conceitos essenciais

  • Idempotência: POST com idempotency key; retry = mesmo resultado.
  • Rate limiting: Token bucket ou sliding window por user/API key. Redis para estado distribuído.
  • Autenticação: JWT, API keys (header X-API-Key), OAuth2.
  • Paginação: Cursor-based (?cursor=xxx&limit=20) melhor que offset para listas grandes.
  • CORS: Configurar CORSMiddleware se o frontend está noutro domínio.

8️⃣ Timeouts e Retries para LLM APIs

  • Timeout: 30-60s para geração; 5-10s para embedding.
  • Retry: Só em 429, 503, timeout. Exponential backoff: 1s, 2s, 4s. Max 3 retries.
  • Circuit breaker: Após N falhas, falhar rápido; half-open para testar recuperação.

9️⃣ Health Checks

  • /health/live — Liveness: processo está vivo. K8s usa para restart.
  • /health/ready — Readiness: DB conectado? LLM API acessível? K8s usa para traffic.

Se readiness falha, o pod deixa de receber tráfego mas não é morto.


🔟 Versionamento de API

  • URL: /v1/chat, /v2/chat — comum, explícito.
  • Header: Accept-Version: 2 — menos intrusivo.
  • Para LLMs: Permite evoluir schemas de prompts, adicionar campos, sem quebrar clientes antigos.

1️⃣1️⃣ Error Handling

  • 400 — Bad request (validação falhou)
  • 401 — Unauthorized
  • 429 — Rate limit exceeded
  • 500 — Erro interno (não expor detalhes ao cliente)
  • 503 — Service unavailable (LLM API down)

Custom exception handlers para respostas consistentes.


1️⃣2️⃣ Logging e Observabilidade

  • Request ID: Gerar em middleware; propagar a todos os logs.
  • Log estruturado: JSON com request_id, user_id, latency, tokens_used.
  • Métricas: Latência p50/p99, taxa de erro, tokens/request.

Ferramentas

  • FastAPI — framework principal
  • Pydantic — validação, schemas
  • Tenacity / backoff — retry com backoff
  • Starlette — base do FastAPI (middleware, responses)

Zona de prática

Sem perguntas. Clica em Editar para adicionar.