baseline: Clover 独立仓库首次基线提交
将 Clover 从上层产品包旧仓库中独立出来,建立专属版本控制。 当前状态=纵切片端到端已打通(登录→选品→出文出图→审核→下载包), M1文案质量去套路化已验收。此提交作为后续按核销清单逐条修复的基线。 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
93
backend/scripts/verify_real_text_gen.py
Normal file
93
backend/scripts/verify_real_text_gen.py
Normal file
@@ -0,0 +1,93 @@
|
||||
"""
|
||||
scripts/verify_real_text_gen.py — 真实文案生成验收脚本
|
||||
调 LLM 用素颜霜产品数据生成3条,原文打印给北哥人工核查。
|
||||
用法:cd backend && python3 scripts/verify_real_text_gen.py
|
||||
读取 .env 里的 CODEPROXY_BASE_URL + CODEPROXY_KEY(中转站)
|
||||
"""
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import httpx
|
||||
from pathlib import Path
|
||||
from dotenv import load_dotenv
|
||||
|
||||
sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
|
||||
|
||||
# 加载 .env
|
||||
env_path = Path(__file__).parent.parent / ".env"
|
||||
load_dotenv(env_path)
|
||||
|
||||
from app.services.ai_engine._text_prompt import COPY_SYSTEM, build_prompt, parse_json_array
|
||||
|
||||
# 素颜霜产品数据(方法验证用,不依赖 DB)
|
||||
PRODUCT = {
|
||||
"name": "素颜霜",
|
||||
"category": "美妆护肤",
|
||||
"selling_points": ["遮瑕提亮", "持妆全天", "养肤成分温和"],
|
||||
"style_tone": "素人分享、真实不浮夸",
|
||||
"text_angles": ["痛点切入", "成分党", "使用场景", "质地肤感", "平价替代"],
|
||||
"brand_keyword": "XX素颜霜",
|
||||
"custom_prompt": "",
|
||||
}
|
||||
|
||||
COUNT = 3
|
||||
|
||||
|
||||
def main():
|
||||
# 主通道 apiports(实测真实可用,模型见 /v1/models)
|
||||
base_url = (os.environ.get("APIPORTS_BASE_URL") or "").rstrip("/")
|
||||
api_key = os.environ.get("APIPORTS_KEY", "")
|
||||
# apiports 无 gpt-4o-mini,文案用 claude-sonnet-4-5(中文质量好)
|
||||
model = os.environ.get("MODEL_TEXT", "claude-sonnet-4-5")
|
||||
|
||||
if not base_url or not api_key:
|
||||
print("[ERROR] .env 缺少 APIPORTS_BASE_URL 或 APIPORTS_KEY")
|
||||
sys.exit(1)
|
||||
|
||||
user_prompt = build_prompt(PRODUCT, COUNT)
|
||||
|
||||
print("=" * 60)
|
||||
print("SYSTEM PROMPT(前300字):")
|
||||
print(COPY_SYSTEM[:300], "...")
|
||||
print("=" * 60)
|
||||
print("USER PROMPT(完整):")
|
||||
print(user_prompt)
|
||||
print("=" * 60)
|
||||
print(f"调用 {base_url} 模型={model} 生成 {COUNT} 条文案...")
|
||||
|
||||
resp = httpx.post(
|
||||
f"{base_url}/chat/completions",
|
||||
headers={"Authorization": f"Bearer {api_key}"},
|
||||
json={
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": COPY_SYSTEM},
|
||||
{"role": "user", "content": user_prompt},
|
||||
],
|
||||
"temperature": 0.9,
|
||||
"max_tokens": 3000,
|
||||
},
|
||||
timeout=120,
|
||||
)
|
||||
resp.raise_for_status()
|
||||
|
||||
raw = resp.json()["choices"][0]["message"]["content"]
|
||||
print("\n===== 原始输出(供北哥核查)=====")
|
||||
print(raw)
|
||||
|
||||
copies = parse_json_array(raw)
|
||||
if copies:
|
||||
print(f"\n===== 解析成功,共 {len(copies)} 条 =====")
|
||||
for i, c in enumerate(copies):
|
||||
print(f"\n--- 第{i+1}条 [{c.get('angle','')}] ---")
|
||||
print(f"标题:{c.get('title')}")
|
||||
print(f"正文({len(c.get('content',''))}字):\n{c.get('content')}")
|
||||
print(f"标签:{c.get('tags')}")
|
||||
print(f"封面大字:{c.get('coverTitle')}")
|
||||
else:
|
||||
print("\n[WARN] JSON 解析失败,请人工看原始输出")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
Reference in New Issue
Block a user