amz_review_analyse/prompts/smoke.py
OnesvmWhoops 2441c9119c Initial commit: VOC LLM 结构化分析流水线
包含七步编排入口、结构化/向量化/聚类/词频/报告模块与 prompts 配置;忽略原始 CSV 与本地密钥。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-03 15:40:13 +08:00

139 lines
4 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""
Prompt 验收脚本(修改 prompts/ 后运行)。
python3 prompts/smoke.py # 仅校验文件加载与渲染(无需 API Key)
python3 prompts/smoke.py --live # 调用模型跑 smoke/reviews.yaml(需 DASHSCOPE_API_KEY)
"""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
PROJECT_ROOT = Path(__file__).resolve().parent.parent
if str(PROJECT_ROOT) not in sys.path:
sys.path.insert(0, str(PROJECT_ROOT))
import yaml
from prompts.loader import (
build_batch_extraction_system,
build_batch_extraction_user,
get_schema,
product_feedback_categories,
validate_prompt_files,
)
def _load_smoke_reviews() -> dict:
path = Path(__file__).resolve().parent / "smoke/reviews.yaml"
with path.open(encoding="utf-8") as f:
return yaml.safe_load(f) or {}
def run_dry() -> int:
errors = validate_prompt_files()
if errors:
print("❌ Prompt 文件校验失败:")
for e in errors:
print(f" - {e}")
return 1
smoke = _load_smoke_reviews()
industry = smoke.get("industry", "Test")
product = smoke.get("product_name", "Test")
reviews = smoke.get("reviews") or []
keys = [str(r["id"]) for r in reviews]
tagged = "\n".join(f"[{r['id']}] {r['text']}" for r in reviews)
keys_literal = ", ".join(json.dumps(k) for k in keys)
system = build_batch_extraction_system(
industry,
product,
n_keys=len(keys),
keys_literal=keys_literal,
)
user = build_batch_extraction_user(
n_keys=len(keys),
keys_literal=keys_literal,
tagged_input=tagged,
)
print("✅ 外置 Prompt 加载与渲染通过")
print(f" 示例评论数: {len(reviews)}")
print(f" system 长度: {len(system)} 字符")
print(f" user 长度: {len(user)} 字符")
return 0
def run_live() -> int:
rc = run_dry()
if rc != 0:
return rc
try:
from 结构化_server import _call_dashscope_chat, _validate_extraction_strict
except ImportError as e:
print(f"❌ 无法导入结构化_server: {e}")
return 1
smoke = _load_smoke_reviews()
industry = smoke["industry"]
product = smoke["product_name"]
reviews = smoke["reviews"]
keys = [str(r["id"]) for r in reviews]
tagged = "\n".join(f"[{r['id']}] {r['text']}" for r in reviews)
keys_literal = ", ".join(json.dumps(k) for k in keys)
system = build_batch_extraction_system(
industry,
product,
n_keys=len(keys),
keys_literal=keys_literal,
)
user = build_batch_extraction_user(
n_keys=len(keys),
keys_literal=keys_literal,
tagged_input=tagged,
)
print("⏳ 调用模型进行 smoke 结构化…")
try:
raw = _call_dashscope_chat(
[{"role": "system", "content": system}, {"role": "user", "content": user}],
max_tokens=8192,
)
except Exception as e:
print(f"❌ 模型调用失败: {e}")
return 1
if not isinstance(raw, dict):
print(f"❌ 期望 JSON 对象,得到: {type(raw).__name__}")
return 1
ok = 0
for k in keys:
if k not in raw:
print(f"❌ 缺少键 {k}")
continue
try:
_validate_extraction_strict(raw[k], k)
ok += 1
print(f"✅ {k} 校验通过")
except ValueError as e:
print(f"❌ {k} 校验失败: {e}")
schema_cats = product_feedback_categories(get_schema())
print(f" 锁定 category 枚举: {', '.join(sorted(schema_cats))}")
return 0 if ok == len(keys) else 1
def main() -> int:
parser = argparse.ArgumentParser(description="Prompt smoke 验收")
parser.add_argument(
"--live",
action="store_true",
help="调用 DashScope 跑 smoke 评论(需 API Key)",
)
args = parser.parse_args()
return run_live() if args.live else run_dry()
if __name__ == "__main__":
raise SystemExit(main())