Skip to content

Commit

Permalink
merge (#934)
Browse files Browse the repository at this point in the history
  • Loading branch information
emrgnt-cmplxty authored Aug 22, 2024
1 parent b7308e1 commit c8024ba
Show file tree
Hide file tree
Showing 18 changed files with 99 additions and 194 deletions.
1 change: 0 additions & 1 deletion compose.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ services:
- PYTHONUNBUFFERED=1
- PORT=${PORT:-8000}
- HOST=${HOST:-0.0.0.0}
- BASE_URL=${BASE_URL:-http://localhost}

# R2R
- CONFIG_NAME=${CONFIG_NAME:-}
Expand Down
25 changes: 2 additions & 23 deletions py/cli/command_group.py
Original file line number Diff line number Diff line change
@@ -1,31 +1,10 @@
import os

import click
from sdk.client import R2RClient


# TODO: refactor this to remove config path and config name
@click.group()
@click.option(
"--config-path", default=None, help="Path to the configuration file"
)
@click.option(
"--config-name", default=None, help="Name of the configuration to use"
)
@click.option(
"--base-url",
default="http://localhost:8000",
help="Base URL for client mode",
)
@click.pass_context
def cli(ctx, config_path, config_name, base_url):
def cli(ctx):
"""R2R CLI for all core operations."""
if config_path and config_name:
raise click.UsageError(
"Cannot specify both config_path and config_name"
)

if config_path:
config_path = os.path.abspath(config_path)

ctx.obj = R2RClient(base_url)
ctx.obj = R2RClient()
12 changes: 10 additions & 2 deletions py/cli/commands/server.py
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,14 @@ def generate_report():
)
@click.option("--project-name", default="r2r", help="Project name for Docker")
@click.option("--image", help="Docker image to use")
@click.option("--config-path", help="Path to the configuration file")
@click.option(
"--config-name", default=None, help="Name of the R2R configuration to use"
)
@click.option(
"--config-path",
default=None,
help="Path to a custom R2R configuration file",
)
@click.pass_obj
def serve(
client,
Expand All @@ -194,6 +201,7 @@ def serve(
exclude_postgres,
project_name,
image,
config_name,
config_path,
):
"""Start the R2R server."""
Expand Down Expand Up @@ -239,7 +247,7 @@ def serve(
click.echo(f"Opening browser to {url}")
webbrowser.open(url)
else:
run_local_serve(client, host, port)
run_local_serve(host, port, config_name, config_path)


@cli.command()
Expand Down
26 changes: 15 additions & 11 deletions py/cli/utils/docker_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -73,8 +73,11 @@ def remove_r2r_network():


def run_local_serve(
obj: R2RClient, host: str, port: int, config_path: Optional[str] = None
):
host: str,
port: int,
config_name: Optional[str] = None,
config_path: Optional[str] = None,
) -> None:
try:
from r2r import R2R
except ImportError:
Expand All @@ -83,14 +86,17 @@ def run_local_serve(
)
sys.exit(1)

r2r_instance = R2R()
llm_provider = r2r_instance.config.completion.provider
llm_model = r2r_instance.config.completion.generation_config.model
model_provider = llm_model.split("/")[0]
r2r_instance = R2R(config_name=config_name, config_path=config_path)

if config_name or config_path:
completion_config = r2r_instance.config.completion
llm_provider = completion_config.provider
llm_model = completion_config.generation_config.model
model_provider = llm_model.split("/")[0]
check_llm_reqs(llm_provider, model_provider, include_ollama=True)

available_port = find_available_port(port)

check_llm_reqs(llm_provider, model_provider, include_ollama=True)
r2r_instance.serve(host, available_port)


Expand All @@ -115,10 +121,8 @@ def run_docker_serve(
config_name = client.config_name
else:
config_name = "default"

config = R2RConfig.from_toml(
R2RBuilder.CONFIG_OPTIONS[config_name]
)

config = R2RConfig.from_toml(R2RBuilder.CONFIG_OPTIONS[config_name])

completion_provider = config.completion.provider
completion_model = config.completion.generation_config.model
Expand Down
4 changes: 3 additions & 1 deletion py/core/main/api/routes/auth/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,9 @@


class AuthRouter(BaseRouter):
def __init__(self, engine: "R2REngine", run_type: RunType = RunType.INGESTION):
def __init__(
self, engine: "R2REngine", run_type: RunType = RunType.INGESTION
):
super().__init__(engine, run_type)
self.setup_routes()

Expand Down
4 changes: 3 additions & 1 deletion py/core/main/api/routes/ingestion/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@


class IngestionRouter(BaseRouter):
def __init__(self, engine: R2REngine, run_type: RunType = RunType.INGESTION):
def __init__(
self, engine: R2REngine, run_type: RunType = RunType.INGESTION
):
super().__init__(engine, run_type)
self.openapi_extras = self.load_openapi_extras()
self.setup_routes()
Expand Down
10 changes: 7 additions & 3 deletions py/core/main/api/routes/management/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@


class ManagementRouter(BaseRouter):
def __init__(self, engine: R2REngine, run_type: RunType = RunType.MANAGEMENT):
def __init__(
self, engine: R2REngine, run_type: RunType = RunType.MANAGEMENT
):
super().__init__(engine, run_type)
self.start_time = datetime.now(timezone.utc)
self.setup_routes()
Expand Down Expand Up @@ -99,8 +101,10 @@ async def get_analytics_app(

try:
result = await self.engine.aanalytics(
filter_criteria=LogFilterCriteria(**filter_criteria),
analysis_types=AnalysisTypes(**analysis_types),
filter_criteria=LogFilterCriteria(filters=filter_criteria),
analysis_types=AnalysisTypes(
analysis_types=analysis_types
),
)
return result
except json.JSONDecodeError as e:
Expand Down
4 changes: 3 additions & 1 deletion py/core/main/api/routes/restructure/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@


class RestructureRouter(BaseRouter):
def __init__(self, engine: R2REngine, run_type: RunType = RunType.RESTRUCTURE):
def __init__(
self, engine: R2REngine, run_type: RunType = RunType.RESTRUCTURE
):
super().__init__(engine, run_type)
self.setup_routes()

Expand Down
4 changes: 3 additions & 1 deletion py/core/main/api/routes/retrieval/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,9 @@


class RetrievalRouter(BaseRouter):
def __init__(self, engine: R2REngine, run_type: RunType = RunType.RETRIEVAL):
def __init__(
self, engine: R2REngine, run_type: RunType = RunType.RETRIEVAL
):
super().__init__(engine, run_type)
self.openapi_extras = self.load_openapi_extras()
self.setup_routes()
Expand Down
4 changes: 0 additions & 4 deletions py/core/main/app_entry.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ class PipelineType(Enum):
def r2r_app(
config_name: Optional[str] = "default",
config_path: Optional[str] = None,
base_url: Optional[str] = None,
pipeline_type: PipelineType = PipelineType.QNA,
) -> FastAPI:
if pipeline_type != PipelineType.QNA:
Expand Down Expand Up @@ -58,19 +57,16 @@ def r2r_app(
config_path = os.getenv("CONFIG_PATH", None)
if not config_path and not config_name:
config_name = "default"
base_url = os.getenv("BASE_URL")
host = os.getenv("HOST", "0.0.0.0")
port = int(os.getenv("PORT", "8000"))
pipeline_type = os.getenv("PIPELINE_TYPE", "qna")

logger.info(f"Environment CONFIG_NAME: {config_name}")
logger.info(f"Environment CONFIG_PATH: {config_path}")
logger.info(f"Environment BASE_URL: {base_url}")
logger.info(f"Environment PIPELINE_TYPE: {pipeline_type}")

app = r2r_app(
config_name=config_name,
config_path=config_path,
base_url=base_url,
pipeline_type=PipelineType(pipeline_type),
)
15 changes: 11 additions & 4 deletions py/core/main/assembly/builder.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,9 @@ class R2RBuilder:
CONFIG_OPTIONS["default"] = None

@staticmethod
def _get_config(config_name):
def _get_config(config_name, config_path=None):
if config_path:
return R2RConfig.from_toml(config_path)
if config_name is None:
return R2RConfig.from_toml()
if config_name in R2RBuilder.CONFIG_OPTIONS:
Expand All @@ -55,10 +57,15 @@ def __init__(
self,
config: Optional[R2RConfig] = None,
config_name: Optional[str] = None,
config_path: Optional[str] = None,
):
if config and config_name:
raise ValueError("Cannot specify both config and config_name")
self.config = config or R2RBuilder._get_config(config_name)
if sum(x is not None for x in [config, config_name, config_path]) > 1:
raise ValueError(
"Specify only one of config, config_name, or config_path"
)
self.config = config or R2RBuilder._get_config(
config_name, config_path
)
self.r2r_app_override: Optional[Type[R2REngine]] = None
self.provider_factory_override: Optional[Type[R2RProviderFactory]] = (
None
Expand Down
1 change: 1 addition & 0 deletions py/core/main/assembly/factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@ def create_prompt_provider(
prompt_provider = None
if prompt_config.provider == "r2r":
from core.providers import R2RPromptProvider

prompt_provider = R2RPromptProvider(prompt_config)
else:
raise ValueError(
Expand Down
13 changes: 3 additions & 10 deletions py/core/main/r2r.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ def __init__(
app: Optional[R2RApp] = None,
config: Optional[R2RConfig] = None,
config_name: Optional[str] = None,
config_path: Optional[str] = None,
*args,
**kwargs,
):
Expand All @@ -40,25 +41,17 @@ def __init__(
if engine and app:
self.engine = engine
self.app = app
elif (config or config_name) or (
config is None and config_name is None
):
else:
from .assembly.builder import R2RBuilder

# Handle the case where 'config_name' is None and 'config' is None
if not config and not config_name:
config_name = "default"
builder = R2RBuilder(
config=config,
config_name=config_name,
config_path=config_path,
)
built = builder.build()
self.engine = built.engine
self.app = built.app
else:
raise ValueError(
"Must provide either 'engine' and 'app', or 'config'/'config_name' to build the R2R object."
)

def __getattr__(self, name):
# Check if the attribute name is 'app' and return it directly
Expand Down
22 changes: 12 additions & 10 deletions py/core/main/services/management_service.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import json
import logging
import uuid
from collections import defaultdict
from typing import Any, Dict, List, Optional, Tuple
from uuid import UUID
Expand Down Expand Up @@ -63,17 +62,17 @@ async def alogs(
aggregated_logs = []

for run in run_info:
run_logs = [
log for log in logs if log["run_id"] == run.run_id
]
run_logs = [log for log in logs if log["run_id"] == run.run_id]
entries = [
{
"key": log["key"],
"value": log["value"],
"timestamp": log["timestamp"],
}
for log in run_logs
][::-1] # Reverse order so that earliest logged values appear first.
][
::-1
] # Reverse order so that earliest logged values appear first.

log_entry = {
"run_id": str(run.run_id),
Expand Down Expand Up @@ -133,8 +132,8 @@ async def aanalytics(
)

filtered_logs = dict(log_processor.populations.items())
results = {"filtered_logs": filtered_logs}

analytics_data = {}
if analysis_types and analysis_types.analysis_types:
for (
filter_key,
Expand All @@ -144,22 +143,22 @@ async def aanalytics(
analysis_type = analysis_config[0]
if analysis_type == "bar_chart":
extract_key = analysis_config[1]
results[filter_key] = (
analytics_data[filter_key] = (
AnalysisTypes.generate_bar_chart_data(
filtered_logs[filter_key], extract_key
)
)
elif analysis_type == "basic_statistics":
extract_key = analysis_config[1]
results[filter_key] = (
analytics_data[filter_key] = (
AnalysisTypes.calculate_basic_statistics(
filtered_logs[filter_key], extract_key
)
)
elif analysis_type == "percentile":
extract_key = analysis_config[1]
percentile = int(analysis_config[2])
results[filter_key] = (
analytics_data[filter_key] = (
AnalysisTypes.calculate_percentile(
filtered_logs[filter_key],
extract_key,
Expand All @@ -171,7 +170,10 @@ async def aanalytics(
f"Unknown analysis type for filter key '{filter_key}': {analysis_type}"
)

return results
return {
"analytics_data": analytics_data or None,
"filtered_logs": filtered_logs,
}

@telemetry_event("AppSettings")
async def aapp_settings(self, *args: Any, **kwargs: Any):
Expand Down
4 changes: 1 addition & 3 deletions py/core/pipelines/ingestion_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,9 +123,7 @@ async def process_documents():
"embedding_pipeline_output": (
results[0] if self.embedding_pipeline else None
),
"kg_pipeline_output": (
results[-1] if self.kg_pipeline else None
),
"kg_pipeline_output": (results[-1] if self.kg_pipeline else None),
}

def add_pipe(
Expand Down
4 changes: 3 additions & 1 deletion py/core/providers/chunking/r2r_chunking.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,9 @@ def _initialize_text_splitter(self) -> TextSplitter:
chunk_overlap=self.config.chunk_overlap,
)
elif self.config.method == Method.BASIC:
raise NotImplementedError("Basic chunking method not implemented. Please use Recursive.")
raise NotImplementedError(
"Basic chunking method not implemented. Please use Recursive."
)
elif self.config.method == Method.BY_TITLE:
raise NotImplementedError("By title method not implemented")
else:
Expand Down
Loading

0 comments on commit c8024ba

Please sign in to comment.