Kogann commited on
Commit
b2348d0
Β·
verified Β·
1 Parent(s): 1f7cc4d

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -15
app.py CHANGED
@@ -253,15 +253,38 @@ def _stock_prompt(risks, style, r):
253
 
254
  @spaces.GPU(duration=30)
255
  def _generate_sentences(prompts):
256
- """The only function needing a real GPU, so the only one decorated."""
257
- enc = gen_tok(prompts, return_tensors="pt", padding=True).to("cuda")
258
- with torch.no_grad():
259
- out = gen_model.generate(**enc, max_new_tokens=110, do_sample=True,
260
- temperature=0.4, top_p=0.9,
261
- repetition_penalty=1.1,
262
- pad_token_id=gen_tok.pad_token_id)
263
- return gen_tok.batch_decode(out[:, enc["input_ids"].shape[1]:],
264
- skip_special_tokens=True)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
265
 
266
  def generate_rationale(risks, amount, sectors, markets, style, recs):
267
  """One sentence per stock, generated in a single batched pass. All factual
@@ -272,11 +295,12 @@ def generate_rationale(risks, amount, sectors, markets, style, recs):
272
  {"role": "user", "content": _stock_prompt(risks, style, r)}],
273
  tokenize=False, add_generation_prompt=True) for _, r in recs.iterrows()]
274
 
275
- try:
276
- sents = _generate_sentences(prompts)
277
- except Exception as e:
278
- return (f"_Recommendations above are complete. The written explanation "
279
- f"could not be generated._\n\n`{type(e).__name__}: {e}`")
 
280
 
281
  amt = parse_amount(amount)
282
  rl = "/".join(_as_list(risks)).lower() or "flexible"
@@ -287,7 +311,7 @@ def generate_rationale(risks, amount, sectors, markets, style, recs):
287
  lines = [f"Based on your {rl}-risk profile and {budget}, here are "
288
  f"{len(recs)} stocks in {sec} from {mkt} matching your preferences.", ""]
289
  for i, ((_, r), s) in enumerate(zip(recs.iterrows(), sents), 1):
290
- sh = int(amt // r["price_usd"]) if (amt > 0 and r["price_usd"]) else None
291
  aff = f" ({sh} shares affordable)" if sh else ""
292
  lines.append(f"{i}. **{r['ticker']}** β€” beta {r['beta']:.2f}, "
293
  f"{r[DIV_COL]:.2f}% yield, {r['cagr_10yr_pct']:.1f}% growth, "
@@ -389,6 +413,10 @@ with gr.Blocks(title="StockMatch AI", theme=gr.themes.Soft()) as demo:
389
  label="6. Company size")
390
  go = gr.Button("πŸ” Find my stocks", variant="primary", size="lg")
391
 
 
 
 
 
392
  gr.Markdown("### Results")
393
  table = gr.Dataframe(label="Your matches", interactive=False, wrap=True)
394
  text = gr.Markdown()
@@ -397,5 +425,6 @@ with gr.Blocks(title="StockMatch AI", theme=gr.themes.Soft()) as demo:
397
  b1.click(lambda: run_quickstart("Cautious Retiree"), None, [table, text])
398
  b2.click(lambda: run_quickstart("Balanced Professional"), None, [table, text])
399
  b3.click(lambda: run_quickstart("Young Growth Seeker"), None, [table, text])
 
400
 
401
  demo.launch()
 
253
 
254
  @spaces.GPU(duration=30)
255
  def _generate_sentences(prompts):
256
+ """The only function needing a real GPU, so the only one decorated.
257
+
258
+ Errors are caught HERE and returned as data rather than raised. ZeroGPU
259
+ executes this in a separate worker process, and an exception crossing that
260
+ boundary arrives as a bare RuntimeError with its message stripped β€” which
261
+ makes diagnosis impossible. Returning the traceback preserves it.
262
+ """
263
+ import traceback
264
+ try:
265
+ enc = gen_tok(prompts, return_tensors="pt", padding=True).to("cuda")
266
+ with torch.no_grad():
267
+ out = gen_model.generate(**enc, max_new_tokens=110, do_sample=True,
268
+ temperature=0.4, top_p=0.9,
269
+ repetition_penalty=1.1,
270
+ pad_token_id=gen_tok.pad_token_id)
271
+ sents = gen_tok.batch_decode(out[:, enc["input_ids"].shape[1]:],
272
+ skip_special_tokens=True)
273
+ return {"ok": True, "sentences": sents}
274
+ except Exception:
275
+ return {"ok": False, "traceback": traceback.format_exc()}
276
+
277
+
278
+ @spaces.GPU(duration=10)
279
+ def _gpu_selftest():
280
+ """Diagnostic: does ZeroGPU work at all, independent of our model?
281
+ Isolates an infrastructure problem from a model-loading problem."""
282
+ import traceback
283
+ try:
284
+ x = torch.randn(4, 4).to("cuda")
285
+ return f"βœ… GPU OK β€” {torch.cuda.get_device_name(0)}, tensor on {x.device}"
286
+ except Exception:
287
+ return "❌ GPU FAILED\n```\n" + traceback.format_exc()[-1200:] + "\n```"
288
 
289
  def generate_rationale(risks, amount, sectors, markets, style, recs):
290
  """One sentence per stock, generated in a single batched pass. All factual
 
295
  {"role": "user", "content": _stock_prompt(risks, style, r)}],
296
  tokenize=False, add_generation_prompt=True) for _, r in recs.iterrows()]
297
 
298
+ result = _generate_sentences(prompts)
299
+ if not result.get("ok"):
300
+ return ("_Recommendations above are complete. The written explanation "
301
+ "could not be generated._\n\n```\n"
302
+ + result.get("traceback", "no traceback")[-1500:] + "\n```")
303
+ sents = result["sentences"]
304
 
305
  amt = parse_amount(amount)
306
  rl = "/".join(_as_list(risks)).lower() or "flexible"
 
311
  lines = [f"Based on your {rl}-risk profile and {budget}, here are "
312
  f"{len(recs)} stocks in {sec} from {mkt} matching your preferences.", ""]
313
  for i, ((_, r), s) in enumerate(zip(recs.iterrows(), sents), 1):
314
+ sh = int(amt // r["price_usd"]) if (amt > 0 and r["price_usd"]) else None
315
  aff = f" ({sh} shares affordable)" if sh else ""
316
  lines.append(f"{i}. **{r['ticker']}** β€” beta {r['beta']:.2f}, "
317
  f"{r[DIV_COL]:.2f}% yield, {r['cagr_10yr_pct']:.1f}% growth, "
 
413
  label="6. Company size")
414
  go = gr.Button("πŸ” Find my stocks", variant="primary", size="lg")
415
 
416
+ # Diagnostic only β€” remove before submitting.
417
+ gpu_btn = gr.Button("πŸ”§ Test GPU", variant="secondary", size="sm")
418
+ gpu_out = gr.Markdown()
419
+
420
  gr.Markdown("### Results")
421
  table = gr.Dataframe(label="Your matches", interactive=False, wrap=True)
422
  text = gr.Markdown()
 
425
  b1.click(lambda: run_quickstart("Cautious Retiree"), None, [table, text])
426
  b2.click(lambda: run_quickstart("Balanced Professional"), None, [table, text])
427
  b3.click(lambda: run_quickstart("Young Growth Seeker"), None, [table, text])
428
+ gpu_btn.click(_gpu_selftest, None, gpu_out)
429
 
430
  demo.launch()