Como o LangChain implementa a autoconsulta

Nov 16, 20234 min read

LangChain é uma biblioteca open-source super popular para orquestração de LLM. Recentemente, eles adicionaram o recuperador “Self Query”. O recuperador “Self Query” permite que você use o LangChain para consultar um banco de dados vetorial como o Milvus. Vamos dar uma olhada em como esse recuperador self-query é implementado. Abordamos as linhas 189 a 233 do arquivo base.py na pasta self-query. Este post também aborda from_llm, o único método de classe.

Neste post, abordaremos:

  • A definição do método de classe Self Query
  • Analisando os parâmetros de Self-Query
  • Criando a cadeia LLM
  • Retornando um recuperador Self Query

Definição do método de classe self query

O único método de classe para a classe base self query é from_llm. Há oito parâmetros especificados e um para nos permitir passar argumentos de palavra-chave (kwargs). Você pode notar que o primeiro “parâmetro” da classe é cls. Se você não tem formação formal em Python, a diferença entre cls e self é simplesmente uma questão de estilo e uso, de acordo com a PEP8.

Há quatro parâmetros obrigatórios para criar uma classe self query: llm, vectorstore, document_contents e metadata_field_info.

  • llm serve para passar um modelo de linguagem.
  • vectorstore é usado para passar um armazenamento vetorial como o Milvus.
  • O nome do parâmetro document_contents é um pouco enganoso. Ele não se refere ao conteúdo real dos documentos armazenados, mas sim a uma breve descrição deles.
  • metadata_field_info é uma sequência de objetos AttributeInfo, dicionários contendo informações sobre os dados no banco de dados vetorial.

Depois dos parâmetros obrigatórios vêm os parâmetros opcionais. Também há quatro deles: structured_query_translator, chain_kwargs, enable_limit e use_original_query. Os dois primeiros têm como padrão None, e o segundo, False.

O parâmetro structured_query_translator nos permite passar um tradutor. Tradutores convertem expressões em declarações de filtro para cada banco de dados vetorial. Essas declarações de filtro são passadas para chain_kwargs como “allowed_comparators” ou “allowed_operators,” dependendo de seu uso. Cada armazenamento vetorial tem comparadores e operadores únicos. Por exemplo, estas são as expressões booleanas permitidas para o Milvus.

Usando o parâmetro enable_limit, podemos decidir se habilitamos o operador limit. Esse operador é um recurso nativo do LangChain que restringe o número de documentos a serem recuperados. O parâmetro final é use_original_query, que determina se queremos utilizar nossa consulta original ou a gerada pelo LLM.

       @classmethod
       def from_llm(
           cls,
           llm: BaseLanguageModel,
           vectorstore: VectorStore,
           document_contents: str,
           metadata_field_info: Sequence[Union[AttributeInfo, dict]],
           structured_query_translator: Optional[Visitor] = None,
           chain_kwargs: Optional[Dict] = None,
           enable_limit: bool = False,
           use_original_query: bool = False,
           **kwargs: Any,
       ) -> "SelfQueryRetriever":

Analisando os parâmetros de self query

Deixe-me explicar como lidamos com os parâmetros. Com base nos parâmetros passados, usamos uma série de instruções if para determinar o que fazer.

Primeiro, verificamos se há um tradutor de consulta estruturada já definido. Caso contrário, usamos o tradutor integrado para o armazenamento vetorial definido.

Em seguida, verificamos os argumentos de palavra-chave da cadeia. Podemos defini-los com os valores passados ou mantê-los em um dicionário vazio. Continuamos a verificar esses argumentos para as duas instruções if a seguir. As duas chaves que procuramos são os comparadores e operadores permitidos. Essas chaves determinam como podemos escrever as expressões de filtro.

           if structured_query_translator is None:
               structured_query_translator = _get_builtin_translator(vectorstore)
           chain_kwargs = chain_kwargs or {}
           if (
               "allowed_comparators" not in chain_kwargs
               and structured_query_translator.allowed_comparators is not None
           ):
               chain_kwargs[
                   "allowed_comparators"
               ] = structured_query_translator.allowed_comparators
           if (
               "allowed_operators" not in chain_kwargs
               and structured_query_translator.allowed_operators is not None
           ):
               chain_kwargs[
                   "allowed_operators"
               ] = structured_query_translator.allowed_operators

Criando a cadeia LLM

Com tudo definido, agora podemos criar nosso construtor de consultas. Nesta etapa, fazemos uma chamada para a função load_query_constructor_runnable dos construtores de consultas. Vamos nos aprofundar mais nesta etapa em outro artigo.

Precisamos passar o LLM, a descrição do conteúdo do documento, os campos de metadados, se queremos ou não habilitar o limite, e os argumentos de palavra-chave a serem passados para a cadeia. Depois de definirmos todos esses elementos, a função retorna um objeto Runnable, que nos permite executar um script especificado.

           query_constructor = load_query_constructor_runnable(
               llm,
               document_contents,
               metadata_field_info,
               enable_limit=enable_limit,
               **chain_kwargs,
           )

Retornando um recuperador de autoconsulta

No final deste método de classe, precisamos retornar o recuperador de autoconsulta. Este método retorna uma instância da classe de autoconsulta. Passamos o construtor de consultas que acabamos de definir, junto com o armazenamento vetorial passado, se deve ou não usar a consulta original, o tradutor e uma lista de argumentos de palavra-chave.

           return cls(
               query_constructor=query_constructor,
               vectorstore=vectorstore,
               use_original_query=use_original_query,
               structured_query_translator=structured_query_translator,
               **kwargs,
           )

Resumo de como o LangChain implementa a autoconsulta

Neste artigo, abordamos como o LangChain implementa um conceito que eles chamam de “self-querying”. É uma maneira de criar uma aplicação simples de geração aumentada por recuperação (RAG). Ela usa todos os mesmos componentes: um LLM, um banco de dados vetorial e alguns prompts para fazer a interface com o LLM.

A autoconsulta é um bloco de código bastante grande no LangChain, mas este artigo aborda especificamente o método de classe from_llm. Este método nos permite criar um app RAG passando apenas quatro campos obrigatórios. O LLM, o banco de dados vetorial, uma descrição dos documentos e as informações de metadados. Quer saber mais sobre LLMs e bancos de dados vetoriais? Venha conversar conosco no Discord.

Atualizado em Jul 09, 2026