Spaces:
Sleeping
Sleeping
Commit ·
34059b2
1
Parent(s): 36d9d96
Diversify merchant negative spotlight
Browse files
app.py
CHANGED
|
@@ -1,4 +1,4 @@
|
|
| 1 |
-
"""Dual-interface Hugging Face Space for clothing aspect-level sentiment analysis."""
|
| 2 |
from __future__ import annotations
|
| 3 |
|
| 4 |
import csv
|
|
@@ -765,8 +765,9 @@ def export_merchant_scores(rows):
|
|
| 765 |
|
| 766 |
def negative_product_spotlight(limit: int = 6) -> str:
|
| 767 |
cards = []
|
|
|
|
| 768 |
for aspect in ASPECTS:
|
| 769 |
-
|
| 770 |
for product in PRODUCTS:
|
| 771 |
try:
|
| 772 |
result = _predict_product(product["name"])
|
|
@@ -778,8 +779,11 @@ def negative_product_spotlight(limit: int = 6) -> str:
|
|
| 778 |
conf = _safe_float(d.get("confidence"))
|
| 779 |
hits = _keyword_hits(product.get("review", ""), aspect)
|
| 780 |
reason = ", ".join(hits[:3]) if hits else _short_text(product.get("review") or product.get("features"), 48)
|
| 781 |
-
|
| 782 |
-
|
|
|
|
|
|
|
|
|
|
| 783 |
if best is None:
|
| 784 |
cards.append(
|
| 785 |
f'<div class="negative-card compact-negative"><h4>{aspect}</h4>'
|
|
@@ -787,6 +791,7 @@ def negative_product_spotlight(limit: int = 6) -> str:
|
|
| 787 |
)
|
| 788 |
continue
|
| 789 |
conf, product, reason = best
|
|
|
|
| 790 |
img = f'<img class="mini-product-img" src="{_esc(_product_image_url(product))}" alt="{_esc(product["name"])}">'
|
| 791 |
cards.append(
|
| 792 |
f'<div class="negative-card compact-negative"><h4>{aspect}</h4>'
|
|
@@ -796,33 +801,6 @@ def negative_product_spotlight(limit: int = 6) -> str:
|
|
| 796 |
)
|
| 797 |
return '<div class="negative-grid">' + "".join(cards[:limit]) + '</div>'
|
| 798 |
|
| 799 |
-
items = []
|
| 800 |
-
for product in PRODUCTS:
|
| 801 |
-
try:
|
| 802 |
-
result = _predict_product(product["name"])
|
| 803 |
-
except Exception:
|
| 804 |
-
continue
|
| 805 |
-
for aspect in ASPECTS:
|
| 806 |
-
d = result.get("aspect_details", {}).get(aspect, {})
|
| 807 |
-
if d.get("label") != "Negative":
|
| 808 |
-
continue
|
| 809 |
-
hits = _keyword_hits(product.get("review", ""), aspect)
|
| 810 |
-
reason = ", ".join(hits) if hits else _short_text(product.get("review") or product.get("features"), 90)
|
| 811 |
-
items.append((_safe_float(d.get("confidence")), aspect, product, reason))
|
| 812 |
-
items.sort(key=lambda x: x[0], reverse=True)
|
| 813 |
-
cards = []
|
| 814 |
-
for conf, aspect, product, reason in items[:limit]:
|
| 815 |
-
img = f'<img class="mini-product-img" src="{_esc(_product_image_url(product))}" alt="{_esc(product["name"])}">'
|
| 816 |
-
cards.append(
|
| 817 |
-
f'<div class="negative-card">{img}<div><b>{_esc(product["name"])}</b>'
|
| 818 |
-
f'<div class="small-label">{_esc(product["category"])} · {aspect} Negative · conf {conf:.2f}</div>'
|
| 819 |
-
f'<p>{_esc(reason)}</p></div></div>'
|
| 820 |
-
)
|
| 821 |
-
if not cards:
|
| 822 |
-
return '<div class="note-card">No highly negative product found in the current catalog sample.</div>'
|
| 823 |
-
return '<div class="negative-grid">' + "".join(cards) + '</div>'
|
| 824 |
-
|
| 825 |
-
|
| 826 |
def _metadata_risks(features: str, categories: str, price: Any, rating: Any, count: Any) -> Dict[str, str]:
|
| 827 |
text = f"{features} {categories}".lower()
|
| 828 |
risks = {}
|
|
@@ -1274,3 +1252,4 @@ demo = build_app()
|
|
| 1274 |
if __name__ == "__main__":
|
| 1275 |
demo.launch(ssr_mode=False)
|
| 1276 |
|
|
|
|
|
|
| 1 |
+
"""Dual-interface Hugging Face Space for clothing aspect-level sentiment analysis."""
|
| 2 |
from __future__ import annotations
|
| 3 |
|
| 4 |
import csv
|
|
|
|
| 765 |
|
| 766 |
def negative_product_spotlight(limit: int = 6) -> str:
|
| 767 |
cards = []
|
| 768 |
+
used_products = set()
|
| 769 |
for aspect in ASPECTS:
|
| 770 |
+
candidates = []
|
| 771 |
for product in PRODUCTS:
|
| 772 |
try:
|
| 773 |
result = _predict_product(product["name"])
|
|
|
|
| 779 |
conf = _safe_float(d.get("confidence"))
|
| 780 |
hits = _keyword_hits(product.get("review", ""), aspect)
|
| 781 |
reason = ", ".join(hits[:3]) if hits else _short_text(product.get("review") or product.get("features"), 48)
|
| 782 |
+
candidates.append((conf, product, reason))
|
| 783 |
+
candidates.sort(key=lambda x: x[0], reverse=True)
|
| 784 |
+
best = next((item for item in candidates if item[1]["name"] not in used_products), None)
|
| 785 |
+
if best is None and candidates:
|
| 786 |
+
best = candidates[0]
|
| 787 |
if best is None:
|
| 788 |
cards.append(
|
| 789 |
f'<div class="negative-card compact-negative"><h4>{aspect}</h4>'
|
|
|
|
| 791 |
)
|
| 792 |
continue
|
| 793 |
conf, product, reason = best
|
| 794 |
+
used_products.add(product["name"])
|
| 795 |
img = f'<img class="mini-product-img" src="{_esc(_product_image_url(product))}" alt="{_esc(product["name"])}">'
|
| 796 |
cards.append(
|
| 797 |
f'<div class="negative-card compact-negative"><h4>{aspect}</h4>'
|
|
|
|
| 801 |
)
|
| 802 |
return '<div class="negative-grid">' + "".join(cards[:limit]) + '</div>'
|
| 803 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 804 |
def _metadata_risks(features: str, categories: str, price: Any, rating: Any, count: Any) -> Dict[str, str]:
|
| 805 |
text = f"{features} {categories}".lower()
|
| 806 |
risks = {}
|
|
|
|
| 1252 |
if __name__ == "__main__":
|
| 1253 |
demo.launch(ssr_mode=False)
|
| 1254 |
|
| 1255 |
+
|