E aí, dev que já viu uma IA inventar uma política de reembolso que não existe? Ou pior: prometer um recurso que o produto não tem, e você ter que explicar pro cliente que “a máquina se confundiu”?
Pois é. Colocar um LLM pra atender clientes é fácil. Difícil é fazer ele responder com precisão, manter o tom corporativo e não alucinar quando não sabe a resposta.
Foi exatamente isso que um experimento acadêmico que conduzi recentemente em minha Pós-Graduação em Engenharia de IA procurou descobrir: como diferentes estruturas de prompt impactam o comportamento do modelo num cenário real de suporte SaaS. E o resultado? O prompt ajuda – e muito – mas não é suficiente. A virada de chave vem com RAG (Retrieval-Augmented Generation).
Neste post, vou te contar o que o experimento revelou, por que prompt engineering sozinho não resolve, e como implementar RAG na prática com Spring AI – do embedding ao vector store. Bora? 🚀
🔬 O experimento: 15 perguntas, 5 estratégias, 75 interações
O estudo simulou a CloudFlow, uma organização fictícia desenvolvida para o experimento, cuja proposta é oferecer uma plataforma SaaS de gestão de projetos para equipes remotas. O time de suporte recebe centenas de dúvidas diárias por chat e e-mail. A empresa queria usar um LLM para atendimento de primeiro nível, mas precisava entender como a estrutura do prompt afetava a qualidade, a consistência e a segurança das respostas.
Foram elaboradas 15 perguntas de clientes, cobrindo desde dúvidas simples (“Como altero a senha?”) até reclamações complexas (“Recebi uma cobrança duplicada”) e questões de conformidade (“Vocês armazenam dados em conformidade com a LGPD?”).
Cada pergunta foi submetida a 5 estratégias de prompt:
- Prompt Simples (Zero-Shot) – Sem contexto, sem papel, sem regra.
- Role Prompt – Define a persona: “Você é um especialista de suporte da CloudFlow. Seja profissional, educado e objetivo.”
- Estrutura Explícita de Saída – Força o formato: Saudação → Solução → Próximos Passos.
- Few-Shot – Fornece exemplos de como a resposta deve ser redigida.
- Restrições e Políticas (Guardrails) – “Nunca invente informações. Quando não souber, escale para um humano. Nunca prometa reembolsos.”
Cada execução foi repetida três vezes para medir consistência. No total, 75 interações avaliadas em clareza, completude, tom corporativo, segurança, consistência e risco de alucinação.
📊 O que o experimento revelou (e por que você deveria se importar)
A tabela abaixo resume os resultados médios:
| Critério | A (Simples) | B (Role) | C (Estruturado) | D (Few-Shot) | E (Políticas) |
|---|---|---|---|---|---|
| Clareza | 3 | 4 | 4 | 5 | 5 |
| Completude | 2 | 3 | 5 | 4 | 5 |
| Tom Corporativo | 2 | 5 | 4 | 5 | 5 |
| Segurança | 2 | 3 | 4 | 4 | 5 |
| Consistência | 2 | 3 | 4 | 5 | 5 |
| Risco de Alucinação | Alto | Médio | Médio | Baixo | Muito Baixo |
A conclusão é clara: o LLM é o mesmo, mas o comportamento muda completamente dependendo do contexto que você fornece.
- Role Prompt resolveu o tom, mas não a estrutura.
- Estrutura Explícita melhorou a completude, mas ainda deixava brechas para alucinação.
- Few-Shot trouxe consistência cirúrgica.
- Políticas (Guardrails) reduziram o risco de alucinação ao mínimo.
Nenhuma das estratégias, quando aplicada isoladamente, mostrou-se totalmente eficaz. Com base nos resultados obtidos, o estudo concluiu que a abordagem mais adequada é uma arquitetura híbrida, combinando Role Prompting, Estrutura de Saída, Few-Shot Learning, Políticas de Segurança e RAG para consultar informações do FAQ oficial.
RAG é a peça que faltava para evitar que o modelo “chute” quando não sabe a resposta.
🧩 O que é RAG (e por que ele resolve o problema da alucinação)
RAG significa Retrieval-Augmented Generation. Em português claro: em vez de confiar apenas no que o modelo aprendeu durante o treinamento, você recupera documentos relevantes de uma base de conhecimento e os injeta no prompt antes de pedir a resposta.
LLMs são treinados em grandes datasets, mas não são treinados nos seus dados privados. Treinar um modelo no seu domínio seria caro e demorado. Então, a alternativa é usar RAG para recuperar informações relevantes de um datastore e passá-las ao LLM junto com a pergunta.
O fluxo é mais ou menos assim:
Em vez de o modelo “inventar” a política de reembolso, ele consulta o documento oficial e responde com base nele. É a diferença entre um atendente que sabe a resposta e um que acha que sabe.
🛠️ Mãos à obra: RAG com Spring AI na prática
Vamos implementar o fluxo completo usando Spring AI. O artigo do meu parceiro Sivalabs me ajudou nessa missão.
1. Dependência e configuração
Adicione o starter do Spring AI para OpenAI (ou outro provedor):
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-openai-spring-boot-starter</artifactId> <version>1.0.0-M1</version> </dependency> Configure a API key no application.properties:
spring.ai.openai.api-key=${OPENAI_API_KEY} 2. Convertendo texto em embeddings
O EmbeddingModel transforma texto ou documentos em vetores:
@Component class MeuComponente { private final EmbeddingModel embeddingModel; MeuComponente(EmbeddingModel embeddingModel) { this.embeddingModel = embeddingModel; } void converterTextoParaEmbedding() { List<Embedding> embeddings = embeddingModel.embed("Eu gosto de Spring Boot"); List<Embedding> embeddingsDoc = embeddingModel.embed(new Document("Eu gosto de Spring Boot")); } } 3. Armazenando e recuperando do VectorStore
O VectorStore é a interface que abstrai o banco vetorial. Para desenvolvimento, use SimpleVectorStore (em memória). Para produção, PgVectorStore (PostgreSQL com extensão pgvector).
@Configuration class AppConfig { @Bean VectorStore vectorStore(EmbeddingModel embeddingModel) { return new SimpleVectorStore(embeddingModel); } } Uso:
@Component class MeuComponente { private final VectorStore vectorStore; MeuComponente(VectorStore vectorStore) { this.vectorStore = vectorStore; } void armazenarERecuperar() { List<Document> documentos = List.of( new Document("A CloudFlow oferece integração nativa com Slack na versão Enterprise."), new Document("A política de reembolso é de 30 dias corridos após a compra.") ); vectorStore.add(documentos); SearchRequest query = SearchRequest.query("Como funciona a integração com Slack?") .withTopK(2); List<Document> similares = vectorStore.similaritySearch(query); String contexto = similares.stream() .map(Document::getContent) .collect(Collectors.joining(System.lineSeparator())); } } O withTopK(2) limita a busca aos 2 documentos mais similares – evitando poluir o prompt com informação irrelevante.
4. Implementando o RAG com ChatClient
Agora o pulo do gato: recuperar os documentos, montar o prompt com contexto e chamar o LLM.
@RestController class RAGController { private final ChatClient chatClient; private final VectorStore vectorStore; RAGController(ChatClient.Builder builder, VectorStore vectorStore) { this.chatClient = builder.build(); this.vectorStore = vectorStore; } @GetMapping("/ai/suporte") String responderCliente(@RequestParam String pergunta) { // 1. Busca documentos relevantes List<Document> similares = vectorStore.similaritySearch( SearchRequest.query(pergunta).withTopK(3) ); String informacao = similares.stream() .map(Document::getContent) .collect(Collectors.joining(System.lineSeparator())); // 2. Monta o prompt com contexto e política de segurança String systemPrompt = """ Você é um agente de suporte sênior da CloudFlow. Use APENAS as informações abaixo para responder. Se a informação não estiver disponível, diga que não sabe e escale para um humano. Nunca prometa reembolsos ou ações que não pode executar. Informações: {informacao} """; // 3. Chama o modelo return chatClient.prompt() .system(systemPrompt.replace("{informacao}", informacao)) .user(pergunta) .call() .content(); } } Pronto. Agora o modelo não está mais “chutando” – ele está fundamentando a resposta em documentos reais e respeitando políticas de segurança. É a combinação de RAG (contexto recuperado) com guardrails (restrições explícitas).
📚 DocumentReader: de arquivos para embeddings
Em vez de criar Document na mão, você pode ler arquivos diretamente com os DocumentReader. O Spring AI oferece implementações como TextReader, JsonReader e PagePdfDocumentReader.
@Component class CarregadorDocumentos { private final VectorStore vectorStore; @Value("classpath:faq-cloudflow.txt") private Resource resource; CarregadorDocumentos(VectorStore vectorStore) { this.vectorStore = vectorStore; } @PostConstruct void carregar() { var textReader = new TextReader(resource); textReader.setCharset(Charset.defaultCharset()); List<Document> documentos = textReader.get(); vectorStore.add(documentos); } } Na prática, você carregaria sua base de conhecimento (FAQ, políticas, manuais) uma vez e ela ficaria disponível para consulta em tempo real.
⚖️ Prompt Engineering vs. RAG: quando usar cada um
| Abordagem | O que resolve | O que não resolve |
|---|---|---|
| Prompt Engineering | Tom, formato, persona, consistência básica | Falta de conhecimento factual; alucinação em perguntas específicas |
| RAG | Falta de conhecimento; fundamentação em dados reais | Tom e formato (precisam ser definidos no prompt) |
| Prompt + RAG | Ambos | Ainda requer guardrails e monitoramento |
A grande sacada do experimento da CloudFlow é que prompt engineering é necessário, mas não suficiente. Você pode ter o melhor role prompt do mundo – se o modelo não tiver acesso à informação correta, ele vai inventar.
RAG resolve a falta de conhecimento. Prompt engineering resolve o comportamento e o tom. Juntos, eles formam a base de um atendimento automatizado confiável.
💡 Dicas quentes para implementar RAG sem sofrer
1. 🎯 Ajuste o topK com cuidado
Buscar 3 documentos é um bom ponto de partida. Muitos documentos poluem o prompt; poucos podem deixar informação de fora. Teste e ajuste.
2. 🧹 Faça chunking inteligente
Documentos muito longos devem ser divididos em pedaços menores (chunks) antes de virar embeddings. Senão, a busca por similaridade fica imprecisa.
3. 🔒 Sempre inclua guardrails
RAG não impede alucinação completamente. O modelo ainda pode ignorar o contexto e inventar. Políticas explícitas (“use APENAS as informações fornecidas”) são essenciais.
4. 🏭 Use pgvector em produção
SimpleVectorStore é ótimo para desenvolvimento, mas para produção use PgVectorStore (PostgreSQL + pgvector) ou outro banco vetorial. O pgvector suporta índices HNSW para busca eficiente em larga escala.
5. 📊 Monitore e avalie
RAG não é “configure e esqueça”. Monitore a qualidade das respostas, colete feedback dos usuários e ajuste o topK, os prompts e a base de conhecimento continuamente.
🎯 Conclusão
O experimento da CloudFlow mostrou que o comportamento do LLM é moldado pela engenharia de contexto. Role prompt, estrutura de saída, few-shot e guardrails fazem diferença – e fazem muita diferença.
A raiz do problema é simples: LLMs não possuem conhecimento nativo sobre os dados da sua organização. Eles desconhecem políticas internas, FAQs e detalhes operacionais específicos. Sem mecanismos para acessar essas informações, inevitavelmente produzirão respostas baseadas em suposições, abrindo espaço para alucinações
A solução é combinar o melhor dos dois mundos:
- Prompt engineering para definir como o modelo se comporta (tom, formato, segurança).
- RAG para garantir o que ele sabe (dados reais, recuperados de uma base confiável).
Com Spring AI, isso é mais fácil do que parece: EmbeddingModel, VectorStore, DocumentReader e ChatClient cobrem todo o fluxo, do documento à resposta.
Da próxima vez que sua IA inventar uma política que não existe, lembre-se: o problema não é o modelo. É a falta de contexto.
Já usou RAG em produção? Ou ainda está no mundo do prompt puro? Conta aí nos comentários! 👇
SpringAI #RAG #LLM #PromptEngineering #Java #InteligenciaArtificial
📚 Referências
- Micro-capstone: Análise de Comportamento de LLM para Atendimento Corporativo (CloudFlow) – experimento com 15 perguntas e 5 estratégias de prompt.
- Sivalabs: Spring AI RAG using Embedding Models and Vector Databases – implementação prática de RAG com Spring AI, EmbeddingModel, VectorStore e DocumentReader.
- Spring AI Documentation:
QuestionAnswerAdvisoreRetrievalAugmentationAdvisorpara implementações prontas de RAG.
Quer mais? No próximo post vou mostrar como usar RetrievalAugmentationAdvisor para implementar RAG modular com Spring AI, incluindo re-ranking e filtragem de documentos. Até lá! 🚀
