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 optional R2RConfig 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.