
Vector databases are commonly used to store vector embeddings for tasks such as similarity search to build recommendation and question-answering systems. Milvus is a popular open-source database that stores embeddings in the form of vector data. It is well-suited and offers indexing features like Approximate Nearest Neighbours (ANN) that enable fast and accurate results.
This article explains how to implement AI-powered search with Python and a Milvus Database. You will use a HuggingFace dataset, create embeddings from the dataset, divide the dataset into two halves (testing and training), and store all created embeddings to a Milvus database by creating a collection. Then, you are to perform a search operation by giving a question prompt and generate the most similar answers.
Before you begin:
Deploy a Vultr Kubernetes Engine cluster with at least:
Deploy a Ubuntu 22.04 A100 Vultr Cloud GPU server.
Use SSH to access the server as a non-root sudo user
Install and Configure Kubectl to access the cluster
Deploy MilvusDB to the VKE cluster
Contact Vultr Support to verify that your account is eligible to deploy at least 20 Block Storage instances required by Milvus DB
To develop and deploy your application, install the necessary dependencies and parameters on the server. Then, connect to your Milvus Cluster to set up database operations as described in the steps below.
Using pip, install the necessary dependencies
Below is what each package does:
transformers: A HuggingFace library used to access and work with pre-trained LLM models for tasks such as text classification and generationdatasets: A HuggingFace library that allows you to access and work with ready-to-use datasets for Natural Language Processing (NLP) taskspymilvus: The Milvus Python client that allows you to perform vector similarity search, storage, and management of large collectionstorch: A machine learning library used to train and build deep learning modelsOpen the Python console
Import the required modules
Below is what each of the imported module classes does:
pymilvus:
connections: Provides functions to manage connections to the Milvus databaseFieldSchema: Define the schema of fields in a Milvus databaseCollectionSchema: Defines the schema of a collectionDataType: Enumerates data types used in a Milvus collectionCollection: Provides the functionality to interact with Milvus collections to create, insert, and search vectorsutility: Provides the data preprocessing and query optimization functions to work with Milvusdatasets:
load_dataset_builder: Loads and returns dataset objects to accesss the database information and its metadataload_dataset: Loads a dataset from a dataset builder and returns the dataset object for data accessDataset: Represents a dataset that provides access to data-related operationstransformers:
AutoTokenizer: Loads the pre-trained tokenization models for NLP tasksAutoModel: A model loading class that automatically loads pre-trained models for NLP taskstorch:
clamp: Provides functions for element-wise limiting of tensor valuessum: Computes the sum of tensor elements along specified dimensionsDeclare the necessary parameters
Below is what each declared parameter does:
DATASET: Defines the Huggingface dataset to use when searching for answersMODEL: Defines the transformer to use for creating embeddingsTOKENIZATION_BATCH_SIZE: Determines how many text elements are processed at once during tokenization. This helps to speed up tokenization by using parallelismINFERENCE_BATCH_SIZE: Sets the batch size for predictions, affecting the efficiency of text classification tasks. You can reduce the batch size to 32 or 18 when using a smaller GPU sizeINSERT_RATIO: Controls the part of text data to convert into embeddings managing the volume of data to index when performing vector searchCOLLECTION_NAME: Sets the collection name you intend to createDIMENSION: Sets the size of an individual embedding to store in the collectionLIMIT: Sets the number of results to search and display in the outputMILVUS_HOST: Sets the VKE cluster external IP address to access the Milvus databaseMILVUS_PORT: Defines the Milvus Database port accessible using the cluster host IP addressConnect to the Milvus database. Replace 192.0.2.100, 19530, root, and Milvus with your actual Milvus cluster values
The above command creates a connection to the Milvus database using your VKE cluster deployment details.
To build the question-answering system, create a collection. Then, insert data to the collection after tokenizing and creating the embeddings.In addition, perform a search operation to get the relevant answers for a specific question to test the system functionality as described in the following sections.
In this section, check for the existence of the collection, create the collection, and set up the index for the collection. To perform text-based operations, load the collection as described in the steps below.
Verify if a collection exists. Replace COLLECTION_NAME with your target collection name
The above command checks if the collection you are making is already made or not, if the collection is present then it is deleted to avoid any conflicts.
Create a new collection. Replace COLLECTION_NAME with your desired name
The above code defines a new collection schema with the following fields:
id: Sets the primary field in which all database entries identifiedoriginal_question: Stores the original question and matches any other question you askanswer: Holds the answer to each original_quesitionoriginal_question_embedding: Contains embeddings for each entry in the original_question to perform a similarity search with your input questionCreate the collection index
The above code creates a new index for the original_question_embedding field to perform a similarity search. When successful, your output should look like the one below:
Load the collection
The above code loads the collection which is important when working with vector databases. Loading the collection ensures that the collection is ready to perform search operations.
Load the dataset
The above code loads the dataset, splits the dataset into training and test sets, then processes the test set to remove any other columns except for the answer text.
Initialize the tokenizer
Tokenize the question
The above code defines a function tokenize_question that takes a batch of data as input and tokenizes the question field into an acceptable Bert model format. It applies truncation and padding, then returns the encoded data in a batch along with input_ids, token_type_ids, and attention_mask. This is a common pre-processing step in NLP tasks before you send data to the model.
Tokenize each entry
The above code uses the map function on the data_dataset and applies the tokenize_question function on every question in the dataset. When successful, the output format is set to a torch compatible format for PyTorch based machine learning models.
Create the embeddings
The above code loads the pre-trained model and passes the tokenized questions through the model to get the required embeddings and the generated embeddings are added to the dataset as question_embeddings.
Insert questions into a collection
The above code uses data from the dataset and inserts it to the collection. The answer is then truncated to consider the VARCHAR limit as displayed in the following output:
In this section, create a custom question dataset, tokenize, and embed the dataset. Then, perform a search operation in the Milvus collection to find the top relevant answers for your question.
Create a new question dataset. Replace When was maths invented with your desired question
The above code creates a new question_dataset dataset. You can increase the number of questions you wnt to generate answers using the questions variable.
Tokenize and embed the question
The above code tokenizes the question_dataset using the tokenize_question function. Then, sets the output format to torch and embeds the question_dataset by applying the embed function to generate the embeddings.
Define the search function
The above search function performs a search operation using the embeddings. It searches for similar questions in the embeddings and retrieves information such as the id, distance, answer and original_question. Retrieved information is organized into lists and returned as a dictionary.
Perform a search operation
The above code applies the search function you defined earlier in the question_dataset. When successful, it prints the information for each question as displayed in the output below:
As displayed in the above output, the closest 10 answers are generated in descending order for the question you asked along with the original questions those answers belong to. The output also displays tensor values with each answer, a less tensor value means that the generated answer is more accurate to your question.
You have built a question answering system using a HuggingFace dataset and Milvus. You created embeddings from the dataset, stored them in a Milvus collection, and performed a similarity search to find the most suitable answers for the provided prompt. You can modify the questions to return more accurate results depending on the tensor values associated with each answer.
To implement more solutions on your Vultr Cloud GPU server, visit the following resources:
0 Comments
Be the first to comment and share your perspective with the community.