Using Retrieval Augmented Generation (RAG)¶
Genie Tooling provides a flexible RAG system through the genie.rag
interface, allowing you to index data from various sources and perform semantic searches.
Core RAG Operations via genie.rag
¶
The genie.rag
interface simplifies common RAG tasks:
genie.rag.index_directory(path, collection_name, ...)
: Indexes all supported files within a local directory.genie.rag.index_web_page(url, collection_name, ...)
: Fetches content from a web URL, extracts text, and indexes it.genie.rag.search(query, collection_name, top_k, ...)
: Performs a semantic search against an indexed collection.
Configuring RAG Components¶
RAG components (Document Loaders, Text Splitters, Embedding Generators, Vector Stores, Retrievers) are configured primarily using FeatureSettings
within your MiddlewareConfig
.
import asyncio
from pathlib import Path
from genie_tooling.config.models import MiddlewareConfig
from genie_tooling.config.features import FeatureSettings
from genie_tooling.genie import Genie
async def main():
app_config = MiddlewareConfig(
features=FeatureSettings(
# RAG Embedder (e.g., for creating embeddings of your documents)
rag_embedder="sentence_transformer", # Alias for "sentence_transformer_embedder_v1"
# rag_embedder_st_model_name="all-MiniLM-L6-v2", # Default ST model
# RAG Vector Store (e.g., for storing and searching embeddings)
rag_vector_store="faiss", # Alias for "faiss_vector_store_v1" (in-memory)
# Or for persistent ChromaDB:
# rag_vector_store="chroma",
# rag_vector_store_chroma_path="./my_rag_db",
# rag_vector_store_chroma_collection_name="my_documents",
# Or for Qdrant:
# rag_vector_store="qdrant", # Example using Qdrant
# rag_vector_store_qdrant_url="http://localhost:6333", # Or path for local Qdrant
# rag_vector_store_qdrant_collection_name="my_qdrant_docs",
# rag_vector_store_qdrant_embedding_dim=384, # Set to your embedder's dimension (e.g., 384 for all-MiniLM-L6-v2)
# Default RAG Loader (used by index_directory if not specified)
rag_loader="file_system", # Alias for "file_system_loader_v1" (default for index_directory)
# For index_web_page, it defaults to "web_page_loader_v1" internally if rag_loader is "web_page" or not set.
)
)
genie = await Genie.create(config=app_config)
# Create a dummy directory and file for indexing
data_path = Path("./rag_data_example")
data_path.mkdir(exist_ok=True)
(data_path / "sample.txt").write_text("Genie makes RAG easy and configurable.")
# Index the directory
collection = "my_sample_collection"
await genie.rag.index_directory(str(data_path), collection_name=collection)
print(f"Indexed documents from '{data_path}' into '{collection}'.")
# Search the collection
query = "How is RAG with Genie?"
results = await genie.rag.search(query, collection_name=collection, top_k=1)
if results:
print(f"Search for '{query}':")
for res in results:
print(f" - Score: {res.score:.4f}, Content: {res.content[:100]}...")
else:
print(f"No results found for '{query}'.")
# Clean up dummy data
(data_path / "sample.txt").unlink(missing_ok=True)
if data_path.exists(): data_path.rmdir() # Only rmdir if it's empty and exists
await genie.close()
if __name__ == "__main__":
asyncio.run(main())
Overriding RAG Component Configurations¶
You can override configurations for specific RAG component plugins (Document Loaders, Text Splitters, Embedding Generators, Vector Stores, Retrievers) using their respective *_configurations
dictionaries in MiddlewareConfig
.
For example, to configure the WebPageLoader
to use Trafilatura for better content extraction when genie.rag.index_web_page()
is called (and rag_loader
feature is set to "web_page"
or not set, allowing the default):
app_config = MiddlewareConfig(
features=FeatureSettings(
rag_loader="web_page", # Explicitly or implicitly uses web_page_loader_v1
rag_embedder="sentence_transformer",
rag_vector_store="faiss"
),
document_loader_configurations={
"web_page_loader_v1": { # Canonical ID of the WebPageLoader
"use_trafilatura": True,
# "trafilatura_include_comments": False # Other loader-specific settings
}
},
embedding_generator_configurations={
"sentence_transformer_embedder_v1": {
"model_name": "paraphrase-multilingual-MiniLM-L12-v2" # Use a different ST model
}
}
)
When calling genie.rag.index_directory()
or genie.rag.search()
, you can also pass loader_id
, splitter_id
, embedder_id
, vector_store_id
, retriever_id
, and their corresponding *_config
dictionaries to override the defaults for that specific call.
Advanced Usage¶
The genie.rag
interface internally uses the RAGManager
. For advanced scenarios requiring direct interaction with the RAGManager
or individual RAG component plugins, you can access it via genie._rag_manager
(though this is generally not needed for typical use cases).
Refer to Creating RAG Plugins for information on developing your own RAG components.