Bhaskar Ram
feat: Python package, FastAPI REST server, TypeScript SDK
634117a
"""
kerdos_rag/cli.py
Command-line interface for the Kerdos RAG engine.
kerdos-rag serve # start Gradio UI (default port 7860)
kerdos-rag api # start FastAPI REST server (default port 8000)
kerdos-rag index <files> # index documents from terminal
"""
from __future__ import annotations
import argparse
import sys
def _cmd_serve(args: argparse.Namespace) -> None:
"""Launch the Gradio web UI."""
import importlib.util, os
os.environ.setdefault("GRADIO_SERVER_PORT", str(args.port))
os.environ.setdefault("GRADIO_SERVER_NAME", args.host)
# app.py lives at the repo root — import it as a module
spec = importlib.util.spec_from_file_location("app", _repo_root() / "app.py")
mod = importlib.util.module_from_spec(spec)
spec.loader.exec_module(mod)
mod.demo.queue()
mod.demo.launch(css=mod.CSS, theme=__import__("gradio").themes.Soft())
def _cmd_api(args: argparse.Namespace) -> None:
"""Launch the FastAPI REST server."""
import uvicorn
from kerdos_rag.server import app # noqa: F401
print(f"[kerdos-rag] Starting REST API on http://{args.host}:{args.port}")
uvicorn.run(
"kerdos_rag.server:app",
host=args.host,
port=args.port,
reload=args.reload,
log_level="info",
)
def _cmd_index(args: argparse.Namespace) -> None:
"""Index documents from the command line and print a summary."""
from kerdos_rag import KerdosRAG
engine = KerdosRAG() # token not needed for pure indexing
result = engine.index(args.files)
if result["indexed"]:
print(f"✅ Indexed: {', '.join(result['indexed'])}")
if result["skipped"]:
print(f"⚠️ Skipped (already indexed): {', '.join(result['skipped'])}")
print(f"📦 Total chunks: {result['chunk_count']}")
if args.save:
engine.save(args.save)
print(f"💾 Index saved to: {args.save}")
def _repo_root():
"""Return the directory containing this package."""
from pathlib import Path
return Path(__file__).resolve().parent.parent
def main(argv: list[str] | None = None) -> None:
parser = argparse.ArgumentParser(
prog="kerdos-rag",
description="Kerdos RAG — Enterprise Document Q&A engine",
)
sub = parser.add_subparsers(dest="command", required=True)
# ── serve ────────────────────────────────────────────────────────────────
p_serve = sub.add_parser("serve", help="Start the Gradio web UI")
p_serve.add_argument("--host", default="0.0.0.0")
p_serve.add_argument("--port", type=int, default=7860)
p_serve.set_defaults(func=_cmd_serve)
# ── api ──────────────────────────────────────────────────────────────────
p_api = sub.add_parser("api", help="Start the FastAPI REST server")
p_api.add_argument("--host", default="0.0.0.0")
p_api.add_argument("--port", type=int, default=8000)
p_api.add_argument("--reload", action="store_true", help="Enable auto-reload (dev only)")
p_api.set_defaults(func=_cmd_api)
# ── index ─────────────────────────────────────────────────────────────────
p_idx = sub.add_parser("index", help="Index documents from the terminal")
p_idx.add_argument("files", nargs="+", metavar="FILE")
p_idx.add_argument("--save", metavar="DIR", default="", help="Save index to directory")
p_idx.set_defaults(func=_cmd_index)
args = parser.parse_args(argv)
args.func(args)
if __name__ == "__main__":
main()