Spaces:
Running
Running
AttributeError: Dropdown has no attribute update (now uses gr.update)
Browse files
app.py
CHANGED
|
@@ -141,21 +141,17 @@ def parse_freeform_query(text: str):
|
|
| 141 |
def semantic_match(query, top_k=15):
|
| 142 |
if not query:
|
| 143 |
return {"category": None, "items": []}
|
| 144 |
-
|
| 145 |
query = query.strip().lower()
|
| 146 |
q_emb = embedder.encode(query, convert_to_tensor=True)
|
| 147 |
sims_items = {n: float(util.cos_sim(q_emb, emb)) for n, emb in ITEM_EMBEDS.items()}
|
| 148 |
ranked_items = sorted(sims_items.items(), key=lambda x: x[1], reverse=True)
|
| 149 |
item_hits = [n for n, score in ranked_items[:top_k] if score > 0.35]
|
| 150 |
-
|
| 151 |
sims_cats = {c: float(util.cos_sim(q_emb, emb)) for c, emb in CATEGORY_EMBEDS.items()}
|
| 152 |
ranked_cats = sorted(sims_cats.items(), key=lambda x: x[1], reverse=True)
|
| 153 |
top_cat, cat_score = (ranked_cats[0] if ranked_cats else (None, 0.0))
|
| 154 |
-
|
| 155 |
related_items = []
|
| 156 |
if top_cat and cat_score > 0.35:
|
| 157 |
related_items = [n for n, t in ITEM_TO_TYPE.items() if t == top_cat]
|
| 158 |
-
|
| 159 |
combined = list(set(item_hits + related_items))
|
| 160 |
return {"category": top_cat if related_items else None, "items": combined}
|
| 161 |
|
|
@@ -179,7 +175,6 @@ def fetch_yata(force_refresh=False):
|
|
| 179 |
return {"stocks": {}}, "Fetch failed"
|
| 180 |
|
| 181 |
def get_live_categories(data):
|
| 182 |
-
"""Return sorted list of categories present in YATA data."""
|
| 183 |
live_cats = set()
|
| 184 |
for _, cdata in data.get("stocks", {}).items():
|
| 185 |
for item in cdata.get("stocks", []):
|
|
@@ -193,9 +188,7 @@ def get_live_categories(data):
|
|
| 193 |
def query_inventory(query_text="", category="", country_name="", capacity=10, refresh=False):
|
| 194 |
print(f"π Query received: '{query_text}', category='{category}', country='{country_name}', cap={capacity}")
|
| 195 |
data, last_update = fetch_yata(force_refresh=refresh)
|
| 196 |
-
stocks = data.get("stocks", {})
|
| 197 |
rows = []
|
| 198 |
-
|
| 199 |
parsed_item, parsed_country = parse_freeform_query(query_text)
|
| 200 |
if not country_name and parsed_country:
|
| 201 |
country_name = parsed_country
|
|
@@ -203,29 +196,23 @@ def query_inventory(query_text="", category="", country_name="", capacity=10, re
|
|
| 203 |
semantic_result = semantic_match(item_term) if item_term else {"category": None, "items": []}
|
| 204 |
semantic_items = semantic_result["items"]
|
| 205 |
semantic_category = semantic_result["category"]
|
| 206 |
-
|
| 207 |
user_code = normalize_country_query(country_name)
|
| 208 |
-
|
| 209 |
-
for code_raw, cdata in stocks.items():
|
| 210 |
code = code_raw.upper()
|
| 211 |
cname = COUNTRY_NAMES.get(code, code)
|
| 212 |
-
|
| 213 |
if country_name:
|
| 214 |
if user_code:
|
| 215 |
if code != user_code:
|
| 216 |
continue
|
| 217 |
elif country_name.lower() not in cname.lower():
|
| 218 |
continue
|
| 219 |
-
|
| 220 |
update_ts = cdata.get("update")
|
| 221 |
update_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_ts)) if update_ts else "Unknown"
|
| 222 |
-
|
| 223 |
for item in cdata.get("stocks", []):
|
| 224 |
iname = item.get("name", "")
|
| 225 |
itype = ITEM_TO_TYPE.get(iname, "").lower()
|
| 226 |
qty = item.get("quantity", 0)
|
| 227 |
cost = item.get("cost", 0)
|
| 228 |
-
|
| 229 |
if item_term:
|
| 230 |
item_ok = (
|
| 231 |
item_term.lower() in iname.lower()
|
|
@@ -236,25 +223,21 @@ def query_inventory(query_text="", category="", country_name="", capacity=10, re
|
|
| 236 |
item_ok = category.lower() == itype
|
| 237 |
else:
|
| 238 |
item_ok = True
|
| 239 |
-
|
| 240 |
if item_ok:
|
| 241 |
rows.append({
|
| 242 |
"Country": cname,
|
| 243 |
"Item": iname,
|
| 244 |
-
"Category": itype.title()
|
| 245 |
"Quantity": qty,
|
| 246 |
"Cost": cost,
|
| 247 |
"Max Capacity Cost": cost * capacity,
|
| 248 |
-
"Updated": update_str
|
| 249 |
})
|
| 250 |
-
|
| 251 |
if not rows:
|
| 252 |
return pd.DataFrame([{"Result": "No inventory found for that query."}]), f"Last update: {last_update}"
|
| 253 |
-
|
| 254 |
df = pd.DataFrame(rows).sort_values(by=["Country", "Item"])
|
| 255 |
for col in ["Quantity", "Cost", "Max Capacity Cost"]:
|
| 256 |
-
|
| 257 |
-
df[col] = df[col].apply(lambda x: f"{x:,.0f}" if isinstance(x, (int, float)) and x != "" else x)
|
| 258 |
return df, f"Last update: {last_update}"
|
| 259 |
|
| 260 |
# ---------------- Wrappers ----------------
|
|
@@ -262,7 +245,7 @@ def run_query(query_text, category, country, capacity, refresh):
|
|
| 262 |
data, _ = fetch_yata(force_refresh=refresh)
|
| 263 |
df, ts = query_inventory(query_text, category, country, capacity, refresh)
|
| 264 |
live_categories = get_live_categories(data)
|
| 265 |
-
return df, ts, gr.
|
| 266 |
|
| 267 |
def run_multi(queries, capacity, refresh):
|
| 268 |
data, _ = fetch_yata(force_refresh=refresh)
|
|
@@ -273,13 +256,12 @@ def run_multi(queries, capacity, refresh):
|
|
| 273 |
if "Result" not in df.columns:
|
| 274 |
dfs.append(df)
|
| 275 |
if not dfs:
|
| 276 |
-
return pd.DataFrame([{"Result": "No results for that set."}]), "No results.", gr.
|
| 277 |
merged = pd.concat(dfs, ignore_index=True).sort_values(by=["Country", "Item"])
|
| 278 |
for col in ["Quantity", "Cost", "Max Capacity Cost"]:
|
| 279 |
-
|
| 280 |
-
merged[col] = merged[col].apply(lambda x: f"{x:,.0f}" if isinstance(x, (int, float)) and x != "" else x)
|
| 281 |
live_categories = get_live_categories(data)
|
| 282 |
-
return merged, f"Last update: {time.strftime('%Y-%m-%d %H:%M:%S')}", gr.
|
| 283 |
|
| 284 |
# ---------------- Gradio UI ----------------
|
| 285 |
with gr.Blocks(title="π§³ Torn Inventory Viewer") as iface:
|
|
@@ -320,33 +302,28 @@ with gr.Blocks(title="π§³ Torn Inventory Viewer") as iface:
|
|
| 320 |
inputs=[query_box, category_drop, country_box, capacity_slider, refresh_check],
|
| 321 |
outputs=[result_df, meta_box, category_drop])
|
| 322 |
|
| 323 |
-
# Convenience buttons
|
| 324 |
btn_short.click(lambda c, r: run_multi(
|
| 325 |
-
["flowers in mexico","flowers in cayman islands","flowers in canada",
|
| 326 |
-
"plushies in mexico","plushies in cayman islands","plushies in canada"],
|
| 327 |
-
c, r),
|
| 328 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 329 |
|
| 330 |
btn_med.click(lambda c, r: run_multi(
|
| 331 |
-
["flowers in hawaii","flowers in united kingdom","flowers in argentina",
|
| 332 |
-
"flowers in switzerland","flowers in japan",
|
| 333 |
-
"plushies in hawaii","plushies in united kingdom","plushies in argentina",
|
| 334 |
-
"plushies in switzerland","plushies in japan"],
|
| 335 |
-
c, r),
|
| 336 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 337 |
|
| 338 |
btn_long.click(lambda c, r: run_multi(
|
| 339 |
-
["flowers in uae","flowers in china","flowers in south africa",
|
| 340 |
-
"plushies in uae","plushies in china","plushies in south africa"],
|
| 341 |
-
c, r),
|
| 342 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 343 |
|
| 344 |
btn_xanax.click(lambda c, r: run_multi(["xanax in south africa"], c, r),
|
| 345 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 346 |
|
| 347 |
btn_temps.click(lambda c, r: run_multi(
|
| 348 |
-
["tear gas in argentina","smoke grenade in south africa","flash grenade in switzerland"],
|
| 349 |
-
c, r),
|
| 350 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 351 |
|
| 352 |
# --- JS for capacity persistence ---
|
|
|
|
| 141 |
def semantic_match(query, top_k=15):
|
| 142 |
if not query:
|
| 143 |
return {"category": None, "items": []}
|
|
|
|
| 144 |
query = query.strip().lower()
|
| 145 |
q_emb = embedder.encode(query, convert_to_tensor=True)
|
| 146 |
sims_items = {n: float(util.cos_sim(q_emb, emb)) for n, emb in ITEM_EMBEDS.items()}
|
| 147 |
ranked_items = sorted(sims_items.items(), key=lambda x: x[1], reverse=True)
|
| 148 |
item_hits = [n for n, score in ranked_items[:top_k] if score > 0.35]
|
|
|
|
| 149 |
sims_cats = {c: float(util.cos_sim(q_emb, emb)) for c, emb in CATEGORY_EMBEDS.items()}
|
| 150 |
ranked_cats = sorted(sims_cats.items(), key=lambda x: x[1], reverse=True)
|
| 151 |
top_cat, cat_score = (ranked_cats[0] if ranked_cats else (None, 0.0))
|
|
|
|
| 152 |
related_items = []
|
| 153 |
if top_cat and cat_score > 0.35:
|
| 154 |
related_items = [n for n, t in ITEM_TO_TYPE.items() if t == top_cat]
|
|
|
|
| 155 |
combined = list(set(item_hits + related_items))
|
| 156 |
return {"category": top_cat if related_items else None, "items": combined}
|
| 157 |
|
|
|
|
| 175 |
return {"stocks": {}}, "Fetch failed"
|
| 176 |
|
| 177 |
def get_live_categories(data):
|
|
|
|
| 178 |
live_cats = set()
|
| 179 |
for _, cdata in data.get("stocks", {}).items():
|
| 180 |
for item in cdata.get("stocks", []):
|
|
|
|
| 188 |
def query_inventory(query_text="", category="", country_name="", capacity=10, refresh=False):
|
| 189 |
print(f"π Query received: '{query_text}', category='{category}', country='{country_name}', cap={capacity}")
|
| 190 |
data, last_update = fetch_yata(force_refresh=refresh)
|
|
|
|
| 191 |
rows = []
|
|
|
|
| 192 |
parsed_item, parsed_country = parse_freeform_query(query_text)
|
| 193 |
if not country_name and parsed_country:
|
| 194 |
country_name = parsed_country
|
|
|
|
| 196 |
semantic_result = semantic_match(item_term) if item_term else {"category": None, "items": []}
|
| 197 |
semantic_items = semantic_result["items"]
|
| 198 |
semantic_category = semantic_result["category"]
|
|
|
|
| 199 |
user_code = normalize_country_query(country_name)
|
| 200 |
+
for code_raw, cdata in data.get("stocks", {}).items():
|
|
|
|
| 201 |
code = code_raw.upper()
|
| 202 |
cname = COUNTRY_NAMES.get(code, code)
|
|
|
|
| 203 |
if country_name:
|
| 204 |
if user_code:
|
| 205 |
if code != user_code:
|
| 206 |
continue
|
| 207 |
elif country_name.lower() not in cname.lower():
|
| 208 |
continue
|
|
|
|
| 209 |
update_ts = cdata.get("update")
|
| 210 |
update_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(update_ts)) if update_ts else "Unknown"
|
|
|
|
| 211 |
for item in cdata.get("stocks", []):
|
| 212 |
iname = item.get("name", "")
|
| 213 |
itype = ITEM_TO_TYPE.get(iname, "").lower()
|
| 214 |
qty = item.get("quantity", 0)
|
| 215 |
cost = item.get("cost", 0)
|
|
|
|
| 216 |
if item_term:
|
| 217 |
item_ok = (
|
| 218 |
item_term.lower() in iname.lower()
|
|
|
|
| 223 |
item_ok = category.lower() == itype
|
| 224 |
else:
|
| 225 |
item_ok = True
|
|
|
|
| 226 |
if item_ok:
|
| 227 |
rows.append({
|
| 228 |
"Country": cname,
|
| 229 |
"Item": iname,
|
| 230 |
+
"Category": itype.title(),
|
| 231 |
"Quantity": qty,
|
| 232 |
"Cost": cost,
|
| 233 |
"Max Capacity Cost": cost * capacity,
|
| 234 |
+
"Updated": update_str
|
| 235 |
})
|
|
|
|
| 236 |
if not rows:
|
| 237 |
return pd.DataFrame([{"Result": "No inventory found for that query."}]), f"Last update: {last_update}"
|
|
|
|
| 238 |
df = pd.DataFrame(rows).sort_values(by=["Country", "Item"])
|
| 239 |
for col in ["Quantity", "Cost", "Max Capacity Cost"]:
|
| 240 |
+
df[col] = df[col].apply(lambda x: f"{x:,.0f}" if isinstance(x, (int, float)) else x)
|
|
|
|
| 241 |
return df, f"Last update: {last_update}"
|
| 242 |
|
| 243 |
# ---------------- Wrappers ----------------
|
|
|
|
| 245 |
data, _ = fetch_yata(force_refresh=refresh)
|
| 246 |
df, ts = query_inventory(query_text, category, country, capacity, refresh)
|
| 247 |
live_categories = get_live_categories(data)
|
| 248 |
+
return df, ts, gr.update(choices=[""] + live_categories)
|
| 249 |
|
| 250 |
def run_multi(queries, capacity, refresh):
|
| 251 |
data, _ = fetch_yata(force_refresh=refresh)
|
|
|
|
| 256 |
if "Result" not in df.columns:
|
| 257 |
dfs.append(df)
|
| 258 |
if not dfs:
|
| 259 |
+
return pd.DataFrame([{"Result": "No results for that set."}]), "No results.", gr.update()
|
| 260 |
merged = pd.concat(dfs, ignore_index=True).sort_values(by=["Country", "Item"])
|
| 261 |
for col in ["Quantity", "Cost", "Max Capacity Cost"]:
|
| 262 |
+
merged[col] = merged[col].apply(lambda x: f"{x:,.0f}" if isinstance(x, (int, float)) else x)
|
|
|
|
| 263 |
live_categories = get_live_categories(data)
|
| 264 |
+
return merged, f"Last update: {time.strftime('%Y-%m-%d %H:%M:%S')}", gr.update(choices=[""] + live_categories)
|
| 265 |
|
| 266 |
# ---------------- Gradio UI ----------------
|
| 267 |
with gr.Blocks(title="π§³ Torn Inventory Viewer") as iface:
|
|
|
|
| 302 |
inputs=[query_box, category_drop, country_box, capacity_slider, refresh_check],
|
| 303 |
outputs=[result_df, meta_box, category_drop])
|
| 304 |
|
|
|
|
| 305 |
btn_short.click(lambda c, r: run_multi(
|
| 306 |
+
["flowers in mexico", "flowers in cayman islands", "flowers in canada",
|
| 307 |
+
"plushies in mexico", "plushies in cayman islands", "plushies in canada"], c, r),
|
|
|
|
| 308 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 309 |
|
| 310 |
btn_med.click(lambda c, r: run_multi(
|
| 311 |
+
["flowers in hawaii", "flowers in united kingdom", "flowers in argentina",
|
| 312 |
+
"flowers in switzerland", "flowers in japan",
|
| 313 |
+
"plushies in hawaii", "plushies in united kingdom", "plushies in argentina",
|
| 314 |
+
"plushies in switzerland", "plushies in japan"], c, r),
|
|
|
|
| 315 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 316 |
|
| 317 |
btn_long.click(lambda c, r: run_multi(
|
| 318 |
+
["flowers in uae", "flowers in china", "flowers in south africa",
|
| 319 |
+
"plushies in uae", "plushies in china", "plushies in south africa"], c, r),
|
|
|
|
| 320 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 321 |
|
| 322 |
btn_xanax.click(lambda c, r: run_multi(["xanax in south africa"], c, r),
|
| 323 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 324 |
|
| 325 |
btn_temps.click(lambda c, r: run_multi(
|
| 326 |
+
["tear gas in argentina", "smoke grenade in south africa", "flash grenade in switzerland"], c, r),
|
|
|
|
| 327 |
inputs=[capacity_slider, refresh_check], outputs=[result_df, meta_box, category_drop])
|
| 328 |
|
| 329 |
# --- JS for capacity persistence ---
|