The theme of this tutorial

What is Retrieval Augmented Generation, and how to build an AI RAG system on Instill Cloud?

Learn what Retrieval-Augmented Generation (RAG) is, its benefits, and how to build a Retrieval-Augmented Generation (RAG) system on Instill Cloud to assist doctors with queries related to urinary tract infections.

October 30, 2024

Tutorial

Retrieval-Augmented Generation (RAG) is an AI framework that combines information retrieval systems with large language models (LLMs) to generate more accurate and relevant text. By combining the strengths of LLMs with the ability to access external knowledge, RAG offers a way to generate responses that are both contextually aware and grounded in real-time, relevant information. This dual functionality enhances the accuracy of AI systems, reducing hallucinations and making them more reliable in dynamic environments.

In this tutorial, we will explore the fundamentals of RAG, its practical benefits, and guide you through building a basic RAG system on Instill Cloud for assisting doctors and medical professionals with the diagnoisis of urinary tract infections. By the end, you'll have a functional API-ready RAG pipeline to test, and will have the knowledge to build and integrate RAG into your own applications, empowering them with real-time retrieval capabilities.

#So What Actually is RAG?

RAG is a natural language processing framework designed to improve the responses of language models by combining two powerful techniques: retrieval and generation. Instead of relying solely on the pre-trained knowledge of a model, RAG allows AI systems to retrieve relevant information from external sources in real time and generate responses that are enriched by this external data.

At a high level, this process involves:

  1. Retrieval: Searching a knowledge base or data catalog to find information related to the user's query.
  2. Generation: Using the retrieved information to craft a response that is accurate, contextually relevant, and factually grounded.

This method allows AI models to provide more reliable and nuanced responses, especially in fields where information changes frequently or where accuracy is paramount.

#How to Build a RAG System?

At a lower level, building a RAG system typically involves two key phases.

#Indexing Phase (Offline):

The indexing phase occurs offline during the setup of the RAG system, where you prepare the knowledge base for future retrieval.

RAG Indexing Phase (Offline): Building a data catalog for future retrieval
RAG Indexing Phase (Offline): Building a data catalog for future retrieval
  1. Extract text from files: Gather textual data from documents, websites, or other sources that will serve as the knowledge base.
  2. Split the text into smaller chunks: Break the extracted text into manageable pieces (chunks) to ensure more efficient retrieval and better context handling.
  3. Convert text chunks into vectors using an embedding model: Use a pre-trained embedding model to convert each text chunk into vector representations, capturing the semantic meaning of the text.
  4. Store vectors and their corresponding text as metadata in a vector database: Save the vectors in a vector database, alongside metadata like the original text, to enable fast similarity-based searches during the online phase.

#Retrieving and Generating Phase (Online):

The retrieving and generating phase happens online, during real-time interactions when the system is serving user queries.

RAG Retrieving and Generating Phase
(Online): Retrieving relevant text chunks and generating responses
RAG Retrieving and Generating Phase (Online): Retrieving relevant text chunks and generating responses
  1. Convert user queries into vectors: Transform the user's input query into a vector using the same embedding model.
  2. Retrieve relevant text chunks from the vector database based on similarity: Search the vector database to find the most semantically similar chunks of text based on the query vector.
  3. Generate a response to the query using the retrieved chunks as context: Feed the retrieved text chunks into the language model to generate a response, grounding it in the retrieved information.

#Why is RAG so Useful?

RAG offers a range of benefits that significantly enhance AI performance, making it a go-to approach for a variety of applications:

💡 Minimizes Hallucinations
Large language models sometimes generate responses that seem plausible but are factually incorrect or nonsensical. RAG mitigates this issue by grounding responses in real, retrieved data, thus reducing the chances of hallucinations and improving the reliability of AI systems.

📚 Incorporates External Knowledge
Unlike standalone models limited by their training data, RAG systems can access and utilize up-to-date information from external sources. This is especially valuable in fast-moving domains like news, finance, law, or medicine, where data relevance can shift rapidly.

🔧 Reduces the Need for Expensive Retraining
Traditional models require frequent retraining to incorporate new information, which is time-consuming and costly. For certain applications, RAG offers a more efficient alternative - by simply updating the external knowledge base, you can maintain access to the latest information without the need to retrain the underlying model.

💰 Cost-Efficiency and Flexibility
RAG is ideal for applications like question-answering, text summarization, and dialogue systems, where it can help avoid the high computational costs of training models from scratch. Instead of fine-tuning large models on new datasets, RAG integrates external data seamlessly into the generation process.

🔐 Data Control and Security
With RAG, organizations have complete control over the data sources their AI models access. Sensitive data can be managed according to authorization levels, ensuring compliance with privacy policies and regulations.

📈 Enhanced Performance in QA and Dialogue Systems
RAG excels in environments where accuracy is critical, such as in QA systems, by grounding answers in factual documents. For dialogue systems, RAG enhances conversation by maintaining relevant context throughout the interaction, making the experience more coherent and dynamic.

#Building a Basic RAG System on ☁️ Instill Cloud

Let's dive in and create a RAG system for assisting doctors and medical professionals with the diagnoisis of urinary tract infections. We'll follow these steps:

  1. Create an Instill Catalog using raw documents (a mix of docx and pdf files) to serve as the knowledge base
  2. Build the basic-rag-anthropic pipeline in the editor
  3. Test the performance of the pipeline on real-world queries
  4. Call the pipeline via API

#Try it Yourself!

Click the button below to view and try the pipeline yourself — for free — on the Instill Cloud platform!

Please note that to use this pipeline, you need to first sign up for an Instill Cloud account, and create, upload and process files to your own Instill Catalog.

#Step-by-Step Tutorial

We'll first use Instill Artifact to handle the Indexing Phase and build our catalog - this will serve as our RAG knowledge base and encompasses converting the documents to markdown text, chunking the text, embedding the chunks, and storing the embeddings in a vector database.

INFO

Under the hood, Instill Artifact is actually powered by a series of Instill VDP pipelines - checkout the Process Files page for more details!

Next, we'll tackle the Retrieving and Generating Phase using Instill VDP to build a simple and generalisable RAG pipeline. Although we will be focusing on building a medical RAG system in this tutorial, the pipeline we will build is fully generalisable to other domains.

#Prerequisites

  • Please create an Instill Cloud account first by following the steps outlined in the Quickstart Guide.
  • Download the medical documents we will be using to build our data catalog from this link. Once downloaded, extract the contents. The files we will be using are a mix of docx and pdf file formats, and contain medical information related to urinary tract infections and their diagnosis.

#Step 1: Create a Catalog with 💾 Instill Artifact

To create a new Catalog from the console:

  1. Launch Instill Console on Instill Cloud.
  2. Navigate to the Artifacts page using the navigation bar.
  3. Click the + Create Catalog button.
  4. Select the Owner (your namespace ID).
  5. Enter a name for your Catalog, e.g. "medical-documents".
  6. (Optional) Enter a description and tags for your Catalog.
  7. Click the Create button.

#Step 2: Index Files into the Catalog

To upload files to a Catalog via the Console, follow these steps:

  1. Click the Catalog card for the new Catalog.
  2. Select Upload Documents in the left panel.
  3. Drag and drop the rag-tutorial-files files into the blue box or click browse computer to upload files.
  4. Click the Process Files button.

The processing status of your files appears in the Files tab. When the status is Completed, you can view your processed Files and Chunks.

This catalog will serve as the knowledge base for the RAG pipeline we will now build.

#Step 3: Create a New Pipeline

  1. Navigate to the Pipelines page using the navigation bar on Instill Cloud.
  2. Click + Create Pipeline in the top right to enter the pipeline editor.
  3. Select the Owner (your namespace ID).
  4. Enter a name for your Pipeline, e.g. "basic-rag".
  5. (Optional) Enter a description for your Pipeline.
  6. Click the Create button, and you will be redirected to the pipeline editor for your new pipeline.
Pipeline editor (left), pipeline preview & input/output (right)
Pipeline editor (left), pipeline preview & input/output (right)

#Step 4. Write the RAG Pipeline Recipe

In the pipeline editor, we will now write the recipe for the Retrieving and Generating Phase of the RAG system.

#Input Variables

In the pipeline recipe, add the necessary input variables required from the user:


variable:
catalog-name:
title: Catalog Name
description: Name of the catalog to retrieve from
instill-format: string
top-k:
title: Top K
description: Number of top documents to retrieve (e.g., 10)
instill-format: number
user-query:
title: User Query
description: The original user query
instill-format: string
namespace:
title: Namespace
description: Namespace for your catalog (useful if you have multiple namespaces)
instill-format: string

#Pipeline Components

To enhance retrieval accuracy, we'll now add a query revisor that refines the user's original query to the pipeline recipe:


component:
query-reviser:
type: anthropic
input:
model-name: claude-3-haiku-20240307
system-message: |-
You are a smart and helpful prompt engineer and expert at revising user queries for vector database search.
prompt: |-
As an expert in language processing and query formulation, your task is to refine and rephrase a user's query in English.
This rephrased query is intended for precise searching within a vector database to locate relevant documents.
You should correct any pronouns, typos, or grammatical errors in both the conversation history and the customer's query to ensure the search engine can retrieve accurate and relevant documents.
The goal is to produce an accurate and effective query that can be used to retrieve relevant related documents from the vector database.
Please only return the revised query, with no additional explanation or text.
**User Query:**
${variable.user-query}
Reformulated Query:
top-k: 1
temperature: 0
max-new-tokens: 1000
task: TASK_TEXT_GENERATION_CHAT

By refining the user's query before searching the catalog, we can improve the accuracy of the retrieval process and, in turn, the quality of the generated response. For this step, its often preferable to use a fast, lightweight model as it typically won't need to perform complex reasoning. We choose Anthropic's low-latency claude-3-haiku-20240307 model for this component.

Now, let's add the retrieval component to the pipeline recipe:


retrieve-from-catalog:
type: instill-artifact
task: TASK_RETRIEVE
input:
catalog-id: ${variable.catalog-name}
namespace: ${variable.namespace}
text-prompt: ${query-reviser.output.text}
top-k: ${variable.top-k}

This component searches your catalog and retrieves relevant documents based on the revised query.

To generate an answer to the user's query using the retrieved documents, we can now add the following code to the recipe:


generate-response:
type: anthropic
input:
model-name: claude-3-5-sonnet-latest
system-message: |-
You are a smart and helpful Q&A agent, assisting users by accurately answering their questions based on the provided context.
Follow these steps and instructions to generate your response:
1. Carefully review the user's query and the provided context.
2. Break down the user's query into smaller, manageable parts if necessary.
3. For each part of the question:
a. Select the most relevant information from the context.
b. Make reasonable inferences based on the given context, but do not go beyond the provided information.
4. Draft a response using the selected information, ensuring the level of detail is appropriate for the user's expertise.
5. Remove any duplicate content from the draft response.
6. Adjust the draft to increase accuracy and relevance.
7. Do not include instructions' explanations or details in your final response.
8. If the question cannot be answered based on the provided context, use your existing knowledge to generate a relevant response, but provide a warning to the user at the end stating that the query was out of context for the specified Catalog.
prompt: |-
You are an accurate and reliable AI assistant capable of answering questions using external documents.
Always be faithful to the provided documents and leverage relevant, accurate information from them as much as possible.
Be aware that external documents might contain noisy or factually incorrect data.
Apply critical reasoning to discern and use the correct information from these sources.
If the question cannot be answered based on the context and user's questions/instructions at all, use your existing knowledge to generate a relevant response, but provide a warning to the user at the end stating that the query was out of context for the specified Catalog.
**Context:**
${retrieve-from-catalog.output.chunks}
**User Query:**
${variable.user-query}
Now, generate your final response based on the given instructions and context to answer the user's query:
top-k: 1
temperature: 0
max-new-tokens: 1000
task: TASK_TEXT_GENERATION_CHAT

For response generation, it can be preferable to use a more powerful model, particularly if the response requires complex reasoning or detailed explanations. In this case, we choose Anthropic's claude-3-5-sonnet-20240620 model for this component.

As you can see, this component also involves some prompt engineering. In particular, the system message includes chain-of-thought instructions for the LLM to follow when generating the response. This helps ensure the response is accurate, relevant, and contextually grounded.

#Define the Outputs

Finally, let's add outputs to capture and display the assistant's response, the revised query, and the retrieved document chunks:


output:
response:
title: Response
value: ${generate-response.output.text}
instill-ui-order: 1
revised-query:
title: Revised Query
value: ${query-reviser.output.text}
instill-ui-order: 2
retrieved-chunks:
title: Retrieved Chunks
value: ${retrieve-from-catalog.output.chunks}
instill-ui-order: 3

#Step 5: Run the Pipeline

There are a few ways you can run a pipeline, see Run Pipeline docs.

#1. Run via Pipeline Editor

In the Input form on the bottom right, fill in the corresponding values:


Catalog Name: `medical-documents`
Namespace: <INSERT_YOUR_NAMESPACE_ID>
Top K: 10
User Query: What are the criteria for diagnosing asymptomatic bacteremic urinary tract infection?

Click Run to execute and observe the response in the output panel, alongside the retrieved chunks used to formulate the response.

Here are some further real-world queries you can try out:

  • "Is 'fever attack' considered a symptom related to urinary tract infection?"
  • "What does 'LUTS' signify in medical terms?"
  • "If a patient doesn't have a catheter or has had a catheter for less than two days but shows UTI symptoms like dysuria or Lower Urinary Tract Symptoms, is this considered a CAUTI?"
  • "If a patient without a catheter has a fever with UTI symptoms, is this a CAUTI? Why?"
  • "A patient has had an indwelling catheter for three calendar days and still has it one day before the UTI diagnosis date, showing symptoms like lower abdominal pain and pelvic discomfort. Is this a CAUTI? Please explain why."
  • "Can mixed bacterial flora be considered a pathogen for healthcare-associated infections? Why?"
  • "If a patient has multiple bed transfers the day before the infection date, how should the infection department be determined?"

#2. Run via API

To generate your Instill API Token, see the API Token Management docs.


export INSTILL_API_TOKEN='**********'
curl -X POST 'https://api.instill.tech/v1beta/users/george_strong/pipelines/basic-rag/trigger' \
--header "Content-Type: application/json" \
--header "Authorization: Bearer $INSTILL_API_TOKEN" \
--data '{
"inputs": [
{
"catalog-name": "medical-documents",
"namespace": "<INSERT_YOUR_NAMESPACE_ID>",
"top-k": 10,
"user-query": "What are the criteria for diagnosing asymptomatic bacteremic urinary tract infection?"
}
]
}'

Here is an example response, showing the response, retrieved-chunks, and revised-query outputs:


{
"outputs": [
{
"response": [
"The criteria for diagnosing Asymptomatic Bacteremic Urinary Tract Infection (ABUTI) are as follows:\n\n1. The patient must have no symptoms or signs that meet the criteria for symptomatic UTI.\n2. The urine culture must show no more than 2 species of microorganisms, with at least one species having a colony count of 100,000 cfu/ml.\n3. A blood culture or other non-culture microbiological tests must show microorganisms, with at least one species matching the urine culture microorganism, also with a colony count of 100,000 cfu/ml.\n\nThese conditions must all occur within the Infection Window Period (IWP)."
],
"retrieved-chunks": [
{
"chunk-uid": "b56d0c7d-dae0-4fa6-aea6-70f6455cde28",
"similarity-score": 0.75519896,
"source-file-name": "flow_v2.pdf",
"text-content": "# Determination Process\n\n## 1. Determine if the urine culture meets the criteria: “Urine culture shows no more than 2 types of microorganisms, with at least one having a colony count ￿ 100,000 cfu/ml.” • If no, not UTI, end process. 2. Determine if the age is ￿ 1 year. • If yes, determine if it meets the criteria for CAUTI or Non-CAUTI in patients 1 year of age or less. • If no, go to step 4. 3. On the date of onset (DOE) of the urinary tract infection, determine if the patient has been using an indwelling catheter for more than 2 calendar days, and if the patient was still using the indwelling catheter on the DOE or the day before. • If true, determine if it meets the criteria for CAUTI. • If false, determine if it meets the criteria for non-CAUTI. • If neither CAUTI nor non-CAUTI, go to step 4. 4. If step 4 is not met, but a blood specimen shows microorganisms, with at least one matching the microorganism in the urine culture with a colony count ￿ 100,000 cfu/ml, determine it as asymptomatic bacteremic UTI (ABUTI). • If true, determine it as ABUTI. • If false, determine it as not UTI. 5. If determined as UTI (including CAUTI, non-CAUTI, ABUTI, CAUTI or Non-CAUTI in patients 1 year of age or less), attempt to determine if it is present on admission (POA). • If POA, label it as a specific infection (POA) (e.g., non-CAUTI (POA)). 1\n"
},
{
"chunk-uid": "042c3272-8b3b-4a45-a2dc-07f5b5e75a71",
"similarity-score": 0.66641873,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": " with at least one species having a colony count of ￿ 100,000 cfu/ml.\n\n 3. CAUTI or Non-CAUTI in Patients 1 Year of Age or Less: The patient\n must meet the following three conditions, all occurring within the IWP:\n\n 3. Urine culture must show no more than 2 species of microorganisms,\n with at least one species having a colony count of ￿ 100,000 cfu/ml.\n 4. Based on the patient’s catheter use, determine whether the case meets\n the criteria for CAUTI or a general UTI case.\n 4. Asymptomatic Bacteremic UTI (ABUTI) Criteria: The patient must meet\n the following three conditions, all occurring within the IWP:\n 1. Regardless of catheter use, the patient has no symptoms or signs that\n meet the criteria for symptomatic UTI.\n • Based on the patient’s catheter use, determine whether the case\n meets the criteria for CAUTI or a general UTI case.\n"
},
{
"chunk-uid": "8d133b1a-a04b-496e-a9df-6b4997d790bd",
"similarity-score": 0.6171713,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": " with at least one species having a colony count of ￿ 100,000 cfu/ml.\n\n 4. Asymptomatic Bacteremic UTI (ABUTI) Criteria: The patient must meet\n the following three conditions, all occurring within the IWP:\n\n 2. Urine culture must show no more than 2 species of microorganisms,\n with at least one species having a colony count of ￿ 100,000 cfu/ml.\n"
},
{
"chunk-uid": "a0d4b333-e098-4125-a3ad-65025689f31a",
"similarity-score": 0.6171368,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": " 4. Asymptomatic Bacteremic UTI (ABUTI) Criteria: The patient must meet\n the following three conditions, all occurring within the IWP:\n\n 2. Urine culture must show no more than 2 species of microorganisms,\n with at least one species having a colony count of ￿ 100,000 cfu/ml.\n 3. Blood culture or other non-culture microbiological tests must show\n microorganisms, with at least one species matching the urine culture\n microorganism with a colony count of ￿ 100,000 cfu/ml.\n • If a patient >65 years old has a fever (>38.0°C) without catheter\n use, they may still meet the criteria for asymptomatic bacteri-\n uria.\n\n"
},
{
"chunk-uid": "4cb2d1e7-a04e-49fa-952f-721cea901028",
"similarity-score": 0.59447926,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": "\n 1. CAUTI Criteria: The patient must meet the following three conditions,\n all occurring within the IWP:\n\n 2. The patient must have at least one of the following signs or symptoms:\n • Fever (>38.0°C)\n • Suprapubic tenderness\n • Costovertebral angle pain or tenderness\n • Urinary urgency (not applicable during catheter use)\n • Urinary frequency (not applicable during catheter use)\n • Dysuria (not applicable during catheter use)\n 3. Urine culture must show no more than 2 species of microorganisms,\n with at least one species having a colony count of ￿ 100,000 cfu/ml.\n 2. Non-CAUTI Criteria: The patient must meet the following three condi-\n tions, all occurring within the IWP:\n"
},
{
"chunk-uid": "98fcbd18-3772-4a1e-b0da-eb21f5877ed0",
"similarity-score": 0.5895911,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": "\n 2. Non-CAUTI Criteria: The patient must meet the following three condi-\n tions, all occurring within the IWP:\n\n 1. On the DOE, the catheter must not have been in place for more than\n 2 calendar days, or the patient must not have had a catheter in place\n on the DOE or the day before.\n 2. The patient must have at least one of the following signs or symptoms:\n • Fever (>38.0°C) (only applicable to patients ￿ 65 years old)\n • Suprapubic tenderness\n • Costovertebral angle pain or tenderness\n • Urinary urgency\n • Urinary frequency\n • Dysuria\n 3. Urine culture must show no more than 2 species of microorganisms,\n\n"
},
{
"chunk-uid": "54afc933-96e8-4c8e-9ef6-8540327b50c7",
"similarity-score": 0.578525,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": " with at least one species having a colony count of ￿ 100,000 cfu/ml.\n\n\n 3. CAUTI or Non-CAUTI in Patients 1 Year of Age or Less: The patient\n must meet the following three conditions, all occurring within the IWP:\n 1. The patient is ￿ 1 year old (regardless of catheter use).\n 2. The patient must have at least one of the following signs or symptoms:\n • Fever (rectal temperature >38.0°C)\n • Hypothermia (rectal temperature <36.0°C)\n • Apnea\n • Bradycardia\n • Lethargy\n • Vomiting\n • Suprapubic tenderness\n • Costovertebral angle pain or tenderness\n 3. Urine culture must show no more than 2 species of microorganisms,\n with at least one species having a colony count of ￿ 100,000 cfu/ml.\n"
},
{
"chunk-uid": "705f2f69-d9dd-4ae6-b8f1-c38723436453",
"similarity-score": 0.5587858,
"source-file-name": "Case 4 not UTI.docx",
"text-content": "# Medical Orders\n\n## Test: Urine routine (urgent) [urine] [capped quantitative centrifuge tube (urine collection tube)] STAT [Note: self-voided] => The urine sample source is self-voided, indicating no catheterization.\n\n# Case Determination of Urinary Tract Infection\n## 1. No catheterization 2. Patient shows no UTI symptoms => Determination: Not a urinary tract infection, only asymptomatic bacteriuria (not UTI; asymptomatic bacteriuria only)\n"
},
{
"chunk-uid": "de22a23b-a3c6-4174-a0df-61c60cacfcee",
"similarity-score": 0.55544055,
"source-file-name": "UTI_rules_v4.pdf",
"text-content": "# Reporting Considerations for Urinary Tract Infections\n\n• Information can come from palpation (tenderness-sign) or patient-\n reported symptoms (pain-symptom). As long as the relevant infor-\n mation is documented in the medical records and the symptom record\n date is within the IWP, it can be included in the symptomatic UTI\n case criteria.\n • Lower abdominal pain, bladder or pelvic discomfort can be consid-\n ered signs of suprapubic tenderness. However, general abdominal\n pain documented in the medical records cannot be used as evidence\n of suprapubic tenderness due to the many causes of abdominal pain."
},
{
"chunk-uid": "0d86211d-dd71-441d-a16c-89a66491b702",
"similarity-score": 0.5472651,
"source-file-name": "General rules-document revision.pdf",
"text-content": "\n 4. According to the surveillance definition, UTI patients’ urine cultures\n should not exceed two microorganisms. If a secondary bloodstream\n infection is confirmed, the third and subsequent pathogens can be\n reported.\n\n"
}
],
"revised-query": [
"What are the criteria for diagnosing asymptomatic bacteremic urinary tract infections?"
]
}
],
"metadata": {
...
}
}

#Conclusion

Congratulations on building a generalisable and customizable Retrieval-Augmented Generation (RAG) system on Instill Cloud! 🎉

Through this tutorial, you have:

  1. Created an Instill Catalog to serve as a knowledge base.
  2. Built a generalizable RAG pipeline with components for query revision, retrieval, and response generation for assisting doctors with UTI-related queries.
  3. Successfully tested the pipeline and learned how to make API calls for seamless integration.

#Next Steps

Now that you've built a simple RAG system, here's what you can explore next:

🍎 Try the new Instill App AI Assistant Seamlessly interact and converse with an out-of-the-box RAG-based AI Assistant with conversation history that is grounded in the context of a chosen Instill Catalog.

📄 Process Complex Documents Build bespoke indexing pipelines to handle complex documents with tables, complex formatting and multi-language content.

🎨 Expand to Multimodal RAG Incorporate image, video and audio processing to handle diverse data queries and adjust your pipeline for multimodal-based information.

Integrate with Other Vector Databases Connect to vector databases like Pinecone or Weaviate to leverage existing knowledge bases.

📚 Explore API-First Documentation Dive into our documentation and Python SDK to further simplify catalog creation and seamlessly integrate with your existing tech stack.

Thank you for following along with this tutorial, and stay tuned for more AI content where we tackle advanced RAG topics (and more) coming soon! 🚀

blurred spotbeam
line

AI infrastructure for Enterprise