feat:完成微信公众号的自动化工具
This commit is contained in:
80
app/services/ai_rewriter.py
Normal file
80
app/services/ai_rewriter.py
Normal file
@@ -0,0 +1,80 @@
|
||||
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)
|
||||
Reference in New Issue
Block a user