活用シーンとソリューション

AI でレビュー返信文を作成:ブランドルール・要対応フラグ・人による承認で安全に運用

6 ステップ 12 分で読めます 56 回閲覧 0
目次

レビューに返信すると、きちんと声に耳を傾けていることが顧客に伝わり、その返信はこれから購入する人も読みます。しかし、心のこもった返信を複数の言語で何百件も書くには、毎週何時間もかかります。この記事では、ローカルの言語モデルを使い、ブランドメモと厳格なルールに沿って、各レビューへの返信文をレビュー投稿者の言語で下書きします。低評価、安全上の問題、法的措置の示唆、不正の疑いなど、人による対応が必要なレビューにはフラグを付け、すべてを承認用のシートに書き出します。自動で投稿されるものは一切ありません。

レビューへの返信に関する各プラットフォームのルールに従ってください。レビューの変更や削除と引き換えに返金、プレゼント、割引を申し出てはいけません。顧客データを公開してもいけません。そもそも公開返信が認められているかどうかも確認してください。返信は、投稿前に必ず人が承認する必要があります。

ステップ1:環境を準備

/opt/reviews 環境と Ollama は、ローカル LLM でレビューを分析する方法で用意したものを使います。同じレビュー CSV をそのまま使えます。スクリプトには id 列と text 列が必要で、rating があればそれも使用します。

ステップ2:ブランドメモを書く

モデルはこのメモをもとに、口調、連絡先、言及してよい事実を判断します。簡潔に、事実だけを書いてください。

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

ステップ3:返信スクリプトを作成

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 のキーワードリストに一致した場合に、そのレビューは要対応としてマークされます。処理済みのレビューはすぐに保存され、次回の実行ではスキップされます。

ステップ4:下書きを生成

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 です。

ステップ5:承認して投稿

  1. replies.csv を Excel または Google スプレッドシートで開き、まず needs_human = yes で絞り込みます。これらは担当者が自ら対応してください。プラットフォーム経由で顧客に個別に連絡し、問題を解決してから公開返信します。
  2. それ以外の行は下書きを読み、必要に応じて修正したうえで final_reply にコピーし、approved を yes にします。
  3. 承認済みの返信は、セラーセンターから投稿するか、プラットフォームが公式 API を提供している場合はその API で投稿します。
  4. どのレビューに誰が返信したかの記録として、ファイルを保管しておきます。

ステップ6:自社のビジネスに合わせて調整

  • ESCALATE に、顧客が使う言語(タイ語、スペイン語、日本語など)の単語を追加します。
  • 保証条件やお手入れ方法など、よく聞かれる事実をブランドメモに追加すると、下書きでよくある質問に正しく答えられるようになります。
  • 理想的だと考える返信を 2~3 件、例としてブランドメモに貼り付けておくと、モデルはその文体に倣います。
  • 人による対応が必要なレビューをすぐにチームへ知らせたい場合は、ワークフローツールでフラグ付きの行を Telegram グループに送信します。n8n で Telegram ボットを作成する方法を参照してください。

よくある質問

返信を自動で投稿できますか?

技術的にはプラットフォームの API を使えば可能ですが、人による承認をおすすめします。誤った公開返信は取り消すのが難しく、多くのプラットフォームでは、出品者がすべての発言に責任を負います。

下書きがどれも同じような文面になる

ルールで表現に変化をつけるようモデルに指示しており、temperature 0.5 によってもばらつきが出ます。最も効果的なのは、構成の異なる返信例をブランドメモに入れておくことです。

どのレビューに返信すべきですか?

ネガティブなレビューや詳しく書かれたレビューを優先してください。こうしたレビューには、良い返信によって購入を検討している人の考えを変えられる可能性があります。短い好意的なレビューには、簡単なお礼程度で十分です。顧客が全体として何に不満を持っているかを把握するには、埋め込みで顧客の話題を把握する方法を参照してください。

上記の手順で解決しない場合は、サポートチケットを送信して IMIDC の 24 時間 365 日対応テクニカルサポートへご連絡ください。サーバー IP、使用しているモデル、エラー出力を添えていただくと、より迅速に調査できます。

この回答はお役に立ちましたか?

関連チュートリアル