1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
|
import argparse
import asyncio
import logging
import os
import sys
from typing import Optional
logger = logging.getLogger(__name__)
try:
from core import R2RApp, R2RBuilder, R2RConfig
from core.utils.logging_config import configure_logging
except ImportError as e:
logger.error(
f"Failed to start server: core dependencies not installed: {e}"
)
logger.error("To run the server, install the required dependencies:")
logger.error("pip install 'r2r[core]'")
sys.exit(1)
async def create_app(
config_name: Optional[str] = None,
config_path: Optional[str] = None,
full: bool = False,
) -> "R2RApp":
"""
Creates and returns an R2R application instance based on the provided
or environment-sourced configuration.
"""
# If arguments not passed, fall back to environment variables
config_name = config_name or os.getenv("R2R_CONFIG_NAME")
config_path = config_path or os.getenv("R2R_CONFIG_PATH")
if config_path and config_name:
raise ValueError(
f"Cannot specify both config_path and config_name, got {config_path} and {config_name}"
)
if not config_path and not config_name:
# If neither is specified nor set in environment,
# default to 'full' if --full is True, else 'default'
config_name = "full" if full else "default"
try:
r2r_instance = await R2RBuilder(
config=R2RConfig.load(config_name, config_path)
).build()
# Start orchestration worker
await r2r_instance.orchestration_provider.start_worker()
return r2r_instance
except ImportError as e:
logger.error(f"Failed to initialize R2R: {e}")
logger.error(
"Please check your configuration and installed dependencies"
)
sys.exit(1)
def run_server(
host: Optional[str] = None,
port: Optional[int] = None,
config_name: Optional[str] = None,
config_path: Optional[str] = None,
full: bool = False,
):
"""
Runs the R2R server with the provided or environment-based settings.
"""
# Overwrite environment variables if arguments are explicitly passed
if host is not None:
os.environ["R2R_HOST"] = host
if port is not None:
os.environ["R2R_PORT"] = str(port)
if config_path is not None:
os.environ["R2R_CONFIG_PATH"] = config_path
if config_name is not None:
os.environ["R2R_CONFIG_NAME"] = config_name
# Fallback to environment or defaults if necessary
final_host = os.getenv("R2R_HOST", "0.0.0.0")
final_port = int(os.getenv("R2R_PORT", "7272"))
try:
configure_logging()
except Exception as e:
logger.error(f"Failed to configure logging: {e}")
try:
async def start():
app = await create_app(config_name, config_path, full)
await app.serve(final_host, final_port)
asyncio.run(start())
except Exception as e:
logger.error(f"Failed to start R2R server: {e}")
sys.exit(1)
def main():
"""
Parse command-line arguments and then run the server.
"""
parser = argparse.ArgumentParser(description="Run the R2R server.")
parser.add_argument(
"--host",
default=None,
help="Host to bind to. Overrides R2R_HOST env if provided.",
)
parser.add_argument(
"--port",
default=None,
type=int,
help="Port to bind to. Overrides R2R_PORT env if provided.",
)
parser.add_argument(
"--config-path",
default=None,
help="Path to the configuration file. Overrides R2R_CONFIG_PATH env if provided.",
)
parser.add_argument(
"--config-name",
default=None,
help="Name of the configuration. Overrides R2R_CONFIG_NAME env if provided.",
)
parser.add_argument(
"--full",
action="store_true",
help="Use the 'full' config if neither config-path nor config-name is specified.",
)
args = parser.parse_args()
run_server(
host=args.host,
port=args.port,
config_name=args.config_name,
config_path=args.config_path,
full=args.full,
)
if __name__ == "__main__":
main()
|