Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -1,13 +1,15 @@
|
|
| 1 |
# app.py — Spine Coder (Chatbot + Feedback + Session Logs) — Gradio 4.x
|
| 2 |
# ------------------------------------------------------------------------------
|
| 3 |
-
# FINAL-v2.1 UI build (hardened):
|
| 4 |
# - Purge caches, dynamic file loader (SPINE_CORE_PATH override) + SHA print
|
| 5 |
# - Startup PROBE to logs + in-UI Diagnostics/Probe
|
| 6 |
# - Clean CPT table (no per-row modifier columns) + Case Modifiers panel
|
| 7 |
# - Build/Core chips, structured logs/export, modern Gradio usage
|
|
|
|
| 8 |
# ------------------------------------------------------------------------------
|
| 9 |
|
| 10 |
import os
|
|
|
|
| 11 |
import json
|
| 12 |
import uuid
|
| 13 |
import pathlib
|
|
@@ -121,6 +123,26 @@ os.environ.setdefault("GRADIO_ANALYTICS_ENABLED", "False")
|
|
| 121 |
DEBUG = os.environ.get("DEBUG", "0") == "1"
|
| 122 |
PAYER_CHOICES = ["Medicare", "BCBS", "Aetna", "Cigna", "UnitedHealthcare", "Other"]
|
| 123 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 124 |
# ==== Logging =================================================================
|
| 125 |
LOG_DIR = os.environ.get("LOG_DIR", "logs")
|
| 126 |
pathlib.Path(LOG_DIR).mkdir(parents=True, exist_ok=True)
|
|
@@ -131,10 +153,59 @@ def _log_path(session_id: str) -> str:
|
|
| 131 |
def _utcnow_iso() -> str:
|
| 132 |
return datetime.now(timezone.utc).isoformat(timespec="seconds")
|
| 133 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 134 |
def _append_log(session_id: str, entry: Dict[str, Any]) -> None:
|
| 135 |
entry = {"ts": _utcnow_iso(), "session_id": session_id, **entry}
|
|
|
|
| 136 |
with open(_log_path(session_id), "a", encoding="utf-8") as f:
|
| 137 |
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
|
|
|
|
|
|
| 138 |
|
| 139 |
def export_session(session_id: str) -> str:
|
| 140 |
src = _log_path(session_id)
|
|
|
|
| 1 |
# app.py — Spine Coder (Chatbot + Feedback + Session Logs) — Gradio 4.x
|
| 2 |
# ------------------------------------------------------------------------------
|
| 3 |
+
# FINAL-v2.1 UI build (hardened) + LIVE REPO LOGGING:
|
| 4 |
# - Purge caches, dynamic file loader (SPINE_CORE_PATH override) + SHA print
|
| 5 |
# - Startup PROBE to logs + in-UI Diagnostics/Probe
|
| 6 |
# - Clean CPT table (no per-row modifier columns) + Case Modifiers panel
|
| 7 |
# - Build/Core chips, structured logs/export, modern Gradio usage
|
| 8 |
+
# - Optional: push each log line to your Space repo (logs-live/YYYY-MM-DD.jsonl)
|
| 9 |
# ------------------------------------------------------------------------------
|
| 10 |
|
| 11 |
import os
|
| 12 |
+
import io
|
| 13 |
import json
|
| 14 |
import uuid
|
| 15 |
import pathlib
|
|
|
|
| 123 |
DEBUG = os.environ.get("DEBUG", "0") == "1"
|
| 124 |
PAYER_CHOICES = ["Medicare", "BCBS", "Aetna", "Cigna", "UnitedHealthcare", "Other"]
|
| 125 |
|
| 126 |
+
# ==== Remote log push settings (optional) =====================================
|
| 127 |
+
# Set HF_TOKEN (or HUGGINGFACEHUB_API_TOKEN) as a Space secret with write access.
|
| 128 |
+
# LOG_PUSH_ENABLE=1 to enable. Defaults to current Space repo (SPACE_ID) if HF_TARGET_REPO not set.
|
| 129 |
+
LOG_PUSH_ENABLE = os.environ.get("LOG_PUSH_ENABLE", "0") == "1"
|
| 130 |
+
HF_TARGET_REPO = os.environ.get("HF_TARGET_REPO") or os.environ.get("SPACE_ID") # e.g., "Slaiwala/Vertebro"
|
| 131 |
+
HF_WRITE_TOKEN = (
|
| 132 |
+
os.environ.get("HF_TOKEN") or
|
| 133 |
+
os.environ.get("HUGGINGFACEHUB_API_TOKEN")
|
| 134 |
+
)
|
| 135 |
+
HF_REPO_TYPE = "space" # keep this as 'space' for Spaces
|
| 136 |
+
|
| 137 |
+
# Lazy import to avoid runtime dependency if not enabled
|
| 138 |
+
_hf_api = None
|
| 139 |
+
def _get_hf_api():
|
| 140 |
+
global _hf_api
|
| 141 |
+
if _hf_api is None:
|
| 142 |
+
from huggingface_hub import HfApi
|
| 143 |
+
_hf_api = HfApi(token=HF_WRITE_TOKEN)
|
| 144 |
+
return _hf_api
|
| 145 |
+
|
| 146 |
# ==== Logging =================================================================
|
| 147 |
LOG_DIR = os.environ.get("LOG_DIR", "logs")
|
| 148 |
pathlib.Path(LOG_DIR).mkdir(parents=True, exist_ok=True)
|
|
|
|
| 153 |
def _utcnow_iso() -> str:
|
| 154 |
return datetime.now(timezone.utc).isoformat(timespec="seconds")
|
| 155 |
|
| 156 |
+
def _push_log_line_to_repo(entry: Dict[str, Any]) -> None:
|
| 157 |
+
"""Append a single JSON line to logs-live/YYYY-MM-DD.jsonl in the Space repo."""
|
| 158 |
+
if not LOG_PUSH_ENABLE:
|
| 159 |
+
return
|
| 160 |
+
if not HF_TARGET_REPO or not HF_WRITE_TOKEN:
|
| 161 |
+
return
|
| 162 |
+
try:
|
| 163 |
+
from huggingface_hub import CommitOperationAdd, hf_hub_download
|
| 164 |
+
api = _get_hf_api()
|
| 165 |
+
|
| 166 |
+
day = datetime.utcnow().strftime("%Y-%m-%d")
|
| 167 |
+
path_in_repo = f"logs-live/{day}.jsonl"
|
| 168 |
+
|
| 169 |
+
# Get existing file (if any)
|
| 170 |
+
existing = ""
|
| 171 |
+
try:
|
| 172 |
+
local_fp = hf_hub_download(
|
| 173 |
+
repo_id=HF_TARGET_REPO,
|
| 174 |
+
filename=path_in_repo,
|
| 175 |
+
repo_type=HF_REPO_TYPE,
|
| 176 |
+
token=HF_WRITE_TOKEN,
|
| 177 |
+
local_dir="/tmp",
|
| 178 |
+
local_dir_use_symlinks=False,
|
| 179 |
+
force_download=False,
|
| 180 |
+
)
|
| 181 |
+
with open(local_fp, "r", encoding="utf-8") as f:
|
| 182 |
+
existing = f.read()
|
| 183 |
+
except Exception:
|
| 184 |
+
existing = ""
|
| 185 |
+
|
| 186 |
+
# Append one line
|
| 187 |
+
new_line = json.dumps(entry, ensure_ascii=False)
|
| 188 |
+
if existing and not existing.endswith("\n"):
|
| 189 |
+
existing += "\n"
|
| 190 |
+
merged = (existing + new_line + "\n").encode("utf-8")
|
| 191 |
+
|
| 192 |
+
api.create_commit(
|
| 193 |
+
repo_id=HF_TARGET_REPO,
|
| 194 |
+
repo_type=HF_REPO_TYPE,
|
| 195 |
+
operations=[CommitOperationAdd(path_in_repo=path_in_repo, path_or_fileobj=io.BytesIO(merged))],
|
| 196 |
+
commit_message=f"logs: append {day} ({entry.get('event','')})",
|
| 197 |
+
)
|
| 198 |
+
except Exception as e:
|
| 199 |
+
# Never break the app due to logging; just print.
|
| 200 |
+
print("[LOG PUSH] failed:", e)
|
| 201 |
+
|
| 202 |
def _append_log(session_id: str, entry: Dict[str, Any]) -> None:
|
| 203 |
entry = {"ts": _utcnow_iso(), "session_id": session_id, **entry}
|
| 204 |
+
# Local JSONL (unchanged)
|
| 205 |
with open(_log_path(session_id), "a", encoding="utf-8") as f:
|
| 206 |
f.write(json.dumps(entry, ensure_ascii=False) + "\n")
|
| 207 |
+
# NEW: push to repo (optional)
|
| 208 |
+
_push_log_line_to_repo(entry)
|
| 209 |
|
| 210 |
def export_session(session_id: str) -> str:
|
| 211 |
src = _log_path(session_id)
|