Spaces:
Sleeping
Sleeping
Upload app.py
Browse files
app.py
CHANGED
|
@@ -10,10 +10,13 @@ from huggingface_hub import InferenceClient
|
|
| 10 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 11 |
# CONFIG
|
| 12 |
|
| 13 |
-
#
|
| 14 |
-
#
|
| 15 |
-
MODEL_ID = os.environ.get("MODEL_ID", "
|
| 16 |
-
|
|
|
|
|
|
|
|
|
|
| 17 |
|
| 18 |
|
| 19 |
REPO_PATH = "/data/questions.json" # where we store generated questions
|
|
@@ -335,10 +338,19 @@ def try_parse_json(text: str) -> Optional[Dict[str, Any]]:
|
|
| 335 |
|
| 336 |
# π§ SIMPLIFIED, ROBUST MODEL CALL (no secrets required)
|
| 337 |
def model_call(prompt: str) -> str:
|
|
|
|
|
|
|
|
|
|
| 338 |
if not MODEL_ID:
|
| 339 |
-
raise RuntimeError("MODEL_ID env var is
|
| 340 |
|
| 341 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 342 |
|
| 343 |
try:
|
| 344 |
out = client.text_generation(
|
|
@@ -349,10 +361,11 @@ def model_call(prompt: str) -> str:
|
|
| 349 |
return_full_text=False,
|
| 350 |
)
|
| 351 |
except Exception as e:
|
|
|
|
| 352 |
raise RuntimeError(f"Inference API error: {e}") from e
|
| 353 |
|
| 354 |
if not out:
|
| 355 |
-
raise RuntimeError("
|
| 356 |
|
| 357 |
return out.strip()
|
| 358 |
|
|
@@ -387,7 +400,12 @@ def normalize_output(
|
|
| 387 |
|
| 388 |
|
| 389 |
def ai_generate(lang: str, category_key: str, variant: str) -> Dict[str, Any]:
|
|
|
|
|
|
|
|
|
|
|
|
|
| 390 |
prompt = build_prompt(lang, category_key, variant)
|
|
|
|
| 391 |
try:
|
| 392 |
raw_text = model_call(prompt)
|
| 393 |
parsed = try_parse_json(raw_text) if raw_text else None
|
|
@@ -395,29 +413,40 @@ def ai_generate(lang: str, category_key: str, variant: str) -> Dict[str, Any]:
|
|
| 395 |
if parsed:
|
| 396 |
return normalize_output(parsed, lang, category_key, variant)
|
| 397 |
|
| 398 |
-
#
|
| 399 |
few = FEWSHOTS[lang][category_key]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 400 |
return {
|
| 401 |
"category": category_key,
|
| 402 |
"language": lang,
|
| 403 |
-
"questions":
|
| 404 |
-
"micro_actions":
|
| 405 |
"tone": "fallback",
|
| 406 |
-
"safety_notes":
|
|
|
|
|
|
|
|
|
|
| 407 |
}
|
|
|
|
| 408 |
except Exception as e:
|
| 409 |
-
#
|
| 410 |
few = FEWSHOTS[lang][category_key]
|
|
|
|
|
|
|
|
|
|
|
|
|
| 411 |
return {
|
| 412 |
"category": category_key,
|
| 413 |
"language": lang,
|
| 414 |
-
"questions":
|
| 415 |
-
"micro_actions":
|
| 416 |
"tone": "error",
|
| 417 |
"safety_notes": f"Model call error: {type(e).__name__}: {e}",
|
| 418 |
}
|
| 419 |
|
| 420 |
-
|
| 421 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 422 |
# MAIN LOGIC: REPO + SESSION "SEEN" QUESTIONS
|
| 423 |
|
|
|
|
| 10 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 11 |
# CONFIG
|
| 12 |
|
| 13 |
+
# Default to a serverless text-generation model. You can override this in Space
|
| 14 |
+
# settings by defining a MODEL_ID variable if you want to experiment.
|
| 15 |
+
MODEL_ID = os.environ.get("MODEL_ID", "google/gemma-2-2b-it")
|
| 16 |
+
|
| 17 |
+
# Personal access token from your Hugging Face account (Space secret).
|
| 18 |
+
HF_TOKEN = os.environ.get("HF_TOKEN")
|
| 19 |
+
|
| 20 |
|
| 21 |
|
| 22 |
REPO_PATH = "/data/questions.json" # where we store generated questions
|
|
|
|
| 338 |
|
| 339 |
# π§ SIMPLIFIED, ROBUST MODEL CALL (no secrets required)
|
| 340 |
def model_call(prompt: str) -> str:
|
| 341 |
+
"""
|
| 342 |
+
Call Hugging Face Inference API using a single text-generation call.
|
| 343 |
+
"""
|
| 344 |
if not MODEL_ID:
|
| 345 |
+
raise RuntimeError("MODEL_ID env var is empty. Set it or use the default.")
|
| 346 |
|
| 347 |
+
# HF_TOKEN must be defined as a Secret in the Space (read-only token is enough)
|
| 348 |
+
if not HF_TOKEN:
|
| 349 |
+
raise RuntimeError(
|
| 350 |
+
"HF_TOKEN is not set. Add a Hugging Face token as a Space secret named HF_TOKEN."
|
| 351 |
+
)
|
| 352 |
+
|
| 353 |
+
client = InferenceClient(model=MODEL_ID, token=HF_TOKEN)
|
| 354 |
|
| 355 |
try:
|
| 356 |
out = client.text_generation(
|
|
|
|
| 361 |
return_full_text=False,
|
| 362 |
)
|
| 363 |
except Exception as e:
|
| 364 |
+
# Bubble up a clear error so ai_generate can surface it
|
| 365 |
raise RuntimeError(f"Inference API error: {e}") from e
|
| 366 |
|
| 367 |
if not out:
|
| 368 |
+
raise RuntimeError("Inference API returned an empty response.")
|
| 369 |
|
| 370 |
return out.strip()
|
| 371 |
|
|
|
|
| 400 |
|
| 401 |
|
| 402 |
def ai_generate(lang: str, category_key: str, variant: str) -> Dict[str, Any]:
|
| 403 |
+
"""
|
| 404 |
+
Try to call the model. If anything fails or JSON is invalid,
|
| 405 |
+
fall back to shuffling the few-shots and include a safety_notes message.
|
| 406 |
+
"""
|
| 407 |
prompt = build_prompt(lang, category_key, variant)
|
| 408 |
+
|
| 409 |
try:
|
| 410 |
raw_text = model_call(prompt)
|
| 411 |
parsed = try_parse_json(raw_text) if raw_text else None
|
|
|
|
| 413 |
if parsed:
|
| 414 |
return normalize_output(parsed, lang, category_key, variant)
|
| 415 |
|
| 416 |
+
# Model replied but not valid JSON
|
| 417 |
few = FEWSHOTS[lang][category_key]
|
| 418 |
+
q_pool = few["questions"][:]
|
| 419 |
+
m_pool = few["micro_actions"][:]
|
| 420 |
+
random.shuffle(q_pool)
|
| 421 |
+
random.shuffle(m_pool)
|
| 422 |
return {
|
| 423 |
"category": category_key,
|
| 424 |
"language": lang,
|
| 425 |
+
"questions": (q_pool + [""] * 4)[:4],
|
| 426 |
+
"micro_actions": (m_pool + [""] * 2)[:2],
|
| 427 |
"tone": "fallback",
|
| 428 |
+
"safety_notes": (
|
| 429 |
+
"Model replied but JSON parsing failed. "
|
| 430 |
+
f"raw_text starts with: {repr(raw_text[:160])}"
|
| 431 |
+
),
|
| 432 |
}
|
| 433 |
+
|
| 434 |
except Exception as e:
|
| 435 |
+
# Any HF / network / auth error ends up here
|
| 436 |
few = FEWSHOTS[lang][category_key]
|
| 437 |
+
q_pool = few["questions"][:]
|
| 438 |
+
m_pool = few["micro_actions"][:]
|
| 439 |
+
random.shuffle(q_pool)
|
| 440 |
+
random.shuffle(m_pool)
|
| 441 |
return {
|
| 442 |
"category": category_key,
|
| 443 |
"language": lang,
|
| 444 |
+
"questions": (q_pool + [""] * 4)[:4],
|
| 445 |
+
"micro_actions": (m_pool + [""] * 2)[:2],
|
| 446 |
"tone": "error",
|
| 447 |
"safety_notes": f"Model call error: {type(e).__name__}: {e}",
|
| 448 |
}
|
| 449 |
|
|
|
|
| 450 |
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
|
| 451 |
# MAIN LOGIC: REPO + SESSION "SEEN" QUESTIONS
|
| 452 |
|