|
|
import gradio as gr |
|
|
import requests |
|
|
import json |
|
|
import os |
|
|
import shutil |
|
|
import threading |
|
|
import mimetypes |
|
|
from models import OptimizeRequest, AutotuneRequest, QARequest |
|
|
from api import start_api |
|
|
|
|
|
threading.Thread(target=start_api, daemon=True).start() |
|
|
|
|
|
|
|
|
BASE_INTERNAL = "http://127.0.0.1:8000" |
|
|
|
|
|
|
|
|
def call_api(endpoint: str, payload: dict) -> str: |
|
|
try: |
|
|
r = requests.post(f"{BASE_INTERNAL}{endpoint}", json=payload, timeout=120) |
|
|
return json.dumps(r.json(), indent=2) |
|
|
except Exception as e: |
|
|
return str(e) |
|
|
|
|
|
|
|
|
def upload_docs_tool(files, docs_path="data/docs"): |
|
|
""" |
|
|
Upload documents to the server's docs folder. |
|
|
|
|
|
Accepts local file paths or URLs. Returns a list of MCP FileData-like dicts. |
|
|
""" |
|
|
os.makedirs(docs_path, exist_ok=True) |
|
|
saved = [] |
|
|
|
|
|
for f in files: |
|
|
if f.startswith("http://") or f.startswith("https://"): |
|
|
|
|
|
r = requests.get(f, stream=True) |
|
|
fname = f.split("/")[-1] |
|
|
dest = os.path.join(docs_path, fname) |
|
|
with open(dest, "wb") as out_file: |
|
|
shutil.copyfileobj(r.raw, out_file) |
|
|
else: |
|
|
|
|
|
fname = os.path.basename(f) |
|
|
dest = os.path.join(docs_path, fname) |
|
|
shutil.copy(f, dest) |
|
|
|
|
|
mime_type = mimetypes.guess_type(dest)[0] or "application/octet-stream" |
|
|
saved.append({ |
|
|
"path": dest, |
|
|
"url": f"file://{os.path.abspath(dest)}", |
|
|
"orig_name": fname, |
|
|
"mime_type": mime_type, |
|
|
"is_stream": False, |
|
|
"meta": {} |
|
|
}) |
|
|
|
|
|
return {"status": "ok", "uploaded_files": saved, "docs_path": docs_path} |
|
|
|
|
|
|
|
|
def optimize_rag_tool(payload: str) -> str: |
|
|
"""🔧 Explicit optimization request: user provides all pipeline configs manually.""" |
|
|
return call_api("/optimize_rag", json.loads(payload)) |
|
|
|
|
|
|
|
|
def autotune_tool(payload: str) -> str: |
|
|
"""🔧 Autotune RAG: recommends chunk sizes and embedding models automatically.""" |
|
|
return call_api("/autotune_rag", json.loads(payload)) |
|
|
|
|
|
|
|
|
def generate_qa_tool(payload: str) -> str: |
|
|
"""🧩 Generates a validation QA dataset for RAG evaluation.""" |
|
|
return call_api("/generate_validation_qa", json.loads(payload)) |
|
|
|
|
|
|
|
|
|
|
|
optimize_rag_tool.__doc__ = OptimizeRequest.__doc__ |
|
|
autotune_tool.__doc__ = AutotuneRequest.__doc__ |
|
|
generate_qa_tool.__doc__ = QARequest.__doc__ |
|
|
|
|
|
|
|
|
def model_to_json(model_cls) -> str: |
|
|
return json.dumps({k: v.default for k, v in model_cls.__fields__.items()}, indent=2) |
|
|
|
|
|
|
|
|
|
|
|
DEFAULT_UPLOAD_PATH = "data/docs" |
|
|
DEFAULT_OPTIMIZE_JSON = model_to_json(OptimizeRequest) |
|
|
DEFAULT_AUTOTUNE_JSON = model_to_json(AutotuneRequest) |
|
|
DEFAULT_QA_JSON = model_to_json(QARequest) |
|
|
|
|
|
with gr.Blocks(theme=gr.themes.Soft()) as demo: |
|
|
gr.Markdown("# Ragmint MCP Client") |
|
|
|
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("## Upload Documents") |
|
|
gr.Markdown("📂 Upload files (local paths or URLs) to your `data/docs` folder") |
|
|
upload_files = gr.File(file_count="multiple", type="filepath") |
|
|
upload_path = gr.Textbox(value=DEFAULT_UPLOAD_PATH, label="Docs Path") |
|
|
upload_btn = gr.Button("Upload", variant="primary") |
|
|
upload_out = gr.JSON(label="Response") |
|
|
upload_btn.click(upload_docs_tool, inputs=[upload_files, upload_path], outputs=upload_out) |
|
|
gr.Markdown("---") |
|
|
|
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("## Optimize RAG") |
|
|
gr.Markdown(OptimizeRequest.__doc__ or "No description available.") |
|
|
optimize_input = gr.Textbox(lines=12, value=DEFAULT_OPTIMIZE_JSON, label="OptimizeRequest JSON") |
|
|
optimize_btn = gr.Button("Submit", variant="primary") |
|
|
optimize_out = gr.Textbox(lines=15, label="Response") |
|
|
optimize_btn.click(optimize_rag_tool, inputs=optimize_input, outputs=optimize_out) |
|
|
gr.Markdown("---") |
|
|
|
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("## Autotune RAG") |
|
|
gr.Markdown(AutotuneRequest.__doc__ or "No description available.") |
|
|
autotune_input = gr.Textbox(lines=12, value=DEFAULT_AUTOTUNE_JSON, label="AutotuneRequest JSON") |
|
|
autotune_btn = gr.Button("Submit", variant="primary") |
|
|
autotune_out = gr.Textbox(lines=15) |
|
|
autotune_btn.click(autotune_tool, inputs=autotune_input, outputs=autotune_out) |
|
|
gr.Markdown("---") |
|
|
|
|
|
|
|
|
with gr.Column(): |
|
|
gr.Markdown("## Generate QA") |
|
|
gr.Markdown(QARequest.__doc__ or "No description available.") |
|
|
qa_input = gr.Textbox(lines=12, value=DEFAULT_QA_JSON, label="QARequest JSON") |
|
|
qa_btn = gr.Button("Submit", variant="primary") |
|
|
qa_out = gr.Textbox(lines=15, label="Response") |
|
|
qa_btn.click(generate_qa_tool, inputs=qa_input, outputs=qa_out) |
|
|
gr.Markdown("---") |
|
|
|
|
|
if __name__ == "__main__": |
|
|
demo.launch( |
|
|
server_name="0.0.0.0", |
|
|
server_port=7860, |
|
|
mcp_server=True, |
|
|
show_error=True |
|
|
) |
|
|
|