Cardiosense-AG commited on
Commit
d923822
·
verified ·
1 Parent(s): 834143d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +107 -102
app.py CHANGED
@@ -1,59 +1,85 @@
 
1
  import os
2
  import platform
3
- from pathlib import Path
4
  import time
5
- import traceback
 
6
 
7
  import streamlit as st
8
  import pandas as pd
9
 
10
- from src.paths import base_dir, guidelines_dir, faiss_index_dir, exports_dir
 
 
 
 
 
 
 
 
 
 
 
 
11
 
12
- st.set_page_config(page_title="AI-Native E-Consult Prototype (V1)", page_icon="🩺", layout="wide")
13
  st.title("AI‑Native E‑Consult Prototype (V1)")
14
  st.caption("Step 0 — Environment Setup & Health Check")
15
  st.warning("Demo only — de‑identified data. Prototype for feedback; **not for clinical use**.", icon="🛑")
16
 
 
 
 
17
 
 
 
18
 
19
- # ---------- Helper ----------
20
- def _try_import(modname: str):
21
  try:
22
  m = __import__(modname)
23
- ver = getattr(m, "__version__", "n/a")
24
- return True, ver, None
25
- except Exception as e:
26
- return False, None, str(e)
27
-
28
- def _hf_whoami():
29
- try:
30
- from huggingface_hub import whoami
31
- token = os.getenv("HF_TOKEN") or os.getenv("HUGGINGFACEHUB_API_TOKEN")
32
- if not token:
33
- return False, None, "No HF token found. Add HF_TOKEN in Space Settings → Variables."
34
- me = whoami(token=token)
35
- return True, me, None
36
  except Exception as e:
37
- return False, None, str(e)
38
-
39
- # ---------- Persistent dirs ----------
40
- bdir = base_dir()
41
- gdir = guidelines_dir()
42
- idir = faiss_index_dir()
43
- xdir = exports_dir()
44
-
45
- with st.expander("📁 Storage locations (persistent)"):
46
- st.write({
47
- "base_dir": str(bdir),
48
- "guidelines_dir": str(gdir),
49
- "faiss_index_dir": str(idir),
50
- "exports_dir": str(xdir),
 
51
  })
52
- st.caption("These live on the Space's persistent volume so your RAG index survives restarts.")
53
 
54
- # ---------- Diagnostics ----------
55
- colA, colB = st.columns(2)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
56
 
 
57
  with colA:
58
  st.subheader("System")
59
  st.write({
@@ -61,76 +87,55 @@ with colA:
61
  "platform": platform.platform(),
62
  "cwd": str(Path.cwd()),
63
  "time": time.strftime("%Y-%m-%d %H:%M:%S"),
 
 
64
  })
65
- ok_torch, torch_ver, torch_err = _try_import("torch")
66
- if ok_torch:
67
- import torch
68
- cuda = torch.cuda.is_available()
69
- device = torch.cuda.get_device_name(0) if cuda else "CPU"
70
- st.success(f"torch {torch_ver} — CUDA: {'✅' if cuda else '❌'} — device: {device}")
71
- else:
72
- st.error(f"torch import failed: {torch_err}")
73
 
74
  with colB:
75
- st.subheader("Core libraries")
76
- rows = []
77
- for name in ["transformers", "accelerate", "bitsandbytes", "faiss", "pypdf", "pandas", "numpy", "huggingface_hub", "sentence_transformers"]:
78
- ok, ver, err = _try_import(name)
79
- rows.append({"library": name, "status": "ok" if ok else "error", "version_or_error": ver if ok else err})
80
- st.dataframe(pd.DataFrame(rows), hide_index=True, use_container_width=True)
81
-
82
- st.divider()
83
- st.subheader("Hugging Face auth check (for later model pulls)")
84
- if st.button("Check HF token"):
85
- ok, me, err = _hf_whoami()
86
- if ok:
87
- who = me.get("name") or me.get("email") or me.get("username", "unknown")
88
- st.success(f"HF token valid ✅ — signed in as: {who}")
89
- else:
90
- st.warning(f"HF token not verified: {err}")
91
-
92
- st.subheader("Quick functionality tests")
93
- if st.button("Run health checks"):
94
- results = []
95
-
96
- # 1) Write to persistent storage
97
- try:
98
- testfile = bdir / "healthcheck.txt"
99
- testfile.write_text("ok\n")
100
- results.append(("write_persistent", True, f"wrote {testfile}"))
101
- except Exception as e:
102
- results.append(("write_persistent", False, str(e)))
103
-
104
- # 2) FAISS in-memory index sanity test
105
  try:
106
- import numpy as np, faiss
107
- xb = np.random.random((50, 8)).astype("float32")
108
- idx = faiss.IndexFlatL2(8)
109
- idx.add(xb)
110
- D, I = idx.search(xb[:1], 5)
111
- results.append(("faiss_search", True, f"top5 ids: {I[0].tolist()}"))
112
- except Exception as e:
113
- results.append(("faiss_search", False, str(e)))
114
 
115
- # 3) bitsandbytes soft check (import + CUDA capability if torch has it)
116
- try:
117
- import bitsandbytes as bnb # noqa
118
- cuda_msg = ""
119
- try:
120
- import torch
121
- if torch.cuda.is_available():
122
- # light test: allocate a tiny 4-bit linear layer if available
123
- from bitsandbytes.nn import Linear4bit
124
- _ = Linear4bit(8, 8, bias=False)
125
- cuda_msg = "CUDA-backed 4-bit layer constructed."
126
- except Exception:
127
- pass
128
- results.append(("bitsandbytes", True, f"import ok. {cuda_msg}"))
129
- except Exception as e:
130
- results.append(("bitsandbytes", False, str(e)))
131
 
132
- st.success("Health checks complete.")
133
- st.dataframe(pd.DataFrame([{"check": k, "ok": ok, "detail": d} for (k, ok, d) in results]),
134
- hide_index=True, use_container_width=True)
 
 
 
 
135
 
136
- st.info("If the checks are green, the Space is ready for Step 1 (RAG Corpus Prep).")
 
1
+ # app.py
2
  import os
3
  import platform
 
4
  import time
5
+ from pathlib import Path
6
+ from typing import Dict
7
 
8
  import streamlit as st
9
  import pandas as pd
10
 
11
+ from src.paths import (
12
+ base_dir,
13
+ guidelines_dir,
14
+ faiss_index_dir,
15
+ exports_dir,
16
+ cases_dir,
17
+ audit_dir,
18
+ hf_cache_dir,
19
+ initialize_environment,
20
+ describe_paths,
21
+ )
22
+
23
+ st.set_page_config(page_title="AI‑Native E‑Consult — Health Check", page_icon="🩺", layout="wide")
24
 
 
25
  st.title("AI‑Native E‑Consult Prototype (V1)")
26
  st.caption("Step 0 — Environment Setup & Health Check")
27
  st.warning("Demo only — de‑identified data. Prototype for feedback; **not for clinical use**.", icon="🛑")
28
 
29
+ # ---------- Initialize env & log ----------
30
+ env = initialize_environment()
31
+ st.session_state.setdefault("_app_env", env)
32
 
33
+ with st.expander("Environment variables (runtime)", expanded=False):
34
+ st.json(env)
35
 
36
+ # ---------- Dependency checks ----------
37
+ def _probe_import(modname: str):
38
  try:
39
  m = __import__(modname)
40
+ ver = getattr(m, "__version__", "")
41
+ # faiss exposes version differently sometimes
42
+ if modname == "faiss" and not ver:
43
+ ver = getattr(m, "FAISS_VERSION", "") or ""
44
+ return True, ver, ""
 
 
 
 
 
 
 
 
45
  except Exception as e:
46
+ return False, "", f"{type(e).__name__}: {e}"
47
+
48
+ mods = [
49
+ "torch", "accelerate", "transformers", "bitsandbytes", "faiss",
50
+ "sentence_transformers", "pypdf", "huggingface_hub", "numpy", "pandas"
51
+ ]
52
+
53
+ rows = []
54
+ for name in mods:
55
+ ok, ver, err = _probe_import(name)
56
+ rows.append({
57
+ "package": name,
58
+ "status": "✅" if ok else "❌",
59
+ "version": ver,
60
+ "error": err,
61
  })
 
62
 
63
+ st.subheader("Python packages")
64
+ st.dataframe(pd.DataFrame(rows), use_container_width=True)
65
+
66
+ # ---------- CUDA ----------
67
+ cuda_txt = "Not checked"
68
+ gpu_name = ""
69
+ try:
70
+ import torch
71
+ has_cuda = torch.cuda.is_available()
72
+ cuda_txt = "✅ Available" if has_cuda else "❌ Not available"
73
+ if has_cuda:
74
+ try:
75
+ gpu_name = torch.cuda.get_device_name(0)
76
+ except Exception:
77
+ gpu_name = "CUDA detected (name unavailable)"
78
+ except Exception as e:
79
+ has_cuda = False
80
+ cuda_txt = f"⚠️ Torch import error: {e}"
81
 
82
+ colA, colB = st.columns(2)
83
  with colA:
84
  st.subheader("System")
85
  st.write({
 
87
  "platform": platform.platform(),
88
  "cwd": str(Path.cwd()),
89
  "time": time.strftime("%Y-%m-%d %H:%M:%S"),
90
+ "CUDA": cuda_txt,
91
+ "GPU": gpu_name,
92
  })
 
 
 
 
 
 
 
 
93
 
94
  with colB:
95
+ st.subheader("Paths")
96
+ pinfo: Dict[str, str] = describe_paths()
97
+ st.write(pinfo)
98
+
99
+ # basic directory status
100
+ def _count_pdfs(p: Path) -> int:
101
+ return sum(1 for _ in p.glob("**/*.pdf"))
102
+
103
+ def _human_bytes(n: int) -> str:
104
+ for u in ["B", "KB", "MB", "GB", "TB"]:
105
+ if n < 1024:
106
+ return f"{n:.1f} {u}"
107
+ n /= 1024
108
+ return f"{n:.1f} PB"
109
+
110
+ # quick cache dir size
111
+ cache = Path(pinfo["hf_cache_dir"])
112
+ size = 0
 
 
 
 
 
 
 
 
 
 
 
 
113
  try:
114
+ for root, _, files in os.walk(cache):
115
+ for f in files:
116
+ try:
117
+ size += (Path(root) / f).stat().st_size
118
+ except Exception:
119
+ pass
120
+ except Exception:
121
+ pass
122
 
123
+ st.write({
124
+ "guideline_pdfs": _count_pdfs(Path(pinfo["guidelines_dir"])),
125
+ "index_present": (
126
+ (Path(pinfo["faiss_index_dir"]) / "faiss.index").exists()
127
+ and (Path(pinfo["faiss_index_dir"]) / "chunks.jsonl").exists()
128
+ and (Path(pinfo["faiss_index_dir"]) / "index_info.json").exists()
129
+ ),
130
+ "hf_cache_size": _human_bytes(size),
131
+ })
 
 
 
 
 
 
 
132
 
133
+ st.info(
134
+ "**Model selection**\n\n"
135
+ f"- Primary: `{os.getenv('MODEL_ID', 'google/medgemma-27b-text-it')}` (GPU / 4-bit)\n"
136
+ f"- Fallback: `{os.getenv('MODEL_FALLBACK_ID', 'google/medgemma-4b-it')}` (CPU)\n"
137
+ f"- Stub mode (`E2E_STUB=1`): returns deterministic output for UI tests.",
138
+ icon="⚙️"
139
+ )
140
 
141
+ st.success("Health page loaded. Proceed to **Step 1 RAG Corpus Prep** from the sidebar when ready.", icon="➡️")