Thiết kế Prompt & API — Tự động tạo đánh giá bằng AI
| Hạng mục | Nội dung |
|---|---|
| Trạng thái | 🟡 Đang thảo luận |
| Liên quan | #10 Tự động tạo đánh giá AI |
1. Thiết kế Prompt
1.1 Danh sách Prompt
| # | Tên Prompt | Mục đích | LLM sử dụng | Gọi từ |
|---|---|---|---|---|
| 1 | generate_review | Tạo nội dung đánh giá | Claude Sonnet 4 | generate_review node |
| 2 | quality_check | Kiểm tra chất lượng | Claude Haiku 4.5 | quality_check node |
| 3 | regenerate_with_feedback | Tái tạo khi NG kèm feedback | Claude Sonnet 4 | retry_generate node |
| 4 | regenerate_with_tone | Tái tạo khi đổi tone | Claude Sonnet 4 | /api/reviews/regenerate |
1.2 Prompt tạo đánh giá (generate_review)
Biến đầu vào:
| Biến | Kiểu | Mô tả | Ví dụ |
|---|---|---|---|
tone | string | Tone đánh giá | 丁寧 / カジュアル / ビジネス |
shop_name | string | Tên cửa hàng | 銀座ヘアサロンA |
rating | int | Đánh giá (1〜5) | 5 |
store_keywords | string | Keyword cửa hàng (phân cách bằng dấu phẩy) | 丁寧な接客, 駅近, 清潔感 |
survey_answers | string | Nội dung trả lời khảo sát | Xem bên dưới |
Định dạng survey_answers:
Q: 接客について
A: とても良い
Q: 清潔感について
A: 清潔でした
Q: また来たいと思いますか?
A: ぜひまた来たい
Q: 自由記述
A: スタッフの方がとても親切で、カウンセリングも丁寧でした。仕上がりも大満足です。System Prompt:
あなたは実際の顧客として口コミを書くアシスタントです。
アンケート回答を元に、自然で信頼性のある口コミ文を生成してください。
【トーン】{tone}
【トーン別の文体ガイド】
- 丁寧: Sử dụng kính ngữ.「〜していただきました」「大変満足しております」. Ấn tượng trầm tĩnh 30〜50 tuổi.
- カジュアル: Giọng nói chuyện với bạn bè.「〜だった!」「めっちゃ良かった」. Ấn tượng tươi sáng 20〜30 tuổi.
- ビジネス: Khách quan, ngắn gọn.「サービスの質が高い」「費用対効果が良い」. Ấn tượng doanh nhân.
【生成ルール】
1. Số ký tự: 200〜400 ký tự
2. Cấu trúc: Lý do đến cửa hàng → Chi tiết trải nghiệm → Cảm nhận/Tổng kết
3. Cụ thể: Phản ánh nội dung trả lời khảo sát (không bao gồm câu hỏi)
4. Keyword: Chèn 1〜3 keyword một cách tự nhiên. Không cần nhồi hết
5. Tự nhiên: Tránh các điều sau
- Liệt kê dạng bullet
- Từ nối rõ ràng「まず」「次に」「最後に」
- Khen quá mức liên tục
- Nhồi keyword máy móc
- Giọng quảng cáo「〜がおすすめです」
6. Đa dạng: Mỗi lần tạo phải khác nhau về cách mở đầu, cấu trúc, cách diễn đạt
7. Giống con người: Thêm cảm nhận nhỏ, câu chuyện cá nhân để tạo cảm giác trải nghiệm thựcHuman Prompt:
以下のアンケート回答から口コミ文を生成してください。
【店舗名】{shop_name}
【評価】★{rating}
【店舗キーワード】{store_keywords}
【回答内容】
{survey_answers}Tham số LLM:
| Tham số | Giá trị | Lý do |
|---|---|---|
| model | claude-sonnet-4-20250514 | Chất lượng tiếng Nhật tốt |
| temperature | 0.8 | Tạo văn phong đa dạng |
| max_tokens | 800 | 400 ký tự (~600 tokens) + dư |
| top_p | 0.95 | Mở rộng phạm vi biểu đạt tự nhiên |
Ví dụ đầu ra (Tone: 丁寧):
友人の紹介で銀座ヘアサロンAを初めて利用いたしました。駅から近く迷わずに到着できたのが助かりました。店内は清潔感があり、落ち着いた雰囲気でリラックスできます。担当していただいたスタイリストの方のカウンセリングがとても丁寧で、髪の悩みや希望をしっかり聞いてくださいました。施術中も細やかな気配りがあり、仕上がりにはとても満足しています。次回もぜひお願いしたいと思います。
1.3 Prompt kiểm tra chất lượng (quality_check)
Tiêu chí chấm điểm (100 điểm):
| # | Tiêu chí | Điểm | Tiêu chuẩn đạt |
|---|---|---|---|
| 1 | Số ký tự | 20 điểm | 200〜400 ký tự: 20 điểm / Ngoài phạm vi: 0〜10 điểm |
| 2 | Tự nhiên | 30 điểm | Không có cảm giác AI: 30 điểm / Không tự nhiên: 0〜15 điểm |
| 3 | Biểu đạt không phù hợp | 20 điểm | Không vấn đề: 20 điểm / Có: 0 điểm |
| 4 | Phản ánh keyword | 15 điểm | 1〜3 keyword tự nhiên: 15 điểm |
| 5 | Phản ánh khảo sát | 15 điểm | Phản ánh cụ thể: 15 điểm |
Tiêu chuẩn đạt: 70 điểm trở lên → Đạt / Dưới 70 → Tái tạo (tối đa 3 lần)
Model sử dụng: Claude Haiku 4.5 (temperature: 0.1 — để kết quả đánh giá ổn định)
Định dạng JSON đầu ra:
{
"passed": true,
"score": 85,
"breakdown": {
"char_count": {"score": 20, "detail": "280文字。範囲内。"},
"naturalness": {"score": 25, "detail": "概ね自然。"},
"inappropriate": {"score": 20, "detail": "問題なし。"},
"keywords": {"score": 10, "detail": "2個含まれている。"},
"survey_reflection": {"score": 10, "detail": "回答内容が反映されている。"}
},
"feedback": ""
}1.4 Prompt tái tạo
Khi chất lượng NG (regenerate_with_feedback):
- Prompt generate_review + điểm lần trước + feedback cải thiện
- temperature: 0.9 (cao hơn để tạo văn khác lần trước)
Khi đổi tone (regenerate_with_tone):
- Prompt generate_review + chỉ thị "không sử dụng lại cách diễn đạt của lần trước"
- temperature: 0.8
1.5 Giá trị cấu hình tuning
| Cài đặt | Giá trị mặc định | Phạm vi điều chỉnh |
|---|---|---|
| Điểm đạt | 70 | 50〜90 |
| Số lần retry tối đa | 3 | 1〜5 |
| Số ký tự tối thiểu | 200 | 100〜300 |
| Số ký tự tối đa | 400 | 300〜600 |
Quản lý hằng số trong
app/config.py. Sau này có thể thay đổi từ màn hình quản lý.
2. Thiết kế API
2.1 Cấu trúc hệ thống
Frontend (Vue.js) → Laravel API (hiện có) → Python FastAPI (mới) → Claude API- Frontend → Laravel: Xác thực/quản lý session xử lý bên Laravel hiện có
- Laravel → Python: Giao tiếp HTTP nội bộ (cùng VPC), xác thực bằng API key
- Python → Anthropic API: Giao tiếp HTTPS bên ngoài
2.2 Endpoint Python FastAPI
POST /api/v1/generate — Tạo đánh giá mới
Request:
{
"survey_id": 123,
"shop_name": "銀座ヘアサロンA",
"rating": 5,
"tone": "丁寧",
"store_keywords": ["丁寧な接客", "駅近", "清潔感"],
"survey_answers": [
{"question": "接客について", "answer": "とても良い"},
{"question": "自由記述", "answer": "スタッフの方がとても親切で..."}
]
}Response:
{
"status": "success",
"data": {
"review_text": "友人の紹介で銀座ヘアサロンAを初めて利用いたしました。...",
"char_count": 280,
"quality_score": 85,
"quality_breakdown": { ... },
"retry_count": 0,
"tone_used": "丁寧"
}
}Timeout: 30 giây
POST /api/v1/regenerate — Đổi tone / tái tạo
Request:
{
"survey_id": 123,
"shop_name": "銀座ヘアサロンA",
"rating": 5,
"tone": "カジュアル",
"store_keywords": ["丁寧な接客", "駅近", "清潔感"],
"survey_answers": [...],
"previous_tone": "丁寧",
"previous_review": "友人の紹介で銀座ヘアサロンAを..."
}GET /api/v1/health — Health check
{"status": "ok", "version": "1.0.0", "llm_available": true}2.3 Endpoint Laravel API
GET /api/surveys/{id}/for-review — Lấy dữ liệu khảo sát (Python gọi)
{
"survey_id": 123,
"shop_id": 456,
"shop_name": "銀座ヘアサロンA",
"rating": 5,
"answered_at": "2026-04-08T14:30:00+09:00",
"answers": [
{"question_id": 1, "question": "接客について", "answer_type": "select", "answer": "とても良い"},
{"question_id": 5, "question": "自由記述", "answer_type": "text", "answer": "スタッフの方がとても親切で..."}
],
"store_keywords": ["丁寧な接客", "駅近", "清潔感"]
}
store_keywordslấy từ KeywordSettings hiện có (/mappy/keywords).
POST /api/reviews/generate — Gọi từ frontend (Laravel → Python nội bộ)
Request: {"survey_id": 123, "tone": "丁寧"}
Luồng xử lý:
- Kiểm tra xác thực session
- Lấy dữ liệu khảo sát từ survey_id
- Lấy store_keywords từ shop_id
- Gọi Python FastAPI
/api/v1/generate - Trả kết quả về frontend
POST /api/reviews/regenerate — Đổi tone / tái tạo
Request: {"survey_id": 123, "tone": "カジュアル", "previous_review": "..."}
POST /api/reviews/submit — Lưu đánh giá + trả URL đăng Google
Request:
{
"survey_id": 123,
"review_text": "友人の紹介で銀座ヘアサロンAを...",
"tone": "丁寧",
"edited": true,
"quality_score": 85
}Response:
{
"success": true,
"data": {
"review_id": 789,
"google_review_url": "https://search.google.com/local/writereview?placeid=XXXXX",
"message": "口コミが保存されました。下記URLからGoogleに投稿してください。"
}
}Việc đăng thực tế do người dùng tự thực hiện bằng tài khoản Google của họ (đối sách Google).
GET /api/surveys/high-rated — Danh sách khảo sát đánh giá cao
Query: ?shop_id=456&min_rating=4&page=1&per_page=20
{
"data": [
{"survey_id": 123, "rating": 5, "answered_at": "2026-04-08", "summary": "接客: とても良い / 自由記述あり", "has_generated_review": false}
],
"meta": {"total": 45, "page": 1, "per_page": 20}
}2.4 Thiết kế DB (Bảng mới)
Bảng reviews:
| Cột | Kiểu | Mô tả |
|---|---|---|
| id | bigint (PK) | |
| survey_id | bigint (FK) | ID khảo sát |
| shop_id | bigint (FK) | ID cửa hàng |
| review_text | text | Nội dung đánh giá cuối cùng |
| tone | varchar(20) | Tone sử dụng |
| quality_score | int | Điểm chất lượng |
| edited | boolean | Người dùng đã chỉnh sửa thủ công hay chưa |
| submitted_at | timestamp | Thời gian đăng lên Google |
| created_at / updated_at | timestamp |
Bảng review_generation_logs:
| Cột | Kiểu | Mô tả |
|---|---|---|
| id | bigint (PK) | |
| survey_id | bigint (FK) | ID khảo sát |
| review_text | text | Nội dung đánh giá đã tạo |
| tone | varchar(20) | Tone |
| quality_score | int | Điểm chất lượng |
| quality_breakdown | json | Chi tiết kiểm tra chất lượng |
| retry_count | int | Số lần retry |
| generation_type | varchar(20) | initial / retry / regenerate / tone_change |
| llm_model | varchar(50) | Model sử dụng |
| input_tokens / output_tokens | int | Số token |
| cost_yen | decimal(10,4) | Chi phí (Yên) |
| created_at | timestamp |
2.5 Xử lý lỗi
| Mã lỗi | HTTP | Mô tả |
|---|---|---|
SURVEY_NOT_FOUND | 404 | Khảo sát không tồn tại |
LOW_RATING | 400 | Đánh giá thấp (3 sao trở xuống) |
GENERATION_FAILED | 500 | Tạo LLM thất bại (vượt giới hạn retry) |
LLM_UNAVAILABLE | 503 | Anthropic API không phản hồi |
RATE_LIMIT | 429 | Vượt giới hạn API |
INVALID_TONE | 400 | Tone không hợp lệ |
2.6 Bảo mật & Hiệu suất
| Hạng mục | Nội dung |
|---|---|
| Xác thực Python API | Xác minh API key nội bộ qua header X-API-Key |
| Mạng | Chỉ truy cập trong cùng VPC (không công khai) |
| Giới hạn tốc độ | 100 lượt/ngày mỗi cửa hàng |
| Log | Ghi log tất cả request vào review_generation_logs |
| Response tạo lần đầu | Trong 10 giây (không retry) |
| Response tối đa | Trong 30 giây (có retry) |
| Request đồng thời | Tối đa 10 |
3. Đối sách chính sách đánh giá Google
3.1 Phương pháp phát hiện của Google và đối sách
Google phát hiện đánh giá AI bằng các phương pháp sau:
| # | Phương pháp phát hiện | Mô tả | Đối sách của hệ thống |
|---|---|---|---|
| 1 | Phân tích mẫu văn bản | Cùng cửa hàng có văn phong/cấu trúc lặp lại | temperature 0.8 + 3 tone + chỉ thị "mỗi lần khác nhau" |
| 2 | Phân tích thời gian đăng | Nhiều đánh giá trong thời gian ngắn | Mỗi flow chỉ 1 bài, không tạo hàng loạt |
| 3 | Phân tích IP/thiết bị | Nhiều đánh giá từ cùng IP/thiết bị | Khách hàng tự đăng từ thiết bị/tài khoản Google của họ |
| 4 | Phân tích hành vi tài khoản | Tài khoản mới chỉ để đăng đánh giá | Sử dụng tài khoản Google hiện có của khách |
| 5 | Xử lý ngôn ngữ tự nhiên (NLP) | Văn phong đặc trưng AI (cấu trúc quá hoàn hảo) | Prompt cấm "liệt kê", "khen quá mức", yêu cầu "giống con người" |
| 6 | Phân tích mật độ keyword | Chèn keyword không tự nhiên (SEO spam) | "Không ép buộc", "1〜3 keyword" trong prompt |
| 7 | Tính nhất quán nội dung | Nội dung chung chung không dựa trên trải nghiệm thực | Tạo từ dữ liệu khảo sát thực tế, phản ánh trải nghiệm cụ thể |
3.2 Chính sách Google (thời điểm 2025)
Google Maps Content Policy cấm:
- Nội dung giả mạo: Đánh giá không dựa trên trải nghiệm thực
- Mạo danh: Đăng với danh nghĩa người khác
- Spam: Lặp lại cùng nội dung, đăng với mục đích quảng cáo
- Nội dung tự động tạo: Đăng tự động bằng bot hoặc script
Quan trọng: Google cấm "AI tự động đăng", không cấm rõ ràng việc "AI tạo bản nháp, người dùng xác nhận/chỉnh sửa rồi tự đăng". Tuy nhiên đây là vùng xám, nên phải thực hiện các đối sách dưới đây.
3.3 Đối sách bắt buộc
| # | Đối sách | Cách triển khai | Ưu tiên |
|---|---|---|---|
| 1 | Khách hàng tự đăng | Sau submit hiển thị Google Review URL, khách tự đăng bằng tài khoản mình. Không tự động đăng qua API | Bắt buộc |
| 2 | Khuyến khích chỉnh sửa | Hiển thị nổi bật trên màn preview "Hãy chỉnh sửa bằng lời của bạn trước khi đăng" | Bắt buộc |
| 3 | Tạo văn phong đa dạng | temperature 0.8, 3 tone, prompt "mỗi lần cấu trúc khác" | Bắt buộc |
| 4 | Chèn keyword tự nhiên | "Không ép buộc", "1〜3 keyword" trong prompt | Bắt buộc |
| 5 | Tạo từng bài một | Không làm tính năng tạo hàng loạt. Mỗi flow chỉ 1 bài | Bắt buộc |
| 6 | Khuyến nghị khoảng cách đăng | Hiển thị trên UI "Khuyến nghị đăng khoảng 1 bài/ngày" | Khuyến nghị |
| 7 | Tiêu chí phát hiện AI trong quality check | Trừ điểm "biểu đạt nhận ra là AI" trong quality_check | Bắt buộc |
| 8 | Ghi log | Ghi log toàn bộ tạo/đăng, có thể truy vết khi có vấn đề | Bắt buộc |
3.4 Hiển thị cảnh báo trên UI (bắt buộc)
Màn hình preview:
⚠ Đánh giá này là bản nháp do AI tạo.
Trước khi đăng, vui lòng xác nhận và chỉnh sửa nội dung bằng lời của bạn.
Nếu có nội dung khác với trải nghiệm thực tế, vui lòng sửa lại.Màn hình hoàn thành:
Bản nháp đánh giá đã được lưu.
Vui lòng mở Google Maps từ link bên dưới và đăng bằng tài khoản của bạn.
[Viết đánh giá trên Google Maps →]