Unlocking the Power of Adaptive RAG Systems
Editor’s note: David vonThenen is a speaker for ODSC East 2025 from May 13th to 15th. Be sure to check out his talk, “Adaptive RAG Systems with Knowledge Graphs: Building Reinforcement-Learning-Driven AI Applications,” there!
Imagine an AI assistant that doesn’t just answer your questions — it understands the deeper context, adapts in real time, and continuously learns from interactions. The future of AI isn’t just about smarter models but about more intelligent systems that seamlessly integrate context, memory, and real-world knowledge. I’m thrilled to share that this vision is precisely what we’ll explore in our upcoming workshop at ODSC East, “Adaptive RAG Systems with Knowledge Graphs: Building Reinforcement-Learning-Driven AI Applications.”
The Evolution of RAG Agents — A New Frontier in AI
Retrieval-Augmented Generation (RAG) represents a critical evolution in AI, combining large language models (LLMs) with external knowledge sources to produce accurate, relevant, and timely responses. Traditional language models, despite their impressive capabilities, often generate responses based solely on patterns learned during training, which may result in outdated or inaccurate information. Adaptive RAG systems address this limitation by retrieving external knowledge dynamically to inform their responses, enabling them to answer questions with greater accuracy and relevancy.
The introduction of external knowledge retrieval fundamentally expands the possibilities of conversational AI applications. From customer support and virtual assistants to medical diagnostics and legal advice, RAG agents can provide contextually accurate and reliable information on demand. This innovative combination also mitigates common issues such as “hallucination,” where models generate plausible but incorrect information, by grounding responses firmly in external verified sources.
Knowledge Graphs and Querying — Powering Smart Responses
Knowledge graphs have become a foundational technology in modern AI systems due to their ability to organize data into interconnected structures. Unlike traditional databases, knowledge graphs explicitly represent relationships between entities, allowing for highly efficient and intuitive data querying. By leveraging structured queries, knowledge graphs enable RAG agents to access precisely the information needed, enriching the agent’s responses with factual accuracy and context-sensitive details.
In practice, querying a knowledge graph involves traversing relationships between entities to find relevant insights. For instance, asking about a movie could lead to retrieving details about its director, actors, release year, and even related films. This structured, relationship-based approach facilitates powerful reasoning capabilities, allowing RAG agents to handle complex, multi-step queries that traditional keyword-based searches struggle with. In our workshop, participants will experience firsthand how integrating knowledge graphs can enhance AI interactions, resulting in responses that are not only accurate but dynamically tailored to user queries.
Workshop Primer: Creating a Knowledge Graph RAG Agent
Below is a quick walkthrough for building a simple Retrieval-Augmented Generation (RAG) agent backed by Neo4j, followed by how to query it. The first script ingests text data, chunks it, creates embeddings, and writes them to Neo4j. The second script shows how to query those embeddings with an LLM for RAG-based Q&A.
IMPORTANT NOTE: The code below contains a simple and naive approach! You need to know a lot more about your dataset in order to properly ingest it! This is for demonstration purposes only!
Ingest and Embed Data in a Graph Database
Use the following code to load .txt files, split them into chunks, create embeddings, and store the results in Neo4j:
import os
import glob
from typing import List
# Neo4j driver
from neo4j import GraphDatabase # LangChain imports
from langchain.docstore.document import Document
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings # or another embedding class
from langchain.vectorstores import Neo4jVector # ----------------------------------
# Configuration
# ----------------------------------
# Feel free to replace these with environment variables or config files
NEO4J_URI = os.getenv("NEO4J_URI", "neo4j://localhost:7687")
NEO4J_USER = os.getenv("NEO4J_USER", "neo4j")
NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD", "password") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") # The local folder containing your text files (subset of 20 Newsgroups)
DATA_FOLDER = "path/to/20newsgroups_subset" # Name of the vector index in Neo4j
INDEX_NAME = "my_rag_index"def load_text_files(folder_path: str) -> List[Document]:
"""
Loads all .txt files in the given folder, splitting them into smaller chunks.
Returns a list of LangChain Document objects.
"""
txt_files = glob.glob(os.path.join(folder_path, "*.txt"))
documents = [] text_splitter = RecursiveCharacterTextSplitter(
chunk_size=1000,
chunk_overlap=100
) for file_path in txt_files:
with open(file_path, "r", encoding="utf-8", errors="ignore") as f:
raw_text = f.read() # Split into smaller chunks
splits = text_splitter.split_text(raw_text) # Create Document objects (with optional metadata)
for chunk in splits:
doc = Document(
page_content=chunk,
metadata={"source": file_path} # e.g., store the file name
)
documents.append(doc) return documents def store_embeddings_in_neo4j(documents: List[Document]):
"""
Takes a list of Documents, generates embeddings via LangChain,
and stores them in Neo4j using Neo4jVector.
"""
# Initialize embeddings
embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY) # Build the vector store directly from the documents
# This will create the necessary nodes and relationships in Neo4j
# and store the vector embeddings.
vectorstore = Neo4jVector.from_documents(
documents,
embedding=embeddings,
url=NEO4J_URI,
username=NEO4J_USER,
password=NEO4J_PASSWORD,
index_name=INDEX_NAME
) print(f"Embeddings stored in Neo4j under index name: {INDEX_NAME}") def main():
# 1. Connect to Neo4j (just as a test—optional if you only rely on from_documents())
driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
print("Testing Neo4j connection...")
with driver.session() as session:
result = session.run("RETURN 1 AS test")
print("Neo4j connection OK? ", bool(result.single())) # 2. Load and chunk text data
print("Loading text files from folder:", DATA_FOLDER)
documents = load_text_files(DATA_FOLDER)
print(f"Loaded {len(documents)} chunks from the text files.") # 3. Store embeddings in Neo4j
print("Storing embeddings to Neo4j...")
store_embeddings_in_neo4j(documents) # Cleanup
driver.close()
print("Done.") if __name__ == "__main__":
main()
Query the RAG Agent
Once your data is embedded and stored in Neo4j, use this second script to query the database via a RetrievalQA chain:
import os
from neo4j import GraphDatabase
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Neo4jVector
from langchain.llms import OpenAI
from langchain.chains import RetrievalQA
# --------------------------------------
# Configuration
# --------------------------------------
NEO4J_URI = os.getenv("NEO4J_URI", "neo4j://localhost:7687")
NEO4J_USER = os.getenv("NEO4J_USER", "neo4j")
NEO4J_PASSWORD = os.getenv("NEO4J_PASSWORD", "password") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") # or your chosen LLM provider def main():
# 1) Connect to Neo4j
driver = GraphDatabase.driver(NEO4J_URI, auth=(NEO4J_USER, NEO4J_PASSWORD))
print("Connected to Neo4j.") # 2) Initialize Embeddings & LLM
embeddings = OpenAIEmbeddings(openai_api_key=OPENAI_API_KEY)
llm = OpenAI(openai_api_key=OPENAI_API_KEY, temperature=0) # 3) Load Vector Store
vectorstore = Neo4jVector(
url=NEO4J_URI,
username=NEO4J_USER,
password=NEO4J_PASSWORD,
embedding=embeddings,
index_name="my_rag_index", # The name of your index in Neo4j
) # 4) Create a RetrievalQA chain
qa_chain = RetrievalQA.from_chain_type(
llm=llm,
retriever=vectorstore.as_retriever(search_kwargs={"k": 3})
) # 5) Query the RAG Agent
user_query = "How do I troubleshoot a Python package installation error?"
response = qa_chain.run(user_query) # 6) Print the Answer
print("User query:", user_query)
print("RAG agent response:", response) # Cleanup
driver.close() if __name__ == "__main__":
main()
That’s all there is to it — just embed your content, store it in Neo4j, and run queries through the vector store using LangChain. This quick workflow lets you maintain a powerful, scalable knowledge base for any LLM-powered application.
Teaser on Reinforcement & Short-Term Memory
Building a truly adaptive system requires more than just retrieving knowledge. At our workshop, we’ll explore how incorporating human feedback (reinforcement learning) helps refine responses in real time, ensuring your RAG agent remains both accurate and evolving. Additionally, we’ll demonstrate how short-term memory can be cleverly used to decide whether new information should be discarded or embedded into long-term knowledge — resulting in a system that grows smarter with every interaction.
Join us to learn practical techniques for harnessing short-term memory, leveraging reinforcement, and folding key insights into your agent’s embeddings. The outcome: more robust, context-aware experiences.
Workshop Experience & Prerequisites
Our upcoming workshop is hands-on and designed to give participants a real-world experience in building adaptive RAG agents using Graph Databases and the open-source LLMs. Participants will also experiment with reinforcement learning through human feedback, directly observing how feedback can enhance AI performance in real-time.
To make the most out of this interactive session, participants should ensure they have:
- A Linux or Mac-based Developer’s Laptop
- Windows Users should use a VM or Cloud Instance
- Python Installed: version 3.10 or higher
- (Recommended) Using a miniconda or venv virtual environment
- Docker (Linux or MacOS) Installed: for running a local Neo4j instance
- Basic familiarity with shell operations
Whether you’re an intermediate software engineer or a data scientist with a general AI/ML background, this workshop is structured to boost your skills and deepen your practical knowledge.
Dive Deeper with RAG Agents — Attend This Workshop
Don’t miss out on this opportunity to explore the cutting edge of adaptive AI. You’ll not only learn about the exciting integration of knowledge graphs, short-term memory, and reinforcement learning but will also actively build and refine an adaptive RAG agent yourself.
Mark your calendars (tentatively) for Wednesday, May 14 as the workshop date, and join us in revolutionizing how AI learns, interacts, and adapts. See you there!
About the Author of Adaptive RAG Systems: David vonThenen
David is a Senior AI/ML Engineer at DigitalOcean, where he’s dedicated to empowering developers to build, scale, and deploy AI/ML models in production. He brings deep expertise in building and training models for applications like NLP, data visualization, and real-time analytics. He aims to help users build, train, and deploy AI models efficiently, making advanced machine learning accessible to individuals of all levels.
LinkedIn: https://www.linkedin.com/in/davidvonthenen
GitHub: https://github.com/davidvonthenen