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

549 lines
22 KiB
Markdown
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.

---
name: wewrite
description: |
微信公众号内容全流程助手:热点抓取 → 选题 → 框架 → 写作 → 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.yaml``config.yaml`
2. 必填:`wechat.appid` + `wechat.secret`(推送草稿箱需要)
3. 可选:`image.api_key`AI 生图需要,不配也能跑,只是跳过生图)
4. 提供命令:`cp {skill_dir}/config.example.yaml {skill_dir}/config.yaml`
5. **如果用户说"先不配微信"** → 设置降级标记 `skip_publish = true`,继续流程
#### 0b. Python 依赖
```bash
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 是否存在
```
- **存在** → 读取,提取:`name`、`topics`、`tone`、`voice`、`blacklist`、`theme`、`cover_style`、`author`、`content_style`
- **不存在** → 进入 Onboard 流程(见下方章节),完成后回到此处继续
如果用户直接给了选题(如"写一篇关于 AI Agent 的公众号文章"),跳过 Step 2-3直接进入 Step 3.5。
---
### Step 2: 热点抓取
```bash
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 评分:
```bash
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 的自检清单逐项检查终稿,**每一项都必须通过**
0. **真实信息锚定**(最重要):每个 H2 段落至少锚定 1 条来自 Step 3.75 的真实素材。没有纯 LLM 自由生成的段落。所有数据/引述/案例可验证,零编造
1. **词汇层**:全文搜索禁用词表 → 命中数必须 = 0。检查词汇温度分布是否覆盖冷/温/热/野至少 3 种
2. **句法层**:确认全文破句/不完整句 ≥ 3 处,无连续 3 句同结构
3. **信息密度层**:确认高密度段后跟低密度段,无连续均匀信息密度
4. **连贯性打破层**:确认至少 1 处跑题再拉回,无每段首句都承接上段
5. **具体性注入层**:每 500 字至少 2 处具体细节(时间/地点/人物/非整数数字)——必须是真实的
6. **情绪真实感层**确认情绪弧线有起伏≥1 高点 + ≥1 犹豫点),无全文平铺
7. **维度随机化层**:确认 Step 4a 选中的维度贯穿全文,不是只出现一两次
8. **段落节奏**:无连续 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. 自动生图
```bash
# 封面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-*` 属性注入
- `:::` 容器语法自动渲染
```bash
python3 {skill_dir}/toolkit/cli.py publish {markdown_path} \
--cover {cover_path} \
--theme {style.yaml 的 theme} \
--title "{最终标题}"
```
如果有 cover 就加 `--cover`,没有就不加。
**降级**:如果 publish 失败或 `skip_publish = true`,改用 preview
```bash
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` 追加记录:
```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.yaml``style.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/`,然后运行:
```bash
python3 {skill_dir}/scripts/build_playbook.py
```
按脚本输出逐批阅读文章,提取风格特征,生成 `playbook.md`
- **用户没有语料 / 暂时不想弄** → 完全正常,跳过。告知用户:"没问题,先用通用风格写,后续你可以随时说'学习我的修改'来让我逐渐适应你的风格。"
### Phase 4: 试跑
Onboard 完成后,问用户:"配置好了,要不要现在试写一篇?"
- **是** → 回到 Step 1执行完整流程
- **否** → 告知用户下次如何触发:"下次直接说'写一篇公众号文章'就行"
---
## 效果复盘
当用户问"文章数据怎么样"、"效果复盘"、"看看表现"时:
```bash
python3 {skill_dir}/scripts/fetch_stats.py --days 7
```
脚本会:
1. 调微信数据分析 API 拉取最近 7 天的文章阅读数据
2. 匹配 history.yaml 中的文章记录
3. 回填 stats 字段(阅读量、分享量、点赞量、阅读率)
回填后,分析数据并给出建议:
- 哪篇文章表现最好?为什么?(标题策略?选题热度?框架类型?)
- 哪篇表现不好?可能的原因?
- 对后续选题/标题/框架的调整建议
这些分析会影响下次运行时 Step 2.5 的偏好参考。
---
## 学习人工修改
当用户说"我改了,学习一下"、"学习我的修改"时:
### 1. 获取 draft 和 final
- draft`output/` 下最新的 .md 文件
- final用户提供修改后的版本粘贴或指定文件路径
### 2. 运行 diff 分析
```bash
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
```bash
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 通用规则 |