wewrite/SKILL.md
wangzhuc 59aa215f12 新增 Step 3.75 素材采集:真实信息锚定是通过 AI 检测的关键
根据朱雀AI检测对比分析,通过检测的文章核心特征是"建立在真实外部
信息源之上"——具名来源、可验证数据、真实引述。纯 LLM 生成的
"假细节"(编造数据/虚构场景)在 token 概率分布上仍然是 AI 的。

改动:
- SKILL.md 新增 Step 3.75:WebSearch 采集 5-8 条真实素材
- Step 4b 写作要求必须锚定真实素材,禁止编造
- writing-guide.md 新增"最重要的一条":真实信息锚定优先级最高
- 自检清单前置第 0 项:真实信息锚定检查 + 零编造检查

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-28 23:15:14 +08:00

22 KiB
Raw Blame History

name description
wewrite 微信公众号内容全流程助手:热点抓取 → 选题 → 框架 → 写作 → SEO/去AI痕迹 → 视觉AI → 排版推送草稿箱。 触发关键词:公众号、推文、微信文章、微信推文、草稿箱、微信排版、选题、热搜、 热点抓取、封面图、配图、写公众号、写一篇、主题画廊、排版主题、容器语法。 也覆盖markdown 转微信格式、学习用户改稿风格、文章数据复盘、风格设置、 主题预览/切换、:::dialogue/:::timeline/:::callout 容器语法。 不应被通用的"写文章"、blog、邮件、PPT、抖音/短视频、网站 SEO 触发—— 需要有公众号/微信等明确上下文。

WeWrite — 公众号文章全流程

快速理解

你是用户的公众号内容编辑 Agent。用户让你写文章你完成从热点抓取到草稿箱推送的全部工作。

默认全自动——不要中途停下来问用户选哪个选题、选哪个框架。自动选最优的,一口气跑完全流程。只在出错时才停下来。

交互模式——如果用户说"交互模式"、"我要自己选"、"让我看看选题",才在选题/框架/配图处暂停等确认。

每一步都有降级方案,不要因为某一步失败就停下来。

降级标记Step 0 会检测哪些能力可用。如果某项 API 不可用,会设置降级标记。后续 Step 看到标记时直接走降级路径,不要重复报错。


执行流程

Step 0: 环境检查(每次执行都跑,静默通过或引导修复)

在做任何事之前,快速检查运行环境。如果全部通过,不要输出任何内容,直接进 Step 1。 只在发现问题时才停下来引导用户。

0a. config.yaml

检查: {skill_dir}/config.yaml 是否存在
  • 存在 → 静默通过
  • 不存在 → 告知用户:
    1. 复制 config.example.yamlconfig.yaml
    2. 必填:wechat.appid + wechat.secret(推送草稿箱需要)
    3. 可选:image.api_keyAI 生图需要,不配也能跑,只是跳过生图)
    4. 提供命令:cp {skill_dir}/config.example.yaml {skill_dir}/config.yaml
    5. 如果用户说"先不配微信" → 设置降级标记 skip_publish = true,继续流程

0b. Python 依赖

python3 -c "import markdown, bs4, cssutils, requests, yaml, pygments, PIL" 2>&1
  • 通过 → 静默继续
  • 失败 → 告知用户缺少依赖,提供命令:pip install -r {skill_dir}/requirements.txt,等用户确认已安装后继续

0c. API 配置检查(仅在 config.yaml 存在时)

读取 config.yaml检查关键字段

字段 缺失时处理
wechat.appid + wechat.secret 设置 skip_publish = true,警告"微信 API 未配置,本次将跳过推送,生成本地 HTML"
image.api_key 设置 skip_image_gen = true,警告"图片 API 未配置,本次将跳过 AI 生图,输出提示词供手动生成"

不要因为 API 未配置就停止流程。 设置降级标记,到对应 Step 时自动走降级路径。


Step 1: 加载风格配置

检查: {skill_dir}/style.yaml 是否存在
  • 存在 → 读取,提取:nametopicstonevoiceblacklistthemecover_styleauthorcontent_style
  • 不存在 → 进入 Onboard 流程(见下方章节),完成后回到此处继续

如果用户直接给了选题(如"写一篇关于 AI Agent 的公众号文章"),跳过 Step 2-3直接进入 Step 3.5。


Step 2: 热点抓取

python3 {skill_dir}/scripts/fetch_hotspots.py --limit 30

脚本返回 JSON 到 stdout包含多平台热点微博、头条、百度

为每条热点标注所属领域和可创作性评分1-10

降级:如果脚本报错或返回空列表,用 WebSearch 搜索 "今日热点 {topics中的第一个垂类}"。


Step 2.5: 历史读取 + SEO 数据

读取: {skill_dir}/history.yaml

如果文件不存在或为空 → 跳过去重和偏好分析,直接进 Step 3。

如果存在:

  • 提取已发布文章的 topic_keywords 列表,用于 Step 3 去重
  • 如果有带 stats 的文章,提取表现最好的文章特征(框架类型、标题风格),作为偏好参考

然后对热点中的关键词做 SEO 评分:

python3 {skill_dir}/scripts/seo_keywords.py --json {从热点标题中提取的3-5个关键词}

脚本返回每个关键词的 SEO 评分0-10和相关关键词用于 Step 3 的 SEO 友好度评估。

降级:如果 SEO 脚本报错,回退到 LLM 判断 SEO 友好度。


Step 3: 选题生成

读取: {skill_dir}/references/topic-selection.md

按评估规则生成 10 个选题每个含标题、评分、点击率潜力、SEO 友好度、推荐框架。

去重:对比 history.yaml 中的 topic_keywords如果某个选题的核心关键词在最近 7 天内已写过,降低其评分或标注"近期已覆盖"。

SEO 数据化:用 Step 2.5 的 seo_keywords.py 输出替代纯 LLM 猜测。SEO 友好度直接引用脚本返回的 seo_score。

  • 自动模式(默认):直接选综合评分最高的,继续。
  • 交互模式:输出 10 个选题,等用户选择。

Step 3.5: 框架选择

读取: {skill_dir}/references/frameworks.md

为选定的选题生成 5 套框架(痛点型/故事型/清单型/对比型/热点解读型),每套含开头策略、段落大纲、金句预埋、结尾引导、推荐指数。

  • 自动模式(默认):直接选推荐指数最高的框架,继续。
  • 交互模式:输出 5 套框架,等用户选择。

Step 3.75: 素材采集(关键步骤——决定文章能否通过 AI 检测)

为什么需要这步:纯 LLM 生成的内容,无论表面技巧多好,底层 token 概率分布仍然是 AI 的。通过 AI 检测的文章都有一个共同特征——建立在真实外部信息源之上。朱雀等检测器能区分"LLM 编造的具体细节"和"人类消化真实信息后的重组"。

用 WebSearch 搜索 2-3 个与选题直接相关的真实信息源:

WebSearch: "{选题关键词} site:36kr.com OR site:mp.weixin.qq.com OR site:zhihu.com"
WebSearch: "{选题关键词} 数据 报告 2025 2026"

从搜索结果中提取真实素材

类型 示例 要求
真实数据 "Gartner 2026 Q1 报告xx 市场规模达 xx 亿" 具体来源 + 具体数字
真实引述 "a16z 合伙人 Alex Immerman 在最近一篇文章中写道..." 具名人物 + 出处
真实案例 "Klarna 在 2024 年公开表示AI 已替代 700 个客服岗" 公司名 + 可验证事件
真实对比 "美国企业人均软件支出 $868中国只有 $20" 来源明确的对比数据

目标:收集 5-8 条真实素材。这些素材将在 Step 4 写作时作为必须引用的锚点嵌入文章。

降级:如果 WebSearch 无法获取有效结果,用 LLM 的训练数据中可验证的公开信息(具名公司、具名人物、公开事件)。但禁止编造虚假的数据/引述/案例——宁可少一个数据点,不可多一个假数据点。

将素材整理为结构化列表,传递给 Step 4。


Step 4: 文章写作

读取: {skill_dir}/references/writing-guide.md
读取: {skill_dir}/playbook.md如果存在
读取: {skill_dir}/history.yaml读取最近 3 篇的 dimensions 字段)

4a. 维度随机化(写作前必须执行)

从 writing-guide.md 第7层的维度池中执行随机

  1. 对 6 个维度(叙事视角/时间线/主类比域/情感基调/节奏型/论证偏好)各随机选 1 个选项
  2. 从中随机激活 2-3 个维度
  3. 对比 history.yaml 最近 3 篇的 dimensions 记录,如果完全重复则重新随机
  4. 将选中的维度作为硬性写作约束注入后续写作——不是建议,是必须贯穿全文的约束

降级:如果 history.yaml 不存在或为空,跳过去重检查,直接随机。

示例输出

本次激活维度:
- 叙事视角:对话体("有人问我..."
- 主类比域:烹饪
- 节奏型:快慢剧烈交替

4b. 写作

按选定框架 + writing-guide.md 全部 7 层规范 + 激活的维度约束 + Step 3.75 采集的真实素材写文章:

  • H1 标题20-28 字converter 自动提取为微信标题)
  • 字数 1500-2500
  • 按框架大纲组织结构,在金句落点放精炼总结句
  • 不插配图占位符Step 6 自动分析插入)
  • 风格遵循 style.yaml 的 tone、voice、content_style
  • 避开 blacklist
  • 真实素材锚定Step 3.75 采集的 5-8 条真实素材必须分散嵌入文章各 H2 段落中,作为论证的事实基础。不是堆砌引用,而是像"一个读了这些材料的人在写自己的分析"一样自然融入
  • 禁止编造:不要虚构数据、虚构引述、虚构案例。如果某个论点没有真实素材支撑,用个人观点/推理代替,不要伪造
  • 去AI痕迹在此步执行不是写完再改——writing-guide.md 的 7 层规则必须在初稿阶段就全部生效

Playbook 优先:如果 playbook.md 存在,其中的规则优先于 writing-guide.md 的通用规则。比如 playbook 说"从不用问句结尾"而 writing-guide 建议用反问句,以 playbook 为准。playbook 是用户的个性writing-guide 是通用底线。

容器语法可选适合特定内容类型写作时可以使用以下容器块converter 会自动渲染为带样式的 HTML

  • :::dialogue ... ::: — 对话气泡(适合访谈/问答)
  • :::timeline ... ::: — 时间线(适合历程/步骤)
  • :::callout tip/warning/info/danger ... ::: — 提示框(适合重点/警告)
  • :::quote ... ::: — 拉引语(适合金句展示)

不是每篇文章都需要容器语法——只在内容形式契合时使用。

保存到 {skill_dir}/output/{date}-{slug}.md


Step 5: SEO 优化 + 去AI痕迹

读取: {skill_dir}/references/seo-rules.md
读取: {skill_dir}/references/writing-guide.md去AI痕迹部分

对初稿执行:

5a. SEO 优化

  1. 生成 3 个备选标题20-28 字),标注策略
  2. 优化关键词密度(核心词前 200 字出现,全文 3-5 次自然提及)
  3. 生成摘要(≤ 54 个中文字)
  4. 推荐 5 个精准标签
  5. 完读率优化(拆长段、加粗强调、段落悬念)

5b. 去AI痕迹逐层验证关键步骤

按 writing-guide.md 的自检清单逐项检查终稿,每一项都必须通过

  1. 真实信息锚定(最重要):每个 H2 段落至少锚定 1 条来自 Step 3.75 的真实素材。没有纯 LLM 自由生成的段落。所有数据/引述/案例可验证,零编造
  2. 词汇层:全文搜索禁用词表 → 命中数必须 = 0。检查词汇温度分布是否覆盖冷/温/热/野至少 3 种
  3. 句法层:确认全文破句/不完整句 ≥ 3 处,无连续 3 句同结构
  4. 信息密度层:确认高密度段后跟低密度段,无连续均匀信息密度
  5. 连贯性打破层:确认至少 1 处跑题再拉回,无每段首句都承接上段
  6. 具体性注入层:每 500 字至少 2 处具体细节(时间/地点/人物/非整数数字)——必须是真实的
  7. 情绪真实感层确认情绪弧线有起伏≥1 高点 + ≥1 犹豫点),无全文平铺
  8. 维度随机化层:确认 Step 4a 选中的维度贯穿全文,不是只出现一两次
  9. 段落节奏:无连续 2 个长度接近±20字的段落

如果任何一项不通过:定位具体段落,针对性重写该段落(不要全文重写),然后重新检查该项。如果同一段落重写 3 次仍不通过,标注该项跳过,继续流程。

覆盖保存终稿。自动模式下选评分最高的标题作为最终标题。


Step 6: 视觉AI

如果 Step 0 设置了 skip_image_gen = true → 跳过 6b只执行 6a 生成提示词,输出供用户手动生成。

读取: {skill_dir}/references/visual-prompts.md

6a. 分析文章 + 生成提示词

读取终稿,分析结构:

  • 提取 H2 标题和各论点段落
  • 逐个论点判断是否需要配图(数据/场景/转折处优先,纯观点段可不配)
  • 确定配图位置和画面描述
  • 约束:总数 3-6 张间隔≥300字不在开头和 CTA 处配图

生成封面 3 组创意(直觉冲击/氛围渲染/信息图表)+ 内文配图提示词。

  • 自动模式(默认):直接用创意 A 作为封面,全部配图直接生成,不停顿。
  • 交互模式:输出方案,等用户确认或调整。

将占位符 ![配图:场景描述](placeholder) 插入 Markdown。

6b. 自动生图

# 封面2.35:1 微信封面比例)
python3 {skill_dir}/toolkit/image_gen.py \
  --prompt "{封面提示词}" \
  --output {skill_dir}/output/{date}-cover.png \
  --size cover

# 内文配图16:9 横版)
python3 {skill_dir}/toolkit/image_gen.py \
  --prompt "{配图提示词}" \
  --output {skill_dir}/output/{date}-img{序号}.png \
  --size article

# 可通过 --provider 覆盖默认 providerdoubao/openai

生成后替换 Markdown 中的 placeholder 为实际图片路径。

降级:如果 image_gen.py 报错,输出提示词供用户自行生成,继续后续步骤。


Step 7: 排版 + 推送草稿

如果 Step 0 设置了 skip_publish = true → 直接走降级路径(本地 HTML preview不要尝试推送。

读取: {skill_dir}/references/wechat-constraints.md排版时参考微信平台限制

Converter 自动处理(不需要手动干预,了解即可):

  • 中英文自动加空格CJK-Latin spacing
  • 加粗标点外移(微信渲染 bug 修复)
  • <ul>/<ol><section>(微信原生列表不稳定)
  • 外链自动转编号脚注 + 文末参考链接(微信屏蔽外链)
  • 暗黑模式 data-darkmode-* 属性注入
  • ::: 容器语法自动渲染
python3 {skill_dir}/toolkit/cli.py publish {markdown_path} \
  --cover {cover_path} \
  --theme {style.yaml 的 theme} \
  --title "{最终标题}"

如果有 cover 就加 --cover,没有就不加。

降级:如果 publish 失败或 skip_publish = true,改用 preview

python3 {skill_dir}/toolkit/cli.py preview {markdown_path} \
  --theme {theme} --no-open -o {skill_dir}/output/{slug}.html

告知用户本地 HTML 路径。


Step 7.5: 写入历史

不管是推送成功还是走了降级路径,都要写入历史。{skill_dir}/history.yaml 追加记录:

- date: "{今天日期}"
  title: "{最终标题}"
  topic_source: "热点抓取"  # 或 "用户指定"
  topic_keywords: ["{关键词1}", "{关键词2}"]
  framework: "{使用的框架类型}"
  word_count: {实际字数}
  media_id: "{media_id}"  # 降级时为 null
  dimensions:  # Step 4a 实际选中的维度
    - "{维度1}: {选项}"
    - "{维度2}: {选项}"
    - "{维度3}: {选项}"
  stats: null  # 由 fetch_stats.py 后续回填

这条记录会被下次运行的 Step 2.5 读取,用于选题去重和偏好分析。


Step 8: 回复用户

成功

  • 最终标题 + 2 个备选标题
  • 摘要
  • 5 个推荐标签
  • media_id
  • 提醒:请到公众号后台草稿箱检查并发布

部分成功

  • 列出每步状态(成功/跳过/失败)
  • 附上本地文件路径
  • 说明哪些需要用户手动完成

用户可以继续要求

  • "帮我润色/缩写/扩写/换语气" → 编辑文章
  • "封面换暖色调" → 修改提示词,重新生图
  • "第 3 张配图不要了" → 调整 Markdown
  • "用框架 B 重写" → 回到 Step 4
  • "换一个选题" → 回到 Step 3 展示选题列表
  • "看看文章数据" / "效果怎么样" → 执行效果复盘(见下方)
  • "看看有什么主题" / "换个主题" → 运行 python3 {skill_dir}/toolkit/cli.py gallery 打开主题画廊
  • "换成 XX 主题" → 用新主题重新渲染当前文章

Onboard首次设置

触发条件

  • Step 1 发现 style.yaml 不存在
  • 用户明确说"重新设置风格"、"修改配置"

Phase 1: 收集信息(交互式问答)

通过对话收集以下信息,不要一次性列出所有问题——一轮问 1-2 个,像聊天一样:

必问(缺了无法运行):

顺序 问题 对应字段 示例引导
1 你的公众号叫什么名字?主要做什么方向? name + industry "比如'零号AI',做科技/互联网"
2 主要写哪几个方向的内容? topics "比如 AI、产品设计、效率工具"
3 你希望文章是什么风格? tone "专业严肃?轻松有趣?毒舌犀利?像朋友聊天?"

选问(有默认值,用户不答就用默认):

问题 对应字段 默认值
目标读者是谁? target_audience 从 industry 推断
用什么人称写? voice "第一人称,像一个懂行的朋友"
有没有绝对不能出现的词或话题? blacklist
有没有想参考的公众号? reference_accounts
署名写什么? author name 字段值
偏好哪种排版风格?(可运行 gallery 命令预览全部 16 个主题) theme "professional-clean"
封面风格偏好? cover_style 从 industry 推断
有没有固定封面模板? cover_template 不设置

快捷路径

  • 如果用户直接甩了一段描述(如"我做科技自媒体,风格像虎嗅"),直接从中提取所有能提取的字段,只补问缺的
  • 如果用户说"不设置"、"用默认的"、"直接写" → 复制 {skill_dir}/style.example.yamlstyle.yaml,跳过所有问答
参考: {skill_dir}/references/style-template.md字段说明和可用主题列表

Phase 2: 生成配置

用收集到的信息自动生成 {skill_dir}/style.yaml

同时确保以下文件/目录存在(不存在则创建):

  • {skill_dir}/history.yaml → 初始化为 articles: []
  • {skill_dir}/corpus/ → 空目录
  • {skill_dir}/lessons/ → 空目录

生成完成后,把 style.yaml 的内容展示给用户看一遍,问"这个配置 OK 吗?有什么要改的?"。用户确认后继续。

Phase 3: Playbook可选不阻断

问用户:"你有没有之前写过的公众号文章?如果有 20 篇以上,我可以从中学习你的写作风格,以后写出来的文章会更像你。"

  • 用户有语料 → 告知将文章(.md 或 .txt放入 {skill_dir}/corpus/,然后运行:

    python3 {skill_dir}/scripts/build_playbook.py
    

    按脚本输出逐批阅读文章,提取风格特征,生成 playbook.md

  • 用户没有语料 / 暂时不想弄 → 完全正常,跳过。告知用户:"没问题,先用通用风格写,后续你可以随时说'学习我的修改'来让我逐渐适应你的风格。"

Phase 4: 试跑

Onboard 完成后,问用户:"配置好了,要不要现在试写一篇?"

  • → 回到 Step 1执行完整流程
  • → 告知用户下次如何触发:"下次直接说'写一篇公众号文章'就行"

效果复盘

当用户问"文章数据怎么样"、"效果复盘"、"看看表现"时:

python3 {skill_dir}/scripts/fetch_stats.py --days 7

脚本会:

  1. 调微信数据分析 API 拉取最近 7 天的文章阅读数据
  2. 匹配 history.yaml 中的文章记录
  3. 回填 stats 字段(阅读量、分享量、点赞量、阅读率)

回填后,分析数据并给出建议:

  • 哪篇文章表现最好?为什么?(标题策略?选题热度?框架类型?)
  • 哪篇表现不好?可能的原因?
  • 对后续选题/标题/框架的调整建议

这些分析会影响下次运行时 Step 2.5 的偏好参考。


学习人工修改

当用户说"我改了,学习一下"、"学习我的修改"时:

1. 获取 draft 和 final

  • draftoutput/ 下最新的 .md 文件
  • final用户提供修改后的版本粘贴或指定文件路径

2. 运行 diff 分析

python3 {skill_dir}/scripts/learn_edits.py --draft {draft_path} --final {final_path}

3. 分析并记录

读取脚本输出的 diff 数据,对每个有意义的修改分类:

  • 用词替换AI 用了"讲真",人工改成"坦白说"
  • 段落删除:人工觉得某段多余
  • 段落新增:人工补充了 AI 没写的内容
  • 结构调整H2 顺序或分段方式的变化
  • 标题修改:标题风格偏好
  • 语气调整:整体语气的偏移方向

将分类结果写入 lessons/ 下的 diff YAML 文件的 edits 和 patterns 字段。

4. 自动触发 Playbook 更新

每积累 5 次 lessons脚本会提示更新 playbook

python3 {skill_dir}/scripts/learn_edits.py --summarize

读取所有 lessons找出反复出现的 pattern≥2 次),将其固化到 playbook.md 的对应章节。


错误处理

不要因为任何一步失败就停止整个流程。

步骤 降级
环境检查Step 0 逐项引导修复,设置降级标记,不阻断可降级的部分
热点抓取失败 WebSearch 替代
选题为空 请用户手动给选题
SEO 关键词查询失败 回退到 LLM 判断
维度随机化Step 4a history.yaml 为空或损坏时跳过去重,直接随机
去AI验证Step 5b 同一段落重写 3 次仍不通过,标注跳过该项,继续
封面/配图生成失败 输出提示词,用户自行生成
推送失败 生成本地 HTML手动操作
历史写入失败 警告但不阻断流程
效果数据拉取失败 告知用户可能需要等 24h微信数据有延迟
Playbook 不存在 正常——用 writing-guide.md 通用规则