- Memory: Stores chat history in a database and enables LLMs to have long-term conversations.
- Knowledge: Stores information in a vector database and provides LLMs with business context. (Here we will use LanceDB)
- Tools: Enable LLMs to take actions like pulling data from an API, sending emails or querying a database, etc.
Memory & knowledge make LLMs smarter while tools make them autonomous.
LanceDB is a vector database and its integration into Phidata makes it easy for us to provide a knowledge base to LLMs. It enables us to store information as embeddings and search for the results similar to ours using query.
What is a Knowledge Base?Knowledge Base is a database of information that the Assistant can search to improve its responses. This information is stored in a vector database and provides LLMs with business context, which makes them respond in a context-aware manner.While any type of storage can act as a knowledge base, vector databases offer the best solution for retrieving relevant results from dense information quickly.
Prerequisites: install and import necessary dependencies
Create a virtual environment- install virtualenv package
bash
- Create a directory for your project and go to the directory and create a virtual environment inside it.
bash
bash
bash
- from inside the project directory, run the following command to activate the virtual environment.
bash
bash
transcript.py and ollama_assistant.py or openai_assistant.py
Run the following command to deactivate the virtual environment if needed
bash
Step 1 - Create a Knowledge Base for AI Assistant using LanceDB
Check out the list of embedders supported by Phidata and their usage here. Here we have usedTextKnowledgeBase, which loads text/docx files to the knowledge base.
Let’s see all the parameters that TextKnowledgeBase takes -
| Name | Type | Purpose | Default |
|---|---|---|---|
path | Union[str, Path] | Path to text file(s). It can point to a single text file or a directory of text files. | provided by user |
formats | List[str] | File formats accepted by this knowledge base. | [".txt"] |
vector_db | VectorDb | Vector Database for the Knowledge Base. Phidata provides a wrapper around many vector DBs, you can import it like this - from phi.vectordb.lancedb import LanceDb | provided by user |
num_documents | int | Number of results (documents/vectors) that vector search should return. | 5 |
reader | TextReader | Phidata provides many types of reader objects which read data, clean it and create chunks of data, encapsulate each chunk inside an object of the Document class, and return List[Document]. | TextReader() |
optimize_on | int | It is used to specify the number of documents on which to optimize the vector database. Supposed to create an index. | 1000 |
Document class?”
We know that, before storing the data in vectorDB, we need to split the data into smaller chunks upon which embeddings will be created and these embeddings along with the chunks will be stored in vectorDB. When the user queries over the vectorDB, some of these embeddings will be returned as the result based on the semantic similarity with the query.
When the user queries over vectorDB, the queries are converted into embeddings, and a nearest neighbor search is performed over these query embeddings which returns the embeddings that correspond to most semantically similar chunks(parts of our data) present in vectorDB.
Here, a “Document” is a class in Phidata. Since there is an option to let Phidata create and manage embeddings, it splits our data into smaller chunks(as expected). It does not directly create embeddings on it. Instead, it takes each chunk and encapsulates it inside the object of the Document class along with various other metadata related to the chunk. Then embeddings are created on these Document objects and stored in vectorDB.
However, using Phidata you can load many other types of data in the knowledge base(other than text). Check out Phidata Knowledge Base for more information.
Let’s dig deeper into the vector_db parameter and see what parameters LanceDb takes -
| Name | Type | Purpose | Default |
|---|---|---|---|
embedder | Embedder | Phidata provides many Embedders that abstract the interaction with embedding APIs and utilize it to generate embeddings. Check out other embedders here | OpenAIEmbedder |
distance | List[str] | The choice of distance metric used to calculate the similarity between vectors, which directly impacts search results and performance in vector databases. | Distance.cosine |
connection | lancedb.db.LanceTable | LanceTable can be accessed through .connection. You can connect to an existing table of LanceDB, created outside of Phidata, and utilize it. If not provided, it creates a new table using table_name parameter and adds it to connection. | None |
uri | str | It specifies the directory location of LanceDB database and establishes a connection that can be used to interact with the database. | "/tmp/lancedb" |
table_name | str | If connection is not provided, it initializes and connects to a new LanceDB table with a specified(or default) name in the database present at uri. | "phi" |
nprobes | int | It refers to the number of partitions that the search algorithm examines to find the nearest neighbors of a given query vector. Higher values will yield better recall (more likely to find vectors if they exist) at the expense of latency. | 20 |
Since we just initialized the KnowledgeBase. The VectorDB table that corresponds to this Knowledge Base is not yet populated with our data. It will be populated in Step 3, once we perform the
load operation.You can check the state of the LanceDB table using - knowledge_base.vector_db.connection.to_pandas()Step 2 - Create an assistant with our choice of LLM and reference to the knowledge base.
Assistants add memory, knowledge, and tools to LLMs. Here we will add only knowledge in this example. Whenever we will give a query to LLM, the assistant will retrieve relevant information from our Knowledge Base(table in LanceDB) and pass it to LLM along with the user query in a structured way.- The
add_references_to_prompt=Truealways adds information from the knowledge base to the prompt, regardless of whether it is relevant to the question.
Step 3 - Load data to Knowledge Base.
The above code loads the data to the Knowledge Base(LanceDB Table) and now it is ready to be used by the assistant.| Name | Type | Purpose | Default |
|---|---|---|---|
recreate | bool | If True, it drops the existing table and recreates the table in the vectorDB. | False |
upsert | bool | If True and the vectorDB supports upsert, it will upsert documents to the vector db. | False |
skip_existing | bool | If True, skips documents that already exist in the vectorDB when inserting. | True |
Tip · What is upsert?During the Load operation, Phidata directly interacts with the LanceDB library and performs the loading of the table with our data in the following steps -
Upsert is a database operation that combines “update” and “insert”. It updates existing records if a document with the same identifier exists, or inserts new records if no matching record exists. This keeps the knowledge base current without manual checks.
- Creates and initializes the table if it does not exist.
-
Then it splits our data into smaller chunks.
Question · How do they create chunks?
Phidata provides multiple knowledge-base types depending on the source data. Most of them (except the LlamaIndexKnowledgeBase and LangChainKnowledgeBase) expose adocument_listsiterator. During the load operation, this iterator reads the input (for example, text files), splits it into chunks, wraps each chunk in aDocument, and yields lists of thoseDocumentobjects. -
Then embeddings are created on these chunks are inserted into the LanceDB Table
Question · How do they insert the chunks into LanceDB?
Each list ofDocumentobjects from the previous step is processed as follows:- Generate embeddings for every
Document. - Clean the
contentfield so only the text you care about is persisted. - Prepare a payload with the
id, the embedding (vector), and any metadata needed for retrieval. - Add the prepared rows to the LanceDB table.
- Generate embeddings for every
-
Now the internal state of
knowledge_baseis changed (embeddings are created and loaded in the table ) and it ready to be used by assistant.