How LangChain Implements Self Querying
LangChain is a super popular open-source library for LLM orchestration. Recently, they added the “Self Query” retriever. The “Self Query” retriever allows you to use LangChain to query a vector database like Milvus. Let’s take a look at how this self-query retriever is implemented. We cover lines 189 to 233 of the base.py
file in the self-query folder. This post also covers from_llm
, the only class method.
In this post, we’ll cover:
- The Self Query Class Method Definition
- Parsing the Self-Query Parameters
- Creating the LLM Chain
- Returning a Self Query Retriever
Self query class method definition
The only class method for the self query base class is from_llm
. There are eight specified parameters and one to allow us to pass keyword arguments (kwargs
). You may notice that the first “parameter” of the class is cls
. If you don't have formal training in Python, the difference between cls
and self
is simply a matter of style and usage, according to PEP8.
There are four required parameters for creating a self query class: llm
, vectorstore
, document_contents
, and metadata_field_info
.
llm
is for passing a language model.vectorstore
is used to pass a vector store like Milvus.- The name of the
document_contents
parameter is a bit misleading. It doesn’t refer to the actual contents of the stored documents but rather a short description of them. metadata_field_info
is a sequence ofAttributeInfo
objects, dictionaries containing information about the data in the vector database.
After the required parameters come the optional parameters. There are four of them as well: structured_query_translator
, chain_kwargs
, enable_limit
, and use_original_query
. The first two default to None
, and the second to False
.
The structured_query_translator
parameter lets us pass in a translator. Translators convert expressions into filter statements for each vector database. These filter statements get passed into chain_kwargs
as “allowed_comparators” or “allowed_operators,” depending on their usage. Each vector store has unique comparators and operators. For example, these are the allowed boolean expressions for Milvus.
Using the enable_limit
parameter, we can decide whether to enable the limit operator. This operator is a native feature of LangChain that restricts the number of documents to be retrieved. The final parameter is use_original_query
, which determines whether we want to utilize our original query or the one generated by 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 the self query parameters
Let me explain how we handle the parameters. Based on the parameters passed in, we use a series of if
statements to determine what to do.
First, we check if there is an already defined structured query translator. If not, we use the built-in translator for the defined vector store.
Next, we check the chain keyword arguments. We can set them to the values passed in or remain in an empty dictionary. We continue to check these arguments for the following two if
statements. The two keys we look for are the allowed comparators and operators. These keys determine how we can write the filter expressions.
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
Creating the LLM chain
With everything defined, we can now create our query constructor. In this step, we make a callout to the load_query_constructor_runnable
function from query constructors. We’ll dive deeper into this step in another article.
We need to pass in the LLM, document content description, metadata fields, whether or not we want to enable the limit, and the keyword arguments to pass to the chain. After we have defined all these elements, the function returns a Runnable
object, which allows us to execute a specified script.
query_constructor = load_query_constructor_runnable(
llm,
document_contents,
metadata_field_info,
enable_limit=enable_limit,
**chain_kwargs,
)
Returning a self query retriever
At the end of this class method, we need to return the self query retriever. This method returns an instance of the self query class. We pass in the query constructor we just defined, along with the passed-in vector store, whether or not to use the original query, the translator, and a list of keyword arguments.
return cls(
query_constructor=query_constructor,
vectorstore=vectorstore,
use_original_query=use_original_query,
structured_query_translator=structured_query_translator,
**kwargs,
)
Summary of how LangChain implements self querying
In this article, we’ve covered how LangChain implements a concept they label “self-querying.” It is a way to build a simple retrieval augmented generation (RAG) application. It uses all the same components: an LLM, a vector database, and some prompts to interface with the LLM.
Self querying is quite a large block of code in LangChain, but this article specifically covers the class method from_llm
. This method allows us to create an RAG app by passing only four required fields. The LLM, the vector database, a description of the documents, and the metadata information. Want to learn more about LLMs and vector databases? Come chat with us on Discord.
- Self query class method definition
- Parsing the self query parameters
- Creating the LLM chain
- Returning a self query retriever
- Summary of how LangChain implements self querying
Content
Start Free, Scale Easily
Try the fully-managed vector database built for your GenAI applications.
Try Zilliz Cloud for Free