Spaces:
Sleeping
Sleeping
Download mrag/cli.py from Angshul/Multimodal-RAG: direct link, hf CLI and curl.
- Browser
- Download file 3.23 kB
-
https://huggingface.co/spaces/Angshul/Multimodal-RAG/resolve/main/mrag/cli.py
- Command line
-
hf download hf://spaces/Angshul/Multimodal-RAG/mrag/cli.py
-
curl -L -o cli.py https://huggingface.co/spaces/Angshul/Multimodal-RAG/resolve/main/mrag/cli.py
3.23 kB
| """Command line: python -m mrag {ingest,ask,stats,reset}""" | |
| from __future__ import annotations | |
| import argparse | |
| import json | |
| import logging | |
| import shutil | |
| import sys | |
| from pathlib import Path | |
| from .config import Config | |
| def main(argv: list[str] | None = None) -> int: | |
| ap = argparse.ArgumentParser(prog="mrag", description="Multimodal RAG with free local models") | |
| ap.add_argument("--config", help="JSON config file (env vars MRAG_* override)") | |
| ap.add_argument("--data-dir") | |
| ap.add_argument("-v", "--verbose", action="store_true") | |
| sub = ap.add_subparsers(dest="cmd", required=True) | |
| p = sub.add_parser("ingest", help="index files / folders (pdf, docx, images, txt/md)") | |
| p.add_argument("paths", nargs="+") | |
| p.add_argument("--force", action="store_true", help="re-index unchanged files") | |
| p = sub.add_parser("ask", help="ask a question") | |
| p.add_argument("question") | |
| p.add_argument("--backend", choices=["ollama", "openai", "extractive"]) | |
| p.add_argument("--model") | |
| p.add_argument("--url") | |
| p.add_argument("--no-stream", action="store_true") | |
| p.add_argument("--show-context", action="store_true") | |
| p.add_argument("--json", action="store_true", help="machine-readable output") | |
| sub.add_parser("stats", help="index statistics") | |
| sub.add_parser("reset", help="delete the index and extracted assets") | |
| a = ap.parse_args(argv) | |
| logging.basicConfig(level=logging.INFO if a.verbose else logging.WARNING, format="%(levelname)s %(message)s") | |
| over = {"data_dir": a.data_dir} | |
| if a.cmd == "ask": | |
| over.update(llm_backend=a.backend, llm_model=a.model, llm_url=a.url) | |
| cfg = Config.load(a.config, **over) | |
| if a.cmd == "reset": | |
| d = Path(cfg.data_dir) | |
| if d.exists(): | |
| shutil.rmtree(d) | |
| print(f"removed {d}") | |
| return 0 | |
| from .pipeline import MultimodalRAG | |
| rag = MultimodalRAG(cfg) | |
| try: | |
| if a.cmd == "ingest": | |
| stats = rag.ingest(a.paths, force=a.force, progress=lambda m: print(m, file=sys.stderr)) | |
| print(json.dumps(stats, indent=2)) | |
| return 1 if stats["errors"] else 0 | |
| if a.cmd == "stats": | |
| print(json.dumps(rag.stats(), indent=2)) | |
| return 0 | |
| stream = not (a.no_stream or a.json) | |
| res = rag.ask(a.question, stream=stream) | |
| if a.json: | |
| print(json.dumps({ | |
| "answer": res["answer"], | |
| "texts": [vars(t) for t in res["texts"]], | |
| "images": [vars(i) for i in res["images"]], | |
| }, indent=2, default=str)) | |
| return 0 | |
| if a.show_context: | |
| for i, t in enumerate(res["texts"], 1): | |
| print(f"[{i}] {Path(t.source).name} p.{t.page} ({t.kind}): {t.text[:160]}...") | |
| for i, im in enumerate(res["images"], 1): | |
| print(f"[Img {i}] {Path(im.source).name} p.{im.page} {im.why} -> {im.path}") | |
| print("-" * 60) | |
| if stream: | |
| for piece in res["answer"]: | |
| print(piece, end="", flush=True) | |
| print() | |
| else: | |
| print(res["answer"]) | |
| return 0 | |
| finally: | |
| rag.close() | |
| if __name__ == "__main__": | |
| raise SystemExit(main()) | |