pixel3user commited on
Commit
2cc645f
·
1 Parent(s): 4b3e157

added json cards

Browse files
Files changed (1) hide show
  1. app.py +71 -0
app.py CHANGED
@@ -137,6 +137,73 @@ def _has_valid_suggestions(raw_suggestions: str) -> bool:
137
 
138
  return True
139
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
140
  # ---- Inference on GPU (ZeroGPU pattern) ----
141
  @spaces.GPU(duration=120)
142
  def generate_answer(image, question, temperature=0.7, top_p=0.95, max_tokens=256):
@@ -257,6 +324,10 @@ def pet_answer_with_recs(image, question, temperature=0.7, top_p=0.95, max_token
257
  sections = [base.strip()]
258
  if include_products:
259
  sections.append(f"Suggested products:\n{suggestions}")
 
 
 
 
260
  sections.append(safety)
261
 
262
  return "\n\n".join([s for s in sections if s])
 
137
 
138
  return True
139
 
140
+ # ---- JSON block helpers ----
141
+ def _extract_products_json_block(text: str) -> str | None:
142
+ start_tag = "<DERMACARE_PRODUCTS_JSON>"
143
+ end_tag = "</DERMACARE_PRODUCTS_JSON>"
144
+ start = text.find(start_tag)
145
+ end = text.find(end_tag)
146
+ if start == -1 or end == -1 or end <= start:
147
+ return None
148
+ json_str = text[start + len(start_tag):end]
149
+ try:
150
+ payload = json.loads(json_str)
151
+ products = payload.get("products", [])
152
+ if isinstance(products, list) and len(products) > 0:
153
+ return f"{start_tag}{json.dumps(payload, ensure_ascii=False)}{end_tag}"
154
+ except Exception:
155
+ return None
156
+ return None
157
+
158
+
159
+ def _filter_candidates_by_budget(cands: list[dict], budget_twd: int | None) -> list[dict]:
160
+ if not budget_twd:
161
+ return cands
162
+ filtered: list[dict] = []
163
+ for c in cands:
164
+ currency = c.get("price_currency")
165
+ value = c.get("price_value")
166
+ if currency == "TWD" and isinstance(value, (int, float)) and value is not None:
167
+ if value <= budget_twd:
168
+ filtered.append(c)
169
+ else:
170
+ filtered.append(c)
171
+ return filtered
172
+
173
+
174
+ def _build_products_json_block_from_candidates(cands: list[dict], max_items: int = 3) -> str | None:
175
+ if not cands:
176
+ return None
177
+ ranked = sorted(cands, key=lambda x: x.get("_score", 0.0), reverse=True)
178
+ picked = ranked[:max_items]
179
+ products = []
180
+ for c in picked:
181
+ products.append({
182
+ "id": c.get("id"),
183
+ "brand": c.get("brand_en") or c.get("brand_zh"),
184
+ "name": c.get("product_name_en") or c.get("product_name_zh"),
185
+ "category": c.get("category_en") or c.get("category_zh"),
186
+ "price_value": c.get("price_value"),
187
+ "price_currency": c.get("price_currency"),
188
+ "why": None,
189
+ "how": None,
190
+ "url": c.get("source_url"),
191
+ "image_url": c.get("image_url"),
192
+ })
193
+ valid_count = sum(1 for p in products if p.get("name"))
194
+ if valid_count == 0:
195
+ return None
196
+ payload = {"version": 1, "products": products}
197
+ return f"<DERMACARE_PRODUCTS_JSON>{json.dumps(payload, ensure_ascii=False)}</DERMACARE_PRODUCTS_JSON>"
198
+
199
+
200
+ def _ensure_products_json_block(suggestions: str, cands: list[dict], budget_twd: int | None) -> str | None:
201
+ existing = _extract_products_json_block(suggestions)
202
+ if existing:
203
+ return existing
204
+ filtered = _filter_candidates_by_budget(cands, budget_twd)
205
+ return _build_products_json_block_from_candidates(filtered)
206
+
207
  # ---- Inference on GPU (ZeroGPU pattern) ----
208
  @spaces.GPU(duration=120)
209
  def generate_answer(image, question, temperature=0.7, top_p=0.95, max_tokens=256):
 
324
  sections = [base.strip()]
325
  if include_products:
326
  sections.append(f"Suggested products:\n{suggestions}")
327
+ if "<DERMACARE_PRODUCTS_JSON>" not in suggestions:
328
+ json_block = _ensure_products_json_block(suggestions, cands, budget_twd)
329
+ if json_block:
330
+ sections.append(json_block)
331
  sections.append(safety)
332
 
333
  return "\n\n".join([s for s in sections if s])