Spaces:
Sleeping
Sleeping
File size: 5,417 Bytes
28431e9 d82f721 936935a d82f721 66af080 d82f721 936935a d82f721 936935a d82f721 936935a d82f721 936935a d82f721 28431e9 d82f721 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 | """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()
|