回覆評價能讓客戶感受到有人在傾聽,潛在買家也會閱讀這些回覆。但每週要用多種語言認真寫出幾百條回覆,得花上好幾個小時。本文用本地大語言模型為每條評價起草回覆,使用與評價相同的語言,並遵循你的品牌說明和一套嚴格的規則。它會標記出需要人工處理的評價,例如低分評價、安全問題、法律威脅或疑似欺詐,並把所有內容寫入一張表格供稽核。任何內容都不會自動釋出。
使用用本地大模型分析商品評價中配置好的 /opt/reviews 環境和 Ollama。同一個評價 CSV 檔案在這裡也能直接使用;指令碼需要 id 和 text 兩列,如果有 rating 列也會一併使用。
模型會依據這份說明確定語氣、聯絡方式以及可以提及的事實。內容要簡短、實事求是:
cat > /data/reviews/brand.txt <<'EOF2'
Business: ACME Home, sells bamboo office accessories online.
Tone: warm and simple, no slang, no emoji.
Support contact: the "Contact seller" button on the order page, or [email protected].
Facts you may mention: 12-month warranty on all stands.
Sign off as: The ACME Home team
EOF2
cat > /opt/reviews/replies.py <<'EOF2'
import csv, json, os, re, sys
import ollama
MODEL = os.environ.get("MODEL", "qwen2.5:7b")
BRAND = open(os.environ.get("BRAND_FILE", "brand.txt"), encoding="utf-8").read()
ESCALATE = re.compile(os.environ.get("ESCALATE",
r"refund|chargeback|injur|burn|fire|smoke|allerg|lawyer|lawsuit|scam|fraud|fake|police|退款|投訴|受傷|起火|過敏|律師|騙"), re.I)
SCHEMA = {"type": "object", "properties": {
"reply": {"type": "string"}, "needs_human": {"type": "boolean"}, "reason": {"type": "string"}},
"required": ["reply", "needs_human", "reason"]}
SYSTEM = """You draft public replies to customer reviews for the business described in the brand notes.
Rules:
- Reply in the same language as the review, in 2 to 4 sentences.
- Thank the customer and respond to the specific point they made. Vary your wording.
- Never admit legal liability. Never promise refunds, replacements, discounts or compensation.
- Never ask the customer to change or remove their review, and never offer anything in return for a review.
- Never include order numbers, names or other personal data.
- For problems, apologise briefly and invite the customer to contact support as described in the brand notes.
- Set needs_human to true for safety issues, legal threats, suspected fraud, abuse, or if you are unsure,
and give the reason. Otherwise leave reason empty.
Brand notes:
""" + BRAND
src, out = sys.argv[1], "replies.csv"
done = set()
if os.path.exists(out):
with open(out, encoding="utf-8-sig") as f:
done = {r["id"] 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()]
new_file = not os.path.exists(out)
with open(out, "a", newline="", encoding="utf-8-sig") as f:
w = csv.writer(f)
if new_file:
w.writerow(["id", "rating", "text", "draft_reply", "needs_human", "reason", "approved", "final_reply"])
for r in reviews:
if r["id"] in done:
continue
res = ollama.chat(model=MODEL, format=SCHEMA, options={"temperature": 0.5}, messages=[
{"role": "system", "content": SYSTEM},
{"role": "user", "content": f"Rating: {r.get('rating', '?')} of 5\nReview: {r['text'][:3000]}"}])
d = json.loads(res.message.content)
reasons = [d["reason"]] if d["needs_human"] and d["reason"] else []
if r.get("rating", "").isdigit() and int(r["rating"]) <= 2:
reasons.append("low rating")
if ESCALATE.search(r["text"]):
reasons.append("keyword: " + ESCALATE.search(r["text"]).group(0))
w.writerow([r["id"], r.get("rating", ""), r["text"], d["reply"].strip(),
"yes" if reasons or d["needs_human"] else "no", "; ".join(reasons), "", ""])
f.flush()
print(r["id"], "NEEDS HUMAN" if reasons or d["needs_human"] else "draft ok", flush=True)
print("done: replies.csv")
EOF2
當模型自己要求人工處理、評分為 2 分或以下,或者文本匹配 ESCALATE 關鍵詞列表時,這條評價就會被標記為需要人工處理。每條評價處理完成後立即儲存,下次執行時會跳過。
cd /data/reviews
/opt/reviews/bin/python /opt/reviews/replies.py reviews.csv
結果檔案為 replies.csv,包含 id、rating、text、draft_reply、needs_human、reason、approved 和 final_reply 列。
replies.csv,先篩選出 needs_human = yes 的行。這些評價請親自處理:通過平台私下聯絡客戶,解決問題後再公開回復。final_reply 列,並把 approved 設為 yes。ESCALATE 中補充客戶所用語言的關鍵詞,例如泰語、西班牙語或日語。技術上可以通過平台 API 實現,但我們建議保留人工稽核。錯誤的公開回復很難挽回,而且很多平台要求賣家對每一句話負責。
規則中已要求模型變換措辭,0.5 的溫度也會增加一些變化。最有效的辦法是在品牌說明中加入結構各不相同的示例回覆。
優先回覆差評和內容詳細的評價,好的回覆可能改變潛在買家的想法。簡短的好評最多回一句簡單的感謝即可。如果想整體瞭解客戶在抱怨什麼,請參閱用 Embedding 向量把評價歸類成話題。
如果按以上步驟操作後問題仍未解決,請提交工單聯絡 IMIDC 7×24 技術支援,並附上伺服器 IP、所用的模型以及報錯資訊,方便工程師快速定位。