from __future__ import annotations import re from textwrap import shorten from openai import OpenAI from app.config import settings from app.schemas import RewriteRequest, RewriteResponse SYSTEM_PROMPT = """ 你是中文内容编辑与合规顾问。请把输入内容进行“原创改写”,要求: 1) 保留核心事实,但避免逐句复述; 2) 结构清晰:导语、3-5个小节、结尾行动建议; 3) 风格适合微信公众号,表达自然,避免AI腔; 4) 如果原文存在未经核实结论,请使用“可能/有待验证”等措辞; 5) 输出必须是 JSON,字段:title, summary, body_markdown。 """.strip() class AIRewriter: def __init__(self) -> None: self._client = None if settings.openai_api_key: self._client = OpenAI( api_key=settings.openai_api_key, base_url=settings.openai_base_url, ) def rewrite(self, req: RewriteRequest) -> RewriteResponse: if not self._client: return self._fallback_rewrite(req) user_prompt = f""" 原始内容: {req.source_text} 改写约束: - 标题参考:{req.title_hint or '自动生成'} - 目标语气:{req.tone} - 目标读者:{req.audience} - 必须保留观点:{req.keep_points or '无'} - 避免词汇:{req.avoid_words or '无'} """.strip() completion = self._client.responses.create( model=settings.openai_model, input=[ {"role": "system", "content": SYSTEM_PROMPT}, {"role": "user", "content": user_prompt}, ], text={"format": {"type": "json_object"}}, ) text = completion.output_text import json data = json.loads(text) return RewriteResponse(**data) def _fallback_rewrite(self, req: RewriteRequest) -> RewriteResponse: clean_text = re.sub(r"\n{2,}", "\n", req.source_text.strip()) lines = [line.strip() for line in clean_text.split("\n") if line.strip()] head = lines[0] if lines else clean_text[:50] title = req.title_hint.strip() or f"{shorten(head, width=26, placeholder='')}:可执行解读" summary = shorten(clean_text, width=90, placeholder="...") body = ( f"## 导语\n" f"这篇内容值得关注的核心在于:{summary}\n\n" f"## 重点拆解\n" f"1. 背景与问题:从原文可以看到关键矛盾已出现。\n" f"2. 方法与动作:建议按“目标-路径-验证”三步推进。\n" f"3. 风险与边界:避免绝对化表述,必要时补充数据来源。\n\n" f"## 公众号改写正文\n" f"{clean_text}\n\n" f"## 结尾\n" f"以上为原创重组版本,可继续补充案例与数据后发布。" ) return RewriteResponse(title=title, summary=summary, body_markdown=body)