Spaces:
Sleeping
Sleeping
Update app.py
Browse files
app.py
CHANGED
|
@@ -279,10 +279,11 @@ def generate_rationale(risks, amount, sectors, markets, style, recs):
|
|
| 279 |
try:
|
| 280 |
sents = _generate_sentences(prompts)
|
| 281 |
except Exception as e:
|
| 282 |
-
# A GPU failure must not take the whole recommendation down
|
| 283 |
-
# above is still valid
|
|
|
|
| 284 |
return (f"_Recommendations above are complete. The written explanation "
|
| 285 |
-
f"could not be generated
|
| 286 |
|
| 287 |
amt = parse_amount(amount)
|
| 288 |
rl = "/".join(_as_list(risks)).lower() or "flexible"
|
|
@@ -309,13 +310,14 @@ DISPLAY_COLS = ["ticker", "sector", "market_region", "cluster_name", "risk_level
|
|
| 309 |
|
| 310 |
def run_custom(risks, amount, sectors, markets, style, caps):
|
| 311 |
"""Plain function, not a generator: @spaces.GPU does not compose well with
|
| 312 |
-
Gradio generator callbacks
|
| 313 |
-
|
|
|
|
| 314 |
if recs.empty:
|
| 315 |
-
return pd.DataFrame(), note
|
| 316 |
cols = [c for c in DISPLAY_COLS if c in recs.columns]
|
| 317 |
text = generate_rationale(risks, amount, sectors, markets, style, recs)
|
| 318 |
-
return recs[cols], (note + "\n\n" + text).strip()
|
| 319 |
|
| 320 |
def run_quickstart(name):
|
| 321 |
"""Served from the pre-generated cache — instant, uses no GPU quota."""
|
|
@@ -325,12 +327,7 @@ def run_quickstart(name):
|
|
| 325 |
"market_cap_millions_usd"]:
|
| 326 |
if c in tbl.columns:
|
| 327 |
tbl[c] = pd.to_numeric(tbl[c], errors="coerce")
|
| 328 |
-
|
| 329 |
-
return (tbl[[c for c in DISPLAY_COLS if c in tbl.columns]],
|
| 330 |
-
entry["rationale"],
|
| 331 |
-
f"*Preset profile:* {a['risk_level']} risk · ${a['investment_amount']:,} · "
|
| 332 |
-
f"{a['sector']} · {a['target_market']} · {a['stock_type']} · "
|
| 333 |
-
f"{a['market_cap_pref']} cap")
|
| 334 |
|
| 335 |
# ---------------------------------------------------------------------------
|
| 336 |
# UI
|
|
@@ -363,8 +360,13 @@ with gr.Blocks(title="StockMatch AI", theme=gr.themes.Soft()) as demo:
|
|
| 363 |
q3 = gr.Dropdown(SECTORS, value=["Utilities"], multiselect=True,
|
| 364 |
label="3. Sector (select one or more, or none for all)")
|
| 365 |
with gr.Column():
|
|
|
|
|
|
|
|
|
|
|
|
|
| 366 |
q4 = gr.Dropdown(MARKETS, value=["USA"], multiselect=True,
|
| 367 |
-
label="4. Target market
|
|
|
|
| 368 |
q5 = gr.Radio(["Dividend", "Growth"], value="Dividend",
|
| 369 |
label="5. Stock type preference")
|
| 370 |
q6 = gr.CheckboxGroup(["Small", "Medium", "Large"], value=["Large"],
|
|
@@ -372,13 +374,12 @@ with gr.Blocks(title="StockMatch AI", theme=gr.themes.Soft()) as demo:
|
|
| 372 |
go = gr.Button("🔍 Find my stocks", variant="primary", size="lg")
|
| 373 |
|
| 374 |
gr.Markdown("### Results")
|
| 375 |
-
info = gr.Markdown()
|
| 376 |
table = gr.Dataframe(label="Matched stocks", interactive=False, wrap=True)
|
| 377 |
text = gr.Markdown()
|
| 378 |
|
| 379 |
-
go.click(run_custom, [q1, q2, q3, q4, q5, q6], [table, text
|
| 380 |
-
b1.click(lambda: run_quickstart("Cautious Retiree"), None, [table, text
|
| 381 |
-
b2.click(lambda: run_quickstart("Balanced Professional"), None, [table, text
|
| 382 |
-
b3.click(lambda: run_quickstart("Young Growth Seeker"), None, [table, text
|
| 383 |
|
| 384 |
demo.launch()
|
|
|
|
| 279 |
try:
|
| 280 |
sents = _generate_sentences(prompts)
|
| 281 |
except Exception as e:
|
| 282 |
+
# A GPU failure must not take the whole recommendation down: the table
|
| 283 |
+
# above is still valid. The exception message is surfaced so the cause
|
| 284 |
+
# is diagnosable rather than hidden behind a generic "Error".
|
| 285 |
return (f"_Recommendations above are complete. The written explanation "
|
| 286 |
+
f"could not be generated._\n\n`{type(e).__name__}: {e}`")
|
| 287 |
|
| 288 |
amt = parse_amount(amount)
|
| 289 |
rl = "/".join(_as_list(risks)).lower() or "flexible"
|
|
|
|
| 310 |
|
| 311 |
def run_custom(risks, amount, sectors, markets, style, caps):
|
| 312 |
"""Plain function, not a generator: @spaces.GPU does not compose well with
|
| 313 |
+
Gradio generator callbacks. The semantic query is computed but not shown —
|
| 314 |
+
it is an internal representation, not something a user needs to read."""
|
| 315 |
+
recs, note, _query = recommend(risks, amount, sectors, markets, style, caps)
|
| 316 |
if recs.empty:
|
| 317 |
+
return pd.DataFrame(), note
|
| 318 |
cols = [c for c in DISPLAY_COLS if c in recs.columns]
|
| 319 |
text = generate_rationale(risks, amount, sectors, markets, style, recs)
|
| 320 |
+
return recs[cols], (note + "\n\n" + text).strip()
|
| 321 |
|
| 322 |
def run_quickstart(name):
|
| 323 |
"""Served from the pre-generated cache — instant, uses no GPU quota."""
|
|
|
|
| 327 |
"market_cap_millions_usd"]:
|
| 328 |
if c in tbl.columns:
|
| 329 |
tbl[c] = pd.to_numeric(tbl[c], errors="coerce")
|
| 330 |
+
return tbl[[c for c in DISPLAY_COLS if c in tbl.columns]], entry["rationale"]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 331 |
|
| 332 |
# ---------------------------------------------------------------------------
|
| 333 |
# UI
|
|
|
|
| 360 |
q3 = gr.Dropdown(SECTORS, value=["Utilities"], multiselect=True,
|
| 361 |
label="3. Sector (select one or more, or none for all)")
|
| 362 |
with gr.Column():
|
| 363 |
+
# The dataset covers four regions built from seven exchanges, so
|
| 364 |
+
# country choices map upward: Japan and China -> Asia, Switzerland
|
| 365 |
+
# and the UK -> Europe. The label states this rather than silently
|
| 366 |
+
# substituting a different market.
|
| 367 |
q4 = gr.Dropdown(MARKETS, value=["USA"], multiselect=True,
|
| 368 |
+
label="4. Target market — grouped into US / Europe / "
|
| 369 |
+
"Israel / Asia (select one or more, or none for all)")
|
| 370 |
q5 = gr.Radio(["Dividend", "Growth"], value="Dividend",
|
| 371 |
label="5. Stock type preference")
|
| 372 |
q6 = gr.CheckboxGroup(["Small", "Medium", "Large"], value=["Large"],
|
|
|
|
| 374 |
go = gr.Button("🔍 Find my stocks", variant="primary", size="lg")
|
| 375 |
|
| 376 |
gr.Markdown("### Results")
|
|
|
|
| 377 |
table = gr.Dataframe(label="Matched stocks", interactive=False, wrap=True)
|
| 378 |
text = gr.Markdown()
|
| 379 |
|
| 380 |
+
go.click(run_custom, [q1, q2, q3, q4, q5, q6], [table, text])
|
| 381 |
+
b1.click(lambda: run_quickstart("Cautious Retiree"), None, [table, text])
|
| 382 |
+
b2.click(lambda: run_quickstart("Balanced Professional"), None, [table, text])
|
| 383 |
+
b3.click(lambda: run_quickstart("Young Growth Seeker"), None, [table, text])
|
| 384 |
|
| 385 |
demo.launch()
|