Spaces:
Running
Running
Upload folder using huggingface_hub
Browse files
app.py
CHANGED
|
@@ -97,6 +97,27 @@ async def _pulse(coro, holder, message, interval: int = 9):
|
|
| 97 |
yield _ev(type="commentary", text=f"{message} ({int(time.monotonic() - start)}s)")
|
| 98 |
|
| 99 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
async def _agent_explain(agent, user_text: str, trip: TripRequest, result) -> str:
|
| 101 |
"""Round 2 — Nemotron compares the packages. Best-effort ('' on failure)."""
|
| 102 |
args_json = json.dumps(trip.model_dump(mode="json"))
|
|
@@ -136,6 +157,11 @@ async def plan_trip(user_text: str) -> str:
|
|
| 136 |
+ Nemotron's explanation). Falls back to the deterministic parser if the
|
| 137 |
agent is unavailable or hedges.
|
| 138 |
"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 139 |
yield _ev(type="commentary", text="Reading your trip request…")
|
| 140 |
|
| 141 |
agent = None
|
|
|
|
| 97 |
yield _ev(type="commentary", text=f"{message} ({int(time.monotonic() - start)}s)")
|
| 98 |
|
| 99 |
|
| 100 |
+
# Cached per-boot preflight (N35). Fail-fast ONLY on genuinely-doomed config
|
| 101 |
+
# (missing SerpApi key — build_trip_packages cannot fetch live flights/hotels).
|
| 102 |
+
# Modal cold-start is NOT a hard failure: it streams via _pulse heartbeats and
|
| 103 |
+
# the loop degrades to the deterministic parser, so we don't gate on it.
|
| 104 |
+
_PREFLIGHT_OK: bool | None = None
|
| 105 |
+
|
| 106 |
+
|
| 107 |
+
def _preflight() -> tuple[bool, str]:
|
| 108 |
+
"""Return (ok, reason). ``reason`` is empty when ok. Cached positive."""
|
| 109 |
+
global _PREFLIGHT_OK
|
| 110 |
+
if _PREFLIGHT_OK:
|
| 111 |
+
return True, ""
|
| 112 |
+
if not os.environ.get("SERPAPI_API_KEY"):
|
| 113 |
+
return False, (
|
| 114 |
+
"SerpApi key is not set on this Space — live flight & hotel search is "
|
| 115 |
+
"unavailable. Add SERPAPI_API_KEY in Settings → Secrets, then restart."
|
| 116 |
+
)
|
| 117 |
+
_PREFLIGHT_OK = True
|
| 118 |
+
return True, ""
|
| 119 |
+
|
| 120 |
+
|
| 121 |
async def _agent_explain(agent, user_text: str, trip: TripRequest, result) -> str:
|
| 122 |
"""Round 2 — Nemotron compares the packages. Best-effort ('' on failure)."""
|
| 123 |
args_json = json.dumps(trip.model_dump(mode="json"))
|
|
|
|
| 157 |
+ Nemotron's explanation). Falls back to the deterministic parser if the
|
| 158 |
agent is unavailable or hedges.
|
| 159 |
"""
|
| 160 |
+
ok, why = _preflight() # N35 — fail-fast on doomed config (missing key)
|
| 161 |
+
if not ok:
|
| 162 |
+
yield _ev(type="error", text=f"⚠️ {why}")
|
| 163 |
+
return
|
| 164 |
+
|
| 165 |
yield _ev(type="commentary", text="Reading your trip request…")
|
| 166 |
|
| 167 |
agent = None
|