Spaces:
Paused
Paused
Download sensorflow/help/chat.py from whassan/SensorflowStudio: direct link, hf CLI and curl.
- Browser
- Download file 2.98 kB
-
https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/help/chat.py
- Command line
-
hf download hf://spaces/whassan/SensorflowStudio/sensorflow/help/chat.py
-
curl -L -o chat.py https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/sensorflow/help/chat.py
2.98 kB
| """Help chat: try optional Ollama, always fall back to FAQ matcher (CPU-safe).""" | |
| from __future__ import annotations | |
| import os | |
| from typing import Any, Dict, List, Optional | |
| import httpx | |
| from sensorflow.help.matcher import format_fallback_answer, match_faq | |
| def _llm_endpoints() -> List[Dict[str, str]]: | |
| endpoints: List[Dict[str, str]] = [] | |
| url = os.environ.get("SENSORFLOW_LLM_URL") | |
| if url: | |
| endpoints.append( | |
| { | |
| "url": url if url.endswith("/api/chat") else url.rstrip("/") + "/api/chat", | |
| "model": os.environ.get("SENSORFLOW_LLM_MODEL", "gemma3:latest"), | |
| } | |
| ) | |
| # Local Ollama last — optional enrichment only | |
| endpoints.append({"url": "http://localhost:11434/api/chat", "model": "gemma3:latest"}) | |
| return endpoints | |
| def _build_prompt(question: str, context_blocks: List[str], page_id: Optional[str]) -> str: | |
| ctx = "\n\n".join(context_blocks[:4]) | |
| page_line = f"Current UI page id: {page_id}\n" if page_id else "" | |
| return ( | |
| "You are the Sensorflow Studio in-app help assistant. Answer briefly and accurately " | |
| "using ONLY the context below. If the context is insufficient, say what the user " | |
| "should open in the Help menu. Do not invent APIs or metrics.\n\n" | |
| f"{page_line}" | |
| f"CONTEXT:\n{ctx}\n\n" | |
| f"USER QUESTION: {question}\n\n" | |
| "Answer in plain language (2–6 short sentences). Mention relevant page names when useful." | |
| ) | |
| def answer_help_question(question: str, page_id: Optional[str] = None) -> Dict[str, Any]: | |
| q = (question or "").strip() | |
| if not q: | |
| return { | |
| "answer": "Ask a question about a Sensorflow Studio page or feature.", | |
| "sources": [], | |
| "provider": "faq_offline", | |
| "page_hint": page_id, | |
| } | |
| matches = match_faq(q, page_id=page_id, top_k=4) | |
| offline = format_fallback_answer(q, matches, page_id=page_id) | |
| context_blocks = [f"[{doc.kind}] {doc.title}: {doc.text[:700]}" for doc, _ in matches] | |
| if not context_blocks: | |
| return offline | |
| prompt = _build_prompt(q, context_blocks, page_id) | |
| for ep in _llm_endpoints(): | |
| try: | |
| res = httpx.post( | |
| ep["url"], | |
| json={ | |
| "model": ep["model"], | |
| "messages": [{"role": "user", "content": prompt}], | |
| "stream": False, | |
| }, | |
| timeout=8.0, | |
| ) | |
| if res.status_code == 200: | |
| text = (res.json().get("message") or {}).get("content") or "" | |
| if text.strip(): | |
| return { | |
| "answer": text.strip(), | |
| "sources": offline["sources"], | |
| "provider": ep["url"], | |
| "page_hint": offline.get("page_hint"), | |
| } | |
| except Exception: | |
| continue | |
| return offline | |