serve.py 4.2 KB

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