Come LangChain implementa il self-querying

Nov 16, 20234 min read

LangChain è una libreria open-source super popolare per l’orchestrazione degli LLM. Di recente, hanno aggiunto il retriever “Self Query”. Il retriever “Self Query” ti permette di usare LangChain per interrogare un database vettoriale come Milvus. Diamo un’occhiata a come è implementato questo self-query retriever. Trattiamo le righe dalla 189 alla 233 del file base.py nella cartella self-query. Questo post tratta anche from_llm, l’unico metodo di classe.

In questo post, tratteremo:

  • La definizione del metodo di classe Self Query
  • Il parsing dei parametri Self-Query
  • La creazione della catena LLM
  • La restituzione di un Self Query Retriever

Definizione del metodo di classe self query

L’unico metodo di classe per la classe base self query è from_llm. Ci sono otto parametri specificati e uno per consentirci di passare argomenti keyword (kwargs). Potresti notare che il primo “parametro” della classe è cls. Se non hai una formazione formale in Python, la differenza tra cls e self è semplicemente una questione di stile e utilizzo, secondo PEP8.

Ci sono quattro parametri obbligatori per creare una classe self query: llm, vectorstore, document_contents e metadata_field_info.

  • llm serve per passare un modello linguistico.
  • vectorstore viene usato per passare un vector store come Milvus.
  • Il nome del parametro document_contents è un po’ fuorviante. Non si riferisce ai contenuti effettivi dei documenti archiviati, ma piuttosto a una loro breve descrizione.
  • metadata_field_info è una sequenza di oggetti AttributeInfo, dizionari contenenti informazioni sui dati nel database vettoriale.

Dopo i parametri obbligatori vengono i parametri opzionali. Anche questi sono quattro: structured_query_translator, chain_kwargs, enable_limit e use_original_query. I primi due hanno valore predefinito None, e il secondo False.

Il parametro structured_query_translator ci consente di passare un traduttore. I traduttori convertono le espressioni in istruzioni di filtro per ciascun database vettoriale. Queste istruzioni di filtro vengono passate in chain_kwargs come “allowed_comparators” o “allowed_operators,” a seconda del loro utilizzo. Ogni vector store ha comparatori e operatori unici. Ad esempio, queste sono le espressioni booleane consentite per Milvus.

Usando il parametro enable_limit, possiamo decidere se abilitare l’operatore limit. Questo operatore è una funzionalità nativa di LangChain che limita il numero di documenti da recuperare. Il parametro finale è use_original_query, che determina se vogliamo utilizzare la nostra query originale o quella generata dall’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":

Parsing dei parametri self query

Lasciami spiegare come gestiamo i parametri. In base ai parametri passati, usiamo una serie di istruzioni if per determinare cosa fare.

Per prima cosa, controlliamo se esiste un structured query translator già definito. In caso contrario, usiamo il traduttore integrato per il vector store definito.

Successivamente, controlliamo gli argomenti parola chiave della chain. Possiamo impostarli sui valori passati o lasciarli in un dizionario vuoto. Continuiamo a controllare questi argomenti per le due istruzioni if seguenti. Le due chiavi che cerchiamo sono i comparatori e gli operatori consentiti. Queste chiavi determinano come possiamo scrivere le espressioni di 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

Creazione della chain LLM

Con tutto definito, ora possiamo creare il nostro costruttore di query. In questo passaggio, richiamiamo la funzione load_query_constructor_runnable dai costruttori di query. Approfondiremo questo passaggio in un altro articolo.

Dobbiamo passare l’LLM, la descrizione del contenuto del documento, i campi di metadati, se vogliamo abilitare o meno il limite e gli argomenti parola chiave da passare alla chain. Dopo aver definito tutti questi elementi, la funzione restituisce un oggetto Runnable, che ci consente di eseguire uno script specificato.

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

Restituzione di un self query retriever

Alla fine di questo metodo di classe, dobbiamo restituire il self query retriever. Questo metodo restituisce un’istanza della classe self query. Passiamo il costruttore di query appena definito, insieme al vector store passato, se utilizzare o meno la query originale, il traduttore e un elenco di argomenti parola chiave.

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

Riepilogo di come LangChain implementa il self querying

In questo articolo abbiamo trattato come LangChain implementa un concetto che chiama “self-querying”. È un modo per creare una semplice applicazione di retrieval augmented generation (RAG). Utilizza tutti gli stessi componenti: un LLM, un database vettoriale e alcuni prompt per interfacciarsi con l’LLM.

Il self querying è un blocco di codice piuttosto ampio in LangChain, ma questo articolo tratta specificamente il metodo di classe from_llm. Questo metodo ci consente di creare un’app RAG passando solo quattro campi obbligatori. L’LLM, il database vettoriale, una descrizione dei documenti e le informazioni sui metadati. Vuoi saperne di più sugli LLM e sui database vettoriali? Vieni a chattare con noi su Discord.

Aggiornato il Jul 09, 2026