应用场景与解决方案

AI 分析商品评价与差评:用本地大模型做情感分析和维度标注,按商品汇总主要问题

6 个步骤 14 分钟阅读 53 次阅读 0
本文目录

一个商品在 Shopee、Lazada、Amazon、TikTok Shop 和独立站上会积累数百条评价,而且往往涉及多种语言。星级评分只能说明出了问题,却说明不了是什么问题。本文用本地大语言模型逐条阅读评价,记录每条评价的整体情感倾向、它称赞或批评的商品维度,以及提到的具体问题。随后按商品生成报告,列出被批评最多的维度、评分与内容不符的评价,以及由 AI 总结的主要问题和改进建议。整个流程都在你自己的服务器上运行,客户的评价内容不会发送给第三方。

请仅通过平台允许的方式获取评价,例如卖家中心导出、官方 API 或自有店铺的数据库。爬取电商平台数据可能违反其服务条款。分析前请删除不需要的个人信息。

步骤 1:安装工具

apt install -y python3-venv
python3 -m venv /opt/reviews
/opt/reviews/bin/pip install ollama numpy scikit-learn
ollama pull qwen2.5:7b

Ollama 的安装配置请参阅使用 Ollama 运行本地大模型。本文用不到 numpy 和 scikit-learn,但配套教程中的话题分析会用到它们。

步骤 2:准备评价数据

把评价导出为 UTF-8 编码的 CSV 文件。id 和 text 两列为必填;sku、rating(1 到 5)和 date 为可选列,但有了它们,报告会更有参考价值:

id,sku,rating,date,text
R1001,LS-01,2,2026-09-14,"The stand wobbles when I type, screws came loose after a week."
R1002,LS-01,5,2026-09-15,"Sturdy, looks great on my desk, easy to fold."
R1003,BT-07,1,2026-09-15,"左耳机三天就没声音了,客服也没回复。"

步骤 3:创建分析脚本

cat > /opt/reviews/reviews.py <<'EOF2'
import csv, json, os, sys
from collections import Counter, defaultdict
import ollama

MODEL = os.environ.get("MODEL", "qwen2.5:7b")
LANGUAGE = os.environ.get("REPORT_LANG", "English")       # language of issues, summaries and the report
ASPECTS = ["quality", "size_fit", "function", "durability", "ease_of_use",
           "delivery", "packaging", "price_value", "customer_service", "other"]
SENT = {"type": "string", "enum": ["positive", "neutral", "negative"]}
SCHEMA = {
    "type": "object",
    "properties": {
        "sentiment": SENT,
        "aspects": {"type": "array", "items": {"type": "object", "properties": {
            "aspect": {"type": "string", "enum": ASPECTS}, "sentiment": SENT}, "required": ["aspect", "sentiment"]}},
        "issues": {"type": "array", "items": {"type": "string"}},
        "summary": {"type": "string"},
    },
    "required": ["sentiment", "aspects", "issues", "summary"],
}
SYSTEM = ("You analyse customer reviews for an online shop. The review can be in any language. "
          "Give the overall sentiment, and the sentiment of each product aspect the review actually mentions. "
          f"List concrete problems as short phrases in {LANGUAGE} (empty list if there are none) "
          f"and write a one-sentence summary in {LANGUAGE}. Do not invent anything that is not in the review.")

def ask(system, text, schema=None):
    r = ollama.chat(model=MODEL, format=schema, options={"temperature": 0}, messages=[
        {"role": "system", "content": system}, {"role": "user", "content": text}])
    return r.message.content

src, out = sys.argv[1], "reviews_tagged.csv"
done = {}
if os.path.exists(out):
    with open(out, encoding="utf-8-sig") as f:
        done = {r["id"]: r for r in csv.DictReader(f)}
with open(src, encoding="utf-8-sig") as f:
    reviews = [r for r in csv.DictReader(f) if r.get("text", "").strip()]

fields = ["id", "sku", "rating", "sentiment", "aspects", "issues", "summary", "text"]
new_file = not os.path.exists(out)
with open(out, "a", newline="", encoding="utf-8-sig") as f:
    w = csv.DictWriter(f, fieldnames=fields)
    if new_file:
        w.writeheader()
    for r in reviews:
        if r["id"] in done:
            continue
        d = json.loads(ask(SYSTEM, r["text"][:4000], SCHEMA))
        row = {"id": r["id"], "sku": r.get("sku", ""), "rating": r.get("rating", ""), "sentiment": d["sentiment"],
               "aspects": "; ".join(f"{a['aspect']}:{a['sentiment']}" for a in d["aspects"]),
               "issues": "; ".join(i.strip() for i in d["issues"] if i.strip()), "summary": d["summary"], "text": r["text"]}
        w.writerow(row)
        f.flush()
        done[r["id"]] = row
        print(r["id"], d["sentiment"], flush=True)

by_sku = defaultdict(list)
for row in done.values():
    by_sku[row["sku"] or "-"].append(row)
with open("report.md", "w", encoding="utf-8") as f:
    for sku, rows in sorted(by_sku.items(), key=lambda x: -len(x[1])):
        sent = Counter(r["sentiment"] for r in rows)
        neg = Counter(a.split(":")[0] for r in rows for a in r["aspects"].split("; ") if a.endswith(":negative"))
        issues = [i for r in rows for i in r["issues"].split("; ") if i]
        odd = [r["id"] for r in rows if r["rating"].isdigit() and ((int(r["rating"]) >= 4 and r["sentiment"] == "negative")
               or (int(r["rating"]) <= 2 and r["sentiment"] == "positive"))]
        f.write(f"## {sku}: {len(rows)} reviews\n\n")
        f.write(f"- Positive {sent['positive']}, neutral {sent['neutral']}, negative {sent['negative']}\n")
        f.write("- Most criticised aspects: " + (", ".join(f"{a} ({n})" for a, n in neg.most_common(5)) or "none") + "\n")
        f.write("- Rating does not match the text: " + (", ".join(odd) or "none") + "\n\n")
        if issues:
            f.write(ask(f"You are a product manager. Group these customer complaints into the main problems, "
                        f"most frequent first, and suggest one concrete fix for each. Answer in {LANGUAGE}, briefly.",
                        "\n".join(issues[:300])) + "\n\n")
        print("report:", sku, flush=True)
print("done: reviews_tagged.csv, report.md")
EOF2

JSON Schema 强制模型按固定结构作答:三种情感倾向之一、从你的列表中选取的维度,以及问题列表。每条评价分析完成后立即保存,再次运行时会跳过已完成的评价,因此可以随时中断和继续,之后也可以把新评价追加到同一个 CSV 文件中。

步骤 4:运行分析

cd /data/reviews
REPORT_LANG="Simplified Chinese" nohup /opt/reviews/bin/python /opt/reviews/reviews.py reviews.csv > reviews.log 2>&1 &
tail -f reviews.log

在 CPU 服务器上,7B 模型处理每条评价需要几秒到几十秒,具体取决于评价长度;数据量大的导出文件可以放在夜间运行,或者通过 MODEL=qwen2.5:3b 换用 qwen2.5:3b 等更小的模型。结果文件为 reviews_tagged.csv(每条评价一行)和 report.md(每个商品一节)。

步骤 5:解读结果

  • 被批评最多的维度(报告中的 Most criticised aspects)显示商品让人失望的地方:耐用性、尺码、物流或包装问题需要不同的解决办法,也由不同的团队负责。
  • 评分与内容不符(报告中的 Rating does not match the text)会列出诸如仍在抱怨(多半是物流问题)的五星评价,以及实际上是好评的一星评价。这两类都值得看一看。
  • AI 总结会把投诉归纳为几个主要问题,并为每个问题给出一条改进建议;可以直接转给产品开发团队或供应商。
  • 在 reviews_tagged.csv 中按商品和负面情感筛选,即可阅读每个问题背后的原始评价。

请根据你的类目调整 ASPECTS 列表,例如服装类可以用 fabric、size_fit 和 colour(面料、尺码、颜色),电子产品可以用 battery、connectivity 和 sound(电池、连接、音质)。

步骤 6:形成例行流程

每月导出一次新评价,用同一个文件运行脚本,并对比不同时期的报告。如果想发现意料之外的问题,可以按照用 Embedding 向量把评价归类成话题的方法对评价进行聚类。如果想更快地回复评价,请参阅用 AI 起草买家评价回复。客户称赞最多的地方,也是撰写商品详情的好素材。

常见问题

分析结果准确吗?

对于表达清晰的评价,情感倾向和维度的判断都比较可靠。反讽、褒贬参半的评价以及“ok”这类极短的文本则较难判断。在依赖这些统计数字之前,请随机抽取 20 条评价与结果核对,并把温度保持为 0,以获得一致的回答。

能用同样的方法分析工单或聊天记录吗?

可以。把每张工单或每段对话放入 text 列,并把维度替换为你的客服分类,例如账单、物流、安装设置或账户。

可以改用云端 AI 模型吗?

很多 AI API 都支持结构化输出,但这样评价内容就会离开你的服务器。请先确认你的隐私合规义务、服务商的服务条款及其支持的地区。

如果按以上步骤操作后问题仍未解决,请提交工单联系 IMIDC 7×24 技术支持,并附上服务器 IP、所用的模型、CSV 文件的前几行(去除个人信息)以及报错信息,方便工程师快速定位。

这篇文章有帮助吗?

相关教程