pixel3user commited on
Commit
b340e7a
·
1 Parent(s): d924ea0
Files changed (1) hide show
  1. app.py +43 -51
app.py CHANGED
@@ -13,37 +13,6 @@ from peft import PeftModel
13
  from qwen_vl_utils import process_vision_info # pip install qwen-vl-utils
14
  from tools.retriever import search as product_search
15
 
16
- # ---- Product JSON block markers ----
17
- PRODUCTS_START = "<DERMACARE_PRODUCTS_JSON>"
18
- PRODUCTS_END = "</DERMACARE_PRODUCTS_JSON>"
19
-
20
- def append_products_json_to_text(text_answer: str, products: list[dict]) -> str:
21
- """
22
- Append a machine-readable JSON block to the end of the text.
23
- The Flutter client will read between the PRODUCTS_START/END tags.
24
- """
25
- payload = {
26
- "version": 1,
27
- "products": products or [],
28
- }
29
- block = PRODUCTS_START + json.dumps(payload, ensure_ascii=False) + PRODUCTS_END
30
- return text_answer.rstrip() + "\n\n" + block
31
-
32
- def to_product_card(meta):
33
- return {
34
- "id": meta.get("id"),
35
- "brand": meta.get("brand_en") or meta.get("brand_zh"),
36
- "name": meta.get("product_name_en") or meta.get("product_name_zh"),
37
- "category": meta.get("category_en") or meta.get("category_zh"),
38
- "price_value": meta.get("price_value"),
39
- "price_currency": meta.get("price_currency"),
40
- "why": "Matches your query by skin concern/ingredient.",
41
- "how": "Use as directed on label; patch-test first.",
42
- "url": meta.get("source_url"),
43
- "image_url": meta.get("image_url"),
44
- "score": round(float(meta.get("_score", 0.0)), 3),
45
- }
46
-
47
  print("VERSIONS:", transformers.__version__, accelerate.__version__, torch.__version__, np.__version__)
48
  os.environ["ACCELERATE_USE_SLOW_RETRIEVAL"] = "true"
49
 
@@ -123,6 +92,40 @@ def recommend_products(query_text: str, budget_twd: int | None = None, k: int =
123
 
124
  return answer
125
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
126
  # ---- Inference on GPU (ZeroGPU pattern) ----
127
  @spaces.GPU(duration=120)
128
  def generate_answer(image, question, temperature=0.7, top_p=0.95, max_tokens=256):
@@ -231,26 +234,15 @@ def pet_answer_with_recs(image, question, temperature=0.7, top_p=0.95, max_token
231
  "Safety notes: For broken/infected skin, pregnancy/lactation, infants, "
232
  "or if symptoms worsen—seek a qualified dermatologist. Patch-test first."
233
  )
234
- # Final combined message (human-readable)
235
- if suggestions.strip() != '':
236
- product_section = f"Suggested products:\n{suggestions}"
237
- else:
238
- product_section = "No relevant products."
239
-
240
- human_text = f"{base}\n\n{product_section}\n\n{safety}"
241
-
242
- # Build deterministic product cards (top-3) for client rendering.
243
- # If retrieval/index fails, fall back to empty list so the client gracefully
244
- # renders only the text.
245
- products_json = []
246
- try:
247
- top3 = [to_product_card(c) for c in cands[:3]]
248
- # Filter out items missing essential fields
249
- products_json = [p for p in top3 if p.get("id") and p.get("brand") and p.get("name")]
250
- except Exception:
251
- products_json = []
252
 
253
- return append_products_json_to_text(human_text, products_json)
254
 
255
  # ---- UI ----
256
  with gr.Blocks(title="DermalCare - Pet & Skincare Assistant") as demo:
@@ -276,4 +268,4 @@ with gr.Blocks(title="DermalCare - Pet & Skincare Assistant") as demo:
276
  outputs=answer
277
  )
278
 
279
- demo.queue().launch(show_api=False, share=True)
 
13
  from qwen_vl_utils import process_vision_info # pip install qwen-vl-utils
14
  from tools.retriever import search as product_search
15
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
  print("VERSIONS:", transformers.__version__, accelerate.__version__, torch.__version__, np.__version__)
17
  os.environ["ACCELERATE_USE_SLOW_RETRIEVAL"] = "true"
18
 
 
92
 
93
  return answer
94
 
95
+
96
+ def _count_products_from_tagged_json(text: str) -> int | None:
97
+ start_tag = "<DERMACARE_PRODUCTS_JSON>"
98
+ end_tag = "</DERMACARE_PRODUCTS_JSON>"
99
+ start = text.find(start_tag)
100
+ end = text.find(end_tag)
101
+ if start == -1 or end == -1 or end <= start:
102
+ return None
103
+ json_str = text[start + len(start_tag):end]
104
+ try:
105
+ payload = json.loads(json_str)
106
+ products = payload.get("products", [])
107
+ if isinstance(products, list):
108
+ return len(products)
109
+ except Exception:
110
+ return None
111
+ return None
112
+
113
+
114
+ def _has_valid_suggestions(raw_suggestions: str) -> bool:
115
+ cleaned = raw_suggestions.strip()
116
+ if not cleaned:
117
+ return False
118
+
119
+ lower = cleaned.lower()
120
+ if "no relevant products" in lower:
121
+ return False
122
+
123
+ count = _count_products_from_tagged_json(cleaned)
124
+ if count is not None:
125
+ return count > 0
126
+
127
+ return True
128
+
129
  # ---- Inference on GPU (ZeroGPU pattern) ----
130
  @spaces.GPU(duration=120)
131
  def generate_answer(image, question, temperature=0.7, top_p=0.95, max_tokens=256):
 
234
  "Safety notes: For broken/infected skin, pregnancy/lactation, infants, "
235
  "or if symptoms worsen—seek a qualified dermatologist. Patch-test first."
236
  )
237
+ suggestions = suggestions.strip()
238
+ include_products = _has_valid_suggestions(suggestions)
239
+
240
+ sections = [base.strip()]
241
+ if include_products:
242
+ sections.append(f"Suggested products:\n{suggestions}")
243
+ sections.append(safety)
 
 
 
 
 
 
 
 
 
 
 
244
 
245
+ return "\n\n".join([s for s in sections if s])
246
 
247
  # ---- UI ----
248
  with gr.Blocks(title="DermalCare - Pet & Skincare Assistant") as demo:
 
268
  outputs=answer
269
  )
270
 
271
+ demo.queue().launch(show_api=False, share=True)