kz110AIPI commited on
Commit
4213665
·
1 Parent(s): ada7257

Improve Hugging Face model artifact loading

Browse files
src/campus_triage/app.py CHANGED
@@ -20,7 +20,7 @@ for import_path in (SRC_DIR, ROOT_DIR):
20
  import streamlit as st
21
 
22
  from campus_triage.config import CATEGORY_LABELS, URGENCY_LABELS
23
- from campus_triage.predict import EXAMPLE_MESSAGES, load_deployed_model, model_available, predict_message
24
 
25
 
26
  CUSTOM_CSS = """
@@ -354,7 +354,9 @@ def run_app() -> None:
354
  render_status_strip()
355
 
356
  if not model_available():
357
- st.error("No trained model found. Run `make data` and `make train`, then relaunch with `streamlit run main.py`.")
 
 
358
  st.stop()
359
 
360
  model = load_deployed_model()
 
20
  import streamlit as st
21
 
22
  from campus_triage.config import CATEGORY_LABELS, URGENCY_LABELS
23
+ from campus_triage.predict import EXAMPLE_MESSAGES, load_deployed_model, model_available, model_search_diagnostics, predict_message
24
 
25
 
26
  CUSTOM_CSS = """
 
354
  render_status_strip()
355
 
356
  if not model_available():
357
+ st.error("No trained model artifact was found for inference.")
358
+ st.caption("The app checked these local and Hugging Face deployment paths:")
359
+ st.code(model_search_diagnostics())
360
  st.stop()
361
 
362
  model = load_deployed_model()
src/campus_triage/predict.py CHANGED
@@ -11,13 +11,11 @@ import tempfile
11
  from pathlib import Path
12
  from typing import Any
13
 
14
- from campus_triage.config import CATEGORY_LABELS, CLASSICAL_MODEL_PATH, ROUTING_RECOMMENDATIONS, URGENCY_LABELS
15
  from campus_triage.features import keyword_explanation
16
  from campus_triage.models import load_dual_classifier
17
 
18
 
19
- ENCODED_CLASSICAL_MODEL_PATH = CLASSICAL_MODEL_PATH.with_suffix(CLASSICAL_MODEL_PATH.suffix + ".b64")
20
-
21
  EXAMPLE_MESSAGES = [
22
  "My FAFSA documents still say incomplete and tuition is due tomorrow. Can someone help?",
23
  "I cannot register for BIO 101 because there is a hold on my account.",
@@ -26,19 +24,42 @@ EXAMPLE_MESSAGES = [
26
  ]
27
 
28
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
29
  def resolve_deployed_model_path(model_path: Path = CLASSICAL_MODEL_PATH) -> Path | None:
30
  """Return a loadable model path, decoding the text artifact when needed."""
31
 
32
- if model_path.exists():
33
- return model_path
34
- if not ENCODED_CLASSICAL_MODEL_PATH.exists():
35
- return None
36
 
37
- decoded_path = Path(tempfile.gettempdir()) / model_path.name
38
- if not decoded_path.exists():
39
- encoded_text = ENCODED_CLASSICAL_MODEL_PATH.read_text(encoding="ascii")
40
- decoded_path.write_bytes(base64.b64decode(encoded_text))
41
- return decoded_path
 
 
 
42
 
43
 
44
  def model_available(model_path: Path = CLASSICAL_MODEL_PATH) -> bool:
@@ -47,13 +68,20 @@ def model_available(model_path: Path = CLASSICAL_MODEL_PATH) -> bool:
47
  return resolve_deployed_model_path(model_path) is not None
48
 
49
 
 
 
 
 
 
 
 
50
  def load_deployed_model(model_path: Path = CLASSICAL_MODEL_PATH) -> Any:
51
  """Load the deployed classical model."""
52
 
53
  resolved_model_path = resolve_deployed_model_path(model_path)
54
  if resolved_model_path is None:
55
  raise FileNotFoundError(
56
- f"Model not found at {model_path} or {ENCODED_CLASSICAL_MODEL_PATH}. Run `make data` and `make train` before launching the app."
57
  )
58
  return load_dual_classifier(str(resolved_model_path))
59
 
 
11
  from pathlib import Path
12
  from typing import Any
13
 
14
+ from campus_triage.config import CATEGORY_LABELS, CLASSICAL_MODEL_PATH, PROJECT_ROOT, ROUTING_RECOMMENDATIONS, URGENCY_LABELS
15
  from campus_triage.features import keyword_explanation
16
  from campus_triage.models import load_dual_classifier
17
 
18
 
 
 
19
  EXAMPLE_MESSAGES = [
20
  "My FAFSA documents still say incomplete and tuition is due tomorrow. Can someone help?",
21
  "I cannot register for BIO 101 because there is a hold on my account.",
 
24
  ]
25
 
26
 
27
+ def candidate_model_paths(model_path: Path = CLASSICAL_MODEL_PATH) -> list[Path]:
28
+ """Return likely binary model locations across local and hosted layouts."""
29
+
30
+ package_root = Path(__file__).resolve().parents[2]
31
+ current_root = Path.cwd()
32
+ candidates = [
33
+ model_path,
34
+ PROJECT_ROOT / "models" / model_path.name,
35
+ package_root / "models" / model_path.name,
36
+ current_root / "models" / model_path.name,
37
+ Path("/app/models") / model_path.name,
38
+ ]
39
+ return list(dict.fromkeys(candidates))
40
+
41
+
42
+ def candidate_encoded_model_paths(model_path: Path = CLASSICAL_MODEL_PATH) -> list[Path]:
43
+ """Return likely text-encoded model locations across local and hosted layouts."""
44
+
45
+ return [path.with_suffix(path.suffix + ".b64") for path in candidate_model_paths(model_path)]
46
+
47
+
48
  def resolve_deployed_model_path(model_path: Path = CLASSICAL_MODEL_PATH) -> Path | None:
49
  """Return a loadable model path, decoding the text artifact when needed."""
50
 
51
+ for candidate_path in candidate_model_paths(model_path):
52
+ if candidate_path.exists():
53
+ return candidate_path
 
54
 
55
+ for encoded_path in candidate_encoded_model_paths(model_path):
56
+ if encoded_path.exists():
57
+ decoded_path = Path(tempfile.gettempdir()) / model_path.name
58
+ if not decoded_path.exists():
59
+ encoded_text = encoded_path.read_text(encoding="ascii")
60
+ decoded_path.write_bytes(base64.b64decode(encoded_text))
61
+ return decoded_path
62
+ return None
63
 
64
 
65
  def model_available(model_path: Path = CLASSICAL_MODEL_PATH) -> bool:
 
68
  return resolve_deployed_model_path(model_path) is not None
69
 
70
 
71
+ def model_search_diagnostics(model_path: Path = CLASSICAL_MODEL_PATH) -> str:
72
+ """Return a readable list of model paths checked during deployment."""
73
+
74
+ checked_paths = candidate_model_paths(model_path) + candidate_encoded_model_paths(model_path)
75
+ return "\n".join(str(path) for path in checked_paths)
76
+
77
+
78
  def load_deployed_model(model_path: Path = CLASSICAL_MODEL_PATH) -> Any:
79
  """Load the deployed classical model."""
80
 
81
  resolved_model_path = resolve_deployed_model_path(model_path)
82
  if resolved_model_path is None:
83
  raise FileNotFoundError(
84
+ "No deployed model artifact found. Checked these paths:\n" + model_search_diagnostics(model_path)
85
  )
86
  return load_dual_classifier(str(resolved_model_path))
87