Olá, Lucas. Como vai?
Sua análise foi cirúrgica e está totalmente correta. O que você enfrentou é um dos desafios mais comuns no desenvolvimento com frameworks de IA generativa como o LangChain: a inconsistência na formatação de saída das LLMs (output parsing).
Muitas vezes, uma pequena atualização no modelo padrão ou a variação na temperatura da API faz com que a IA adicione textos explicativos como "Aqui está o JSON:" ou use aspas diferentes, o que quebra o método apply_and_parse. A sua solução de capturar o prompt bruto com o qa_chain.prompt.format e tratar com Expressões Regulares (Regex) foi excelente e demonstra uma ótima autonomia de desenvolvimento.
Para enriquecer o seu pipeline de avaliação em RAG (Geração Aumentada por Recuperação) e evitar soluções manuais com Regex no futuro, existem algumas boas práticas e abordagens nativas do LangChain atualizado que ajudam a mitigar esse problema.
1. Transição para o Pydantic Output Parser (Abordagem Moderna)
O QAGenerateChain e o antigo apply_and_parse usavam estruturas mais rígidas de strings. Nas versões mais recentes, o LangChain recomenda fortemente o uso do PydanticOutputParser combinado com a nova sintaxe LCEL (LangChain Expression Language).
Com o Pydantic, você força a LLM a retornar um objeto estruturado de forma muito mais segura, pois as instruções de formato são injetadas dinamicamente no prompt. Veja um exemplo prático de como estruturar isso:
from langchain_core.output_parsers import PydanticOutputParser
from langchain_core.prompts import PromptTemplate
from pydantic import BaseModel, Field
# 1. Definimos o esquema de dados esperado
class QAPair(BaseModel):
query: str = Field(description="A pergunta baseada no contexto fornecido.")
answer: str = Field(description="A resposta correta para a pergunta gerada.")
# 2. Criamos o parser baseado no modelo Pydantic
parser = PydanticOutputParser(pydantic_object=QAPair)
# 3. Injetamos as instruções de formato no prompt
prompt = PromptTemplate(
template="Gere uma pergunta e resposta com base no documento.\n{format_instructions}\nDocumento: {doc}",
input_variables=["doc"],
partial_variables={"format_instructions": parser.get_format_instructions()}
)
# 4. Criamos a chain utilizando LCEL (operador |)
nova_qa_chain = prompt | llm | parser
2. Mecanismos de Correção Automática (Retry e Fixing Parsers)
Se o modelo ainda assim falhar em seguir as regras, o LangChain possui módulos específicos para tratar erros de parse sem que a aplicação quebre de imediato:
- OutputFixingParser: Se o parser principal falhar, ele pega a saída errada da LLM, envia para outra LLM junto com o erro cometido e pede: "Corrija este texto para que ele vire o JSON correto".
- RetryOutputParser: Tenta rodar a chain novamente passando o histórico anterior para que o modelo ajuste a resposta de forma automática.
Sobre o seu comentário a respeito dos cortes nos vídeos: você tem toda razão. Na Engenharia de Prompt e na construção de agentes RAG, o comportamento probabilístico das LLMs gera falhas e exceções a todo momento. Mostrar o processo de depuração (debugging), o ajuste fino de um prompt ou o tratamento de um JSON quebrado agrega um valor gigantesco para o aluno, pois reflete o dia a dia real do mercado de IA.
Agradecemos demais o seu feedback construtivo. Ele nos ajuda a refinar a abordagem didática dos próximos cursos e atualizações.
Espero que possa ter lhe ajudado!