Building R2R
Learn how to build and customize R2R applications
Introduction
R2R provides out-of-the-box support for multimodal RAG, hybrid search, knowledge graph-powered RAG, and application management. These functionalities can be accessed directly or through a client-server architecture via the R2R API (specifications here).
Creating an R2R Instance
An R2R instance is typically created using the R2RBuilder
class, which uses the builder pattern to assemble components based on the provided configuration and overrides.
from r2r import R2RConfig, R2RBuilder
config = R2RConfig.from_json("path/to/my_config.json")
app = R2RBuilder(config).build() # defaults to `config.json` when no config is passed
If no configuration file is provided, the engine defaults to the settings in config.json
.
Serving R2R
Every available function in R2R (e.g., app.ingest_files(..)
) can be accessed via a RESTful API.
To launch the server we must construct the app through the get_app
to ensure that dependencies are properly propagated to the API.
from r2r import get_app
app = get_app(R2RBuilder(config))
app.serve()
# alternatively, access FastAPI app directly with app.app
Customizing R2R
Adding Custom Endpoints
You can add custom endpoints to the R2R application:
from fastapi import FastAPI
from r2r import R2RConfig, R2RBuilder
config = R2RConfig.from_json("path/to/config.json")
app = R2RBuilder(config).build()
app = app.app
@app.get("/custom_endpoint")
async def custom_endpoint():
return {"message": "This is a custom endpoint"}
Overriding Method Logic
Existing endpoint logic can be modified by associating a new method with the desired endpoint name:
async def my_aingest_files(
self,
files: list[UploadFile],
metadatas: Optional[list[dict]] = None,
document_ids: Optional[list[uuid.UUID]] = None,
user_ids: Optional[list[Optional[uuid.UUID]]] = None,
versions: Optional[list[str]] = None,
skip_document_info: bool = False,
*args: Any,
**kwargs: Any,
):
# Implement your custom logic here
pass
app.aingest_files = my_aingest_files
Configuring the R2RBuilder
The R2RBuilder
class offers various options for customizing your R2R application.
Configuration Options
config
: An optionalR2RConfig
object.from_config
: An optional string to specify a predefined configuration name.
builder = R2RBuilder(config=my_config)
# or
builder = R2RBuilder(from_config="default")
Overriding Components
Overriding Individual Providers
builder = builder.with_vector_db_provider(my_vector_db_provider)
builder = builder.with_embedding_provider(my_embedding_provider)
builder = builder.with_eval_provider(my_eval_provider)
builder = builder.with_llm_provider(my_llm_provider)
builder = builder.with_prompt_provider(my_prompt_provider)
Overriding Individual Pipes
builder = builder.with_parsing_pipe(my_parsing_pipe)
builder = builder.with_embedding_pipe(my_embedding_pipe)
builder = builder.with_vector_storage_pipe(my_vector_storage_pipe)
builder = builder.with_search_pipe(my_search_pipe)
builder = builder.with_rag_pipe(my_rag_pipe)
builder = builder.with_streaming_rag_pipe(my_streaming_rag_pipe)
builder = builder.with_eval_pipe(my_eval_pipe)
Overriding Pipelines
builder = builder.with_ingestion_pipeline(my_ingestion_pipeline)
builder = builder.with_search_pipeline(my_search_pipeline)
builder = builder.with_rag_pipeline(my_rag_pipeline)
builder = builder.with_streaming_rag_pipeline(my_streaming_rag_pipeline)
builder = builder.with_eval_pipeline(my_eval_pipeline)
Example Usage
Here’s a comprehensive example of configuring and building an R2RCore
with various overrides:
from r2r import (
R2RConfig,
R2RBuilder,
MyCustomR2RCore,
MyCustomProviderFactory,
MyCustomPipeFactory,
MyCustomPipelineFactory,
my_vector_db_provider,
my_embedding_provider,
my_eval_provider,
my_llm_provider,
my_prompt_provider,
my_parsing_pipe,
my_embedding_pipe,
my_vector_storage_pipe,
my_search_pipe,
my_rag_pipe,
my_streaming_rag_pipe,
my_eval_pipe,
my_ingestion_pipeline,
my_search_pipeline,
my_rag_pipeline,
my_streaming_rag_pipeline,
my_eval_pipeline
)
config = R2RConfig.from_json("path/to/my_config.json")
builder = R2RBuilder(config=config)
builder = (
builder.with_app(MyCustomR2RCore)
.with_provider_factory(MyCustomProviderFactory)
.with_pipe_factory(MyCustomPipeFactory)
.with_pipeline_factory(MyCustomPipelineFactory)
.with_vector_db_provider(my_vector_db_provider)
.with_embedding_provider(my_embedding_provider)
.with_eval_provider(my_eval_provider)
.with_llm_provider(my_llm_provider)
.with_prompt_provider(my_prompt_provider)
.with_parsing_pipe(my_parsing_pipe)
.with_embedding_pipe(my_embedding_pipe)
.with_vector_storage_pipe(my_vector_storage_pipe)
.with_search_pipe(my_search_pipe)
.with_rag_pipe(my_rag_pipe)
.with_streaming_rag_pipe(my_streaming_rag_pipe)
.with_eval_pipe(my_eval_pipe)
.with_ingestion_pipeline(my_ingestion_pipeline)
.with_search_pipeline(my_search_pipeline)
.with_rag_pipeline(my_rag_pipeline)
.with_streaming_rag_pipeline(my_streaming_rag_pipeline)
.with_eval_pipeline(my_eval_pipeline)
)
app = builder.build()
Summary
This guide demonstrates how to configure and build an R2RCore
using the R2RBuilder
, allowing you to customize various components and providers to fit your specific needs. By following these steps, you can effectively set up and customize an R2R application, leveraging the flexibility and power of the R2R answer engine.
Was this page helpful?