kappai commited on
Commit
f03f0ce
Β·
verified Β·
1 Parent(s): da49fc9

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -15
app.py CHANGED
@@ -10,10 +10,13 @@ from huggingface_hub import InferenceClient
10
  # ────────────────────────────────────────────────────────────────────────────────
11
  # CONFIG
12
 
13
- # You can hard-code the model here, or override with MODEL_ID as a Space variable.
14
- # Use a free, public chat model that doesn't need a novita api_key
15
- MODEL_ID = os.environ.get("MODEL_ID", "TinyLlama/TinyLlama-1.1B-Chat-v1.0")
16
- HF_TOKEN = os.environ.get("HF_TOKEN") # can stay empty
 
 
 
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 not set and no default is provided.")
340
 
341
- client = InferenceClient(model=MODEL_ID, token=HF_TOKEN or None)
 
 
 
 
 
 
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("Empty response from model.")
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
- # If model replied but JSON is bad, show that in safety_notes
399
  few = FEWSHOTS[lang][category_key]
 
 
 
 
400
  return {
401
  "category": category_key,
402
  "language": lang,
403
- "questions": random.sample(few["questions"], 4),
404
- "micro_actions": random.sample(few["micro_actions"], 2),
405
  "tone": "fallback",
406
- "safety_notes": f"Model replied but JSON parsing failed. raw_text starts with: {repr(raw_text[:160])}",
 
 
 
407
  }
 
408
  except Exception as e:
409
- # Surface the error clearly
410
  few = FEWSHOTS[lang][category_key]
 
 
 
 
411
  return {
412
  "category": category_key,
413
  "language": lang,
414
- "questions": random.sample(few["questions"], 4),
415
- "micro_actions": random.sample(few["micro_actions"], 2),
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