Como integrar LLMs em sistemas legados via API sem reescrever tudo

A integração de Large Language Models (LLMs) em sistemas legados é um dos desafios mais estratégicos para empresas que desejam modernizar suas operações sem incorrer nos altos custos e riscos de uma reescrita completa. Este artigo apresenta um roteiro prático, baseado no contexto de Temas — Lista Final (1200 temas), para conectar LLMs a sistemas existentes através de APIs, preservando o investimento original e adicionando inteligência artificial de forma incremental.

1. Diagnóstico do sistema legado e mapeamento de pontos de integração

Antes de qualquer intervenção técnica, é essencial realizar um diagnóstico detalhado do sistema legado. Identifique módulos com baixo acoplamento, como sistemas de relatórios, consultas a bases de dados ou processos de validação de documentos. Avalie gargalos de processamento manual — tarefas repetitivas como classificação de tickets, extração de informações de e-mails ou geração de resumos são candidatas ideais.

Defina critérios claros para selecionar funcionalidades: baixo risco de erro, alta frequência de uso e disponibilidade de dados históricos para validação. Por exemplo, um sistema de CRM legado pode ter um módulo de análise de sentimentos em feedbacks de clientes que opera manualmente — esse é um ponto perfeito para integração com LLM.

2. Estratégias de comunicação sem reescrever o core

A chave para evitar reescritas é criar uma camada de abstração entre o legado e o LLM. Implemente um API Gateway ou middleware que atue como tradutor entre os protocolos do sistema antigo (SOAP, RPC, filas) e APIs REST modernas.

Para operações assíncronas, utilize webhooks ou filas de mensagens como RabbitMQ ou Kafka. O sistema legado publica eventos em uma fila, o middleware consome, processa com o LLM e retorna o resultado. Exemplo prático:

# Exemplo de middleware com fila RabbitMQ
import pika
import requests

def process_message(ch, method, properties, body):
    # Dados do legado chegam como JSON
    data = json.loads(body)
    # Envia para API do LLM
    response = requests.post(
        "https://api.llm-provider.com/v1/analyze",
        json={"text": data["feedback"], "task": "sentiment"}
    )
    # Retorna resultado para o legado via callback
    callback_url = data["callback"]
    requests.post(callback_url, json=response.json())

connection = pika.BlockingConnection(pika.ConnectionParameters('localhost'))
channel = connection.channel()
channel.basic_consume(queue='legacy_tasks', on_message_callback=process_message)
channel.start_consuming()

Crie endpoints REST simples no próprio legado para expor dados sem modificar a lógica interna. Um endpoint /api/v1/consulta-cliente pode ser adicionado sem alterar o core do sistema.

3. Projeto da camada de API para o LLM

Defina schemas de entrada e saída compatíveis com o formato do sistema legado. Se o legado usa XML, crie um adaptador que converta para JSON antes de enviar ao LLM. Utilize prompts estruturados e templates reutilizáveis:

# Template de prompt padronizado
PROMPT_TEMPLATE = """
Sistema: Classifique o sentimento do feedback abaixo como POSITIVO, NEUTRO ou NEGATIVO.
Contexto: {contexto_cliente}
Feedback: {texto_feedback}
Classificação:
"""

Implemente tratamento de erros com fallback automático para o processamento original. Se o LLM falhar ou exceder o timeout, o sistema deve retornar ao fluxo legado sem interromper o usuário:

def call_llm_with_fallback(data):
    try:
        response = requests.post(LLM_URL, json=data, timeout=5)
        return response.json()
    except (requests.Timeout, requests.ConnectionError):
        # Fallback para lógica original do legado
        return legacy_processor.process(data)

4. Adaptação de dados e transformação de formatos

Sistemas legados frequentemente armazenam dados em formatos proprietários (COBOL, mainframe, SQL antigo). Crie scripts ETL leves para converter esses dados para JSON ou XML. Por exemplo, um script Python que lê arquivos de posicionamento fixo e os transforma:

def parse_cobol_record(record):
    # Formato fixo: campo1 (10 chars), campo2 (20 chars), campo3 (5 chars)
    return {
        "id": record[0:10].strip(),
        "nome": record[10:30].strip(),
        "valor": float(record[30:35].strip())
    }

Normalize campos com vocabulário controlado para evitar ambiguidades. Se o legado usa códigos internos (ex: "ST" para "status"), crie um mapeamento explícito. Implemente caching de embeddings ou respostas frequentes usando Redis para reduzir latência e custos:

import redis
cache = redis.Redis(host='localhost', port=6379)

def get_llm_response(prompt):
    cache_key = hashlib.md5(prompt.encode()).hexdigest()
    cached = cache.get(cache_key)
    if cached:
        return json.loads(cached)
    response = call_llm(prompt)
    cache.setex(cache_key, 3600, json.dumps(response))  # Cache por 1 hora
    return response

5. Validação e segurança na integração

A segurança é crítica ao expor sistemas legados para APIs externas. Implemente autenticação via API keys ou OAuth entre o middleware e o LLM. Use tokens JWT para comunicação interna. Sanitize todas as entradas do usuário antes de enviar ao LLM para evitar injeção de prompt:

def sanitize_input(user_input):
    # Remove caracteres de controle e comandos suspeitos
    import re
    return re.sub(r'[<>\n\r\t]', ' ', user_input[:500])

Mantenha logging detalhado de todas as chamadas ao LLM, incluindo prompt, resposta e latência. Isso permite auditoria e rastreamento de decisões tomadas pelo modelo.

6. Testes e monitoramento da nova funcionalidade

Realize testes A/B comparando a saída do LLM com a lógica original. Para cada requisição, execute ambos os caminhos e compare resultados. Calcule métricas como precisão, recall e desvio médio.

Monitore tempo de resposta, taxa de sucesso e custo por chamada. Crie um dashboard com alertas para degradação ou desvios de comportamento. Exemplo de métricas:

# Métricas para monitoramento
- Latência média: < 2 segundos
- Taxa de sucesso: > 99%
- Custo por chamada: < $0.01
- Taxa de fallback: < 5%

7. Estratégia de rollout e manutenção contínua

Implante gradualmente usando feature flags. Ative o LLM apenas para um subconjunto de usuários (ex: 10%) e monitore o impacto. Documente toda a camada de integração — diagramas de fluxo, schemas de dados e prompts utilizados — para facilitar a manutenção por equipes que conhecem o legado.

Estabeleça um plano de atualização de prompts e fine-tuning conforme o sistema legado evolui. Novos campos, regras de negócio ou regulamentações podem exigir ajustes nos templates.

Conclusão

Integrar LLMs em sistemas legados via API é uma estratégia viável e de baixo risco quando executada com planejamento. Ao criar uma camada de abstração, usar filas de mensagens e implementar fallbacks robustos, é possível adicionar inteligência artificial sem reescrever o core do sistema. O resultado é uma modernização incremental que preserva o investimento existente enquanto abre caminho para inovações futuras.

Referências