Integração inteligente: APIs GraphQL, gRPC e IA em ação

Integração inteligente: APIs GraphQL, gRPC e IA em ação
Objetivo: mostrar como projetar integrações entre sistemas usando GraphQL, gRPC e protocolos de autorização modernos, aproveitando modelos de IA para transformar e enriquecer dados durante a troca de mensagens.
Introdução
No cenário corporativo atual, a troca de informações entre plataformas deixou de ser pontual e passou a ser contínua, orientada a eventos e, cada vez mais, inteligente. Enquanto os primeiros projetos de integração se apoiavam em chamadas síncronas simples, hoje temos à disposição:
- GraphQL – permite que o consumidor escolha exatamente os campos que precisa, reduzindo o volume de dados trafegados.
- gRPC – comunicação binária de alta performance, ideal para pipelines de processamento intensivo.
- OAuth2 – padrão de autorização que garante acesso seguro a recursos distribuídos.
- Modelos de IA – adicionam camada de enriquecimento, como classificação automática, extração de entidades ou geração de respostas.
Desenvolvimento
1. Definindo o contrato de integração
Antes de escrever uma linha de código, é fundamental descrever o contrato entre os sistemas. Duas abordagens populares são:
| Tecnologia | Quando usar | Principais vantagens |
|---|---|---|
| OpenAPI (especificação Swagger) | Integrações HTTP tradicionais, documentação automática | Ferramentas de teste, geração de SDKs |
| Protocol Buffers (para gRPC) | Comunicação de alta performance, streaming bidirecional | Serialização compacta, suporte a múltiplas linguagens |
Para este exemplo, vamos combinar OpenAPI para expor um endpoint HTTP que aceita solicitações de enriquecimento via IA e Protocol Buffers para o canal interno de alta velocidade entre micro‑serviços.
1.1. Especificação OpenAPI (YAML)
openapi: 3.0.3
info:
title: Enriquecimento de Dados
version: 1.0.0
paths:
/enrich:
post:
summary: Envia texto bruto e recebe informações enriquecidas
security:
- oauth2: [enrich:write]
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/EnrichRequest'
responses:
'200':
description: Resultado do enriquecimento
content:
application/json:
schema:
$ref: '#/components/schemas/EnrichResponse'
components:
securitySchemes:
oauth2:
type: oauth2
flows:
clientCredentials:
tokenUrl: https://auth.example.com/oauth2/token
scopes:
enrich:write: Permite enviar dados para enriquecimento
schemas:
EnrichRequest:
type: object
properties:
text:
type: string
description: Texto livre a ser analisado
EnrichResponse:
type: object
properties:
sentiment:
type: string
enum: [positive, neutral, negative]
entities:
type: array
items:
type: string
summary:
type: string
Dica: o uso de client credentials simplifica a autenticação entre serviços sem necessidade de interação humana.
2. Implementando o endpoint HTTP com GraphQL
Embora o contrato acima seja OpenAPI, podemos expor um gateway GraphQL que consuma o mesmo serviço interno. O gateway oferece flexibilidade ao cliente final, que pode solicitar apenas os campos desejados.
2.1. Servidor GraphQL em Python (Ariadne + FastAPI)
# file: graphql_server.py
from fastapi import FastAPI, Request, Depends
from ariadne import gql, make_executable_schema, QueryType, MutationType
from ariadne.asgi import GraphQL
import httpx
import os
API_URL = "http://localhost:8000/enrich"
TOKEN_URL = "https://auth.example.com/oauth2/token"
CLIENT_ID = os.getenv("CLIENT_ID")
CLIENT_SECRET = os.getenv("CLIENT_SECRET")
type_defs = gql("""
type EnrichResult {
sentiment: String!
entities: [String!]!
summary: String!
}
type Query {
_empty: String
}
type Mutation {
enrich(text: String!): EnrichResult!
}
""")
mutation = MutationType()
async def get_access_token() -> str:
async with httpx.AsyncClient() as client:
resp = await client.post(
TOKEN_URL,
data={"grant_type": "client_credentials"},
auth=(CLIENT_ID, CLIENT_SECRET),
)
resp.raise_for_status()
return resp.json()["access_token"]
@mutation.field("enrich")
async def resolve_enrich(_, info, text):
token = await get_access_token()
async with httpx.AsyncClient() as client:
resp = await client.post(
API_URL,
json={"text": text},
headers={"Authorization": f"Bearer {token}"}
)
resp.raise_for_status()
return resp.json()
schema = make_executable_schema(type_defs, mutation)
app = FastAPI()
app.add_route("/graphql", GraphQL(schema, debug=True))
Como funciona:
enrich(text: "..."). /enrich). 2.2. Testando a mutação
mutation {
enrich(text: "O novo modelo de IA da OpenAI superou as expectativas.") {
sentiment
entities
summary
}
}
Resultado esperado:
{
"data": {
"enrich": {
"sentiment": "positive",
"entities": ["OpenAI", "modelo de IA"],
"summary": "A IA da OpenAI superou as expectativas."
}
}
}
3. Canal interno de alta performance com gRPC
Para processar grandes volumes de documentos em lote, utilizamos gRPC. O serviço recebe um stream de textos, chama a IA e devolve um stream de resultados. Essa abordagem reduz latência e permite paralelismo nativo.
3.1. Definição do proto
// file: enrich.proto
syntax = "proto3";
package enrich;
service Enricher {
// Recebe um fluxo de textos e devolve um fluxo de respostas
rpc EnrichStream (stream EnrichRequest) returns (stream EnrichResponse);
}
message EnrichRequest {
string text = 1;
}
message EnrichResponse {
string sentiment = 1;
repeated string entities = 2;
string summary = 3;
}
3.2. Servidor gRPC em Go (exemplo conciso)
// file: server.go
package main
import (
"context"
"io"
"log"
"net"
pb "example.com/enrich"
"google.golang.org/grpc"
"github.com/sashabaranov/go-openai"
)
type server struct {
pb.UnimplementedEnricherServer
aiClient openai.Client
}
func (s server) EnrichStream(stream pb.Enricher_EnrichStreamServer) error {
for {
req, err := stream.Recv()
if err == io.EOF {
return nil
}
if err != nil {
return err
}
// Chamada simplificada à API da OpenAI
resp, err := s.aiClient.CreateChatCompletion(context.Background(), openai.ChatCompletionRequest{
Model: "gpt-4o-mini",
Messages: []openai.ChatCompletionMessage{
{Role: "system", Content: "Analise o texto e retorne sentimento, entidades e resumo."},
{Role: "user", Content: req.Text},
},
})
if err != nil {
return err
}
// Parsing fictício da resposta
result := parseOpenAIResponse(resp.Choices[0].Message.Content)
if err := stream.Send(&pb.EnrichResponse{
Sentiment: result.Sentiment,
Entities: result.Entities,
Summary: result.Summary,
}); err != nil {
return err
}
}
}
func main() {
lis, err := net.Listen("tcp", ":50051")
if err != nil {
log.Fatalf("failed to listen: %v", err)
}
s := grpc.NewServer()
pb.RegisterEnricherServer(s, &server{
aiClient: openai.NewClient("YOUR_OPENAI_API_KEY"),
})
log.Println("gRPC server listening on :50051")
if err := s.Serve(lis); err != nil {
log.Fatalf("failed to serve: %v", err)
}
}
Observação: o código acima usa a biblioteca oficial
go-openai. O métodoparseOpenAIResponsedeve converter o texto retornado em estrutura tipada; a implementação depende do


