fortunius's picture
[ADD] live status milestones during pipeline execution
936935a verified
Raw
History Blame Contribute Delete
5.42 kB
"""UI GreenMetric RAG Assistant v1.0 — Gradio web interface."""
import os
import queue
import threading
import gradio as gr
from openai import APIError
from src.pipeline import ask, _budget
# ---------------------------------------------------------------------------
# Startup check
# ---------------------------------------------------------------------------
from dotenv import load_dotenv
load_dotenv()
if not os.getenv("DEEPSEEK_API_KEY"):
raise RuntimeError(
"DEEPSEEK_API_KEY not found. "
"Set it in your .env file or as an environment variable."
)
# ---------------------------------------------------------------------------
# ChromaDB startup check — auto-build if missing (HF Spaces deployment)
# ---------------------------------------------------------------------------
def _ensure_chromadb() -> None:
"""Build ChromaDB collection if it doesn't exist on disk.
Handles the case where ``chroma_db/`` was not properly deployed to
HF Spaces, or the collection was accidentally dropped.
"""
import chromadb
collection_name = os.getenv("RAG_COLLECTION", "greenmetric_bgem3")
client = chromadb.PersistentClient(path="./chroma_db")
try:
client.get_collection(collection_name)
print(f"ChromaDB collection '{collection_name}' found.")
except ValueError:
print(f"ChromaDB collection '{collection_name}' not found — building...")
from build_collection import chunk_all
from src.embedder import store
sources = chunk_all()
store(sources, collection_name=collection_name)
print("ChromaDB build complete.")
_ensure_chromadb()
# ---------------------------------------------------------------------------
# Budget helpers
# ---------------------------------------------------------------------------
def _budget_display() -> str:
used = _budget.used()
cap = _budget.daily_cap
pct = min(100, used / cap * 100) if cap else 0
return (
f"{used:,} / {cap:,} tokens used today ({pct:.0f}%)\n\n"
"*Token usage is shared across all users. Resets daily at midnight UTC.*"
)
# ---------------------------------------------------------------------------
# Chat handler
# ---------------------------------------------------------------------------
def respond(message: str, chat_history: list[dict]):
chat_history.append({"role": "user", "content": message})
chat_history.append({"role": "assistant", "content": "Thinking..."})
yield chat_history
result_container: dict = {}
status_queue: "queue.Queue[str]" = queue.Queue()
def _on_status(msg: str) -> None:
status_queue.put(msg)
def _run() -> None:
try:
result_container["result"] = ask(message, _on_status=_on_status)
except APIError:
result_container["api_error"] = True
except Exception as exc:
result_container["error"] = exc
thread = threading.Thread(target=_run, daemon=True)
thread.start()
while True:
try:
status = status_queue.get(timeout=0.3)
chat_history[-1]["content"] = status
yield chat_history
except queue.Empty:
if not thread.is_alive():
break
thread.join()
if "api_error" in result_container:
chat_history[-1]["content"] = (
"The AI service is temporarily unavailable. "
"This may be due to rate limits or API downtime. "
"Please try again in a moment."
)
yield chat_history
return
if "error" in result_container:
chat_history[-1]["content"] = (
f"Something went wrong. Please try again.\n\n"
f"Details: {result_container['error']!s}"
)
yield chat_history
return
result = result_container.get("result")
if result is None:
chat_history[-1]["content"] = "Something went wrong. Please try again."
yield chat_history
return
answer = result["answer"]
if result["low_confidence"]:
answer += "\n\nLow confidence: Retrieved context scored near the relevance threshold."
chat_history[-1]["content"] = answer
yield chat_history
# ---------------------------------------------------------------------------
# Layout
# ---------------------------------------------------------------------------
with gr.Blocks(title="UI GreenMetric RAG Assistant v1.0") as app:
gr.Markdown("# UI GreenMetric RAG Assistant v1.0")
chatbot = gr.Chatbot(label="Chat")
with gr.Row():
msg_input = gr.Textbox(
placeholder="Ask a question about UI GreenMetric...",
show_label=False,
scale=4,
)
send_btn = gr.Button("Send", variant="primary", scale=1)
budget_display = gr.Markdown(_budget_display() + "\n\n*Conversations may be logged for quality monitoring.*")
# --- event bindings ---
def _on_send(msg, hist):
for chat_out in respond(msg, hist):
yield chat_out, _budget_display(), ""
send_btn.click(
fn=_on_send,
inputs=[msg_input, chatbot],
outputs=[chatbot, budget_display, msg_input],
)
msg_input.submit(
fn=_on_send,
inputs=[msg_input, chatbot],
outputs=[chatbot, budget_display, msg_input],
)
if __name__ == "__main__":
app.launch()