rag-uigreenmetric / src /conversation.py
fortunius's picture
Upload src/conversation.py with huggingface_hub
7a9d132 verified
Raw
History Blame Contribute Delete
3.09 kB
"""Conversation logging for the UI GreenMetric RAG system.
Logs user queries and generated answers to a HF Dataset for
analysis and monitoring. Uses the same repo as budget tracking.
"""
import json
import os
import time
from datetime import datetime, timezone
from threading import Lock
from dotenv import load_dotenv
load_dotenv()
# ---------------------------------------------------------------------------
# HF logger
# ---------------------------------------------------------------------------
class ConversationLogger:
def __init__(self, repo_id: str):
self.repo_id = repo_id
self.token = os.getenv("HF_TOKEN")
self._buffer: list[dict] = []
self._lock = Lock()
def log(self, entry: dict) -> None:
with self._lock:
self._buffer.append(entry)
def flush(self) -> None:
with self._lock:
if not self._buffer:
return
try:
from huggingface_hub import upload_file, hf_hub_download
tmp = "/tmp/rag_conversations.jsonl"
try:
existing = hf_hub_download(
repo_id=self.repo_id,
filename="conversations.jsonl",
repo_type="dataset",
token=self.token,
)
import shutil
shutil.copy(existing, tmp)
except Exception:
open(tmp, "w").close() # fresh file
with open(tmp, "a") as f:
for e in self._buffer:
f.write(json.dumps(e, ensure_ascii=False) + "\n")
upload_file(
path_or_fileobj=tmp,
path_in_repo="conversations.jsonl",
repo_id=self.repo_id,
repo_type="dataset",
token=self.token,
)
self._buffer.clear()
except Exception:
pass # silent — conversation logging is best-effort
# ---------------------------------------------------------------------------
# Singleton
# ---------------------------------------------------------------------------
_logger: ConversationLogger | None = None
def get_logger() -> ConversationLogger | None:
global _logger
if _logger is None:
repo = os.getenv("RAG_BUDGET_REPO", "")
if repo and os.getenv("HF_TOKEN"):
_logger = ConversationLogger(repo)
return _logger
def log_conversation(
query: str,
answer: str,
route: dict,
chunks: list[str],
tokens: int,
) -> None:
logger = get_logger()
if logger is None:
return
logger.log({
"ts": datetime.now(timezone.utc).isoformat(),
"user_prompt": query,
"response": answer,
"router_source": route.get("source", "?"),
"router_csv_source": route.get("csv_source"),
"query_type": route.get("query_type", "?"),
"token_usage": tokens,
"chunks": chunks,
})