with one click
wechat-writer
微信公众号正文写作——写作风格指导、正文生成、存档、相似度检查
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Menu
微信公众号正文写作——写作风格指导、正文生成、存档、相似度检查
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
Based on SOC occupation classification
微信公众号 HTML 排版——读取 markdown + media_id 构建 HTML 草稿、执行 create-draft
微信公众号封面和配图生成——封面漫画生成、PIL叠加文字、配图生成、上传微信获取 media_id
微信公众号文章发布总调度——写正文 → 用户确认文字 → 做图 → 用户确认图片 → 发草稿
| name | wechat-writer |
| description | 微信公众号正文写作——写作风格指导、正文生成、存档、相似度检查 |
| triggers | ["写公众号正文","写微信公众号"] |
| env | {"RESEARCH_DIR":"~/.hermes/research/","ARTICLE_HISTORY_FILE":"~/.hermes/research/articles_history.json"} |
👉 "有判断的聊天",而不是"完整的文章"
👉 更高目标:"让读者经历这个道理",而不是"讲道理给他听"
讲知识、讲概念、讲结构——对你没价值。
有经验、有观点、有归纳。但问题:抽象、平、缺画面。
典型症状:满篇"本质是……""核心问题是……""其实是因为……"
有场景、有冲突、有"瞬间"。读者不是"理解",而是"感受到"。
以下句式是"总结层语言",每句都要改:
"本质是……"
"核心问题是……"
"其实是因为……"
"这说明……"
"问题在于……"
每句抽象 → 强制问自己3个问题:
| 时间三层(纵向) | 维度三层(横向) |
|---|---|
| 之前(预期) | 外部(场景/对话) |
| 当下(事件) | 内部(我内心) |
| 之后(反应) | 关系(他们关心什么) |
如:"它们看起来五花八门。/实际上都在补同一件事:/Agent根本不是一个完整系统。"
如:"在那之前,它只是一个会说话的模型"
如:"但记住还不够...问题只是从'忘了'变成'说错了'"
很多人觉得,自动驾驶最难的是技术。
2019年在加州,我们团队100多人,博士占一半,
技术指标跑赢所有人。
三个月推不动一台车。
每一块写进正文前,必须完整思考这五层:
| 层次 | 思考内容 | 写进正文时 |
|---|---|---|
| 背景 | 时间/地点/人物 | 融进第一句 |
| 预期 | 我原本以为 | 融进叙述 |
| 现实 | 实际发生了什么 | 直接写对话/行为 |
| 反差 | 预期 vs 现实 | 融进叙述 |
| 反应 | 那一刻我…… | 直接写感受 |
❌ 错误(正文出现标记词):
【背景】2019年11月,加州,第一次给车厂做演示。
【预期】我以为他们会问准确率。
✅ 正确(标记词全部消失):
2019年11月,加州,第一次给车厂做演示。
我准备了三个月,把所有技术指标都跑通。
总工听完,站起来说——"如果出事,谁负责?"
这不是技术问题。
这是责任结构的问题。
"技术团队最容易犯的错,不是技术不够强。
是做了一堆——
没有人站出来说过'我负责'的东西。"
规则:小标题 = ❶❷❸ + 文章句子,不含框架标记词
❌ 坏的小标题:
✅ 好的小标题(具体短句):
import json, os
HISTORY_FILE = os.path.expanduser("~/.hermes/research/articles_history.json")
NEW_THEME_KEYWORDS = ["主题词1", "主题词2"] # ← 每次替换
history = json.load(open(HISTORY_FILE)) if os.path.exists(HISTORY_FILE) else []
print(f"历史文章共 {len(history)} 篇")
for art in history[-10:]:
themes = set(art.get("themes", []))
tags = set(art.get("tags", []))
new_kw = set(NEW_THEME_KEYWORDS)
overlap = themes & new_kw
if overlap:
print(f" ⚠️ [{art['date']}] {art['title']}: 主题重叠={overlap}")
if len(history) >= 5:
recent_themes = set()
for art in history[-5:]:
recent_themes.update(art.get("themes", []))
theme_overlap = recent_themes & set(NEW_THEME_KEYWORDS)
if len(theme_overlap) >= 2:
print(f"\n⚠️ 近5篇主题重叠≥2,建议先和用户确认换角度再写")
else:
print(f"\n✅ 主题可写")
else:
print(f"\n✅ 历史文章不足5篇,直接写")
判断:近5篇主题重叠 ≥ 2 → 先和用户确认换角度
按以上指南写完正文,保存为 ~/.hermes/research/article_*.md
import json, os, uuid, re
from datetime import datetime
HISTORY_FILE = os.path.expanduser("~/.hermes/research/articles_history.json")
ARTICLE_DIR = os.path.expanduser("~/.hermes/research/")
NEW_THEMES = ["主题词1", "主题词2"] # ← 每次替换
NEW_TITLE = "文章标题"
NEW_FILE = "article_xxx.md"
NEW_WORDS = 0 # 字数
new_entry = {
"id": str(uuid.uuid4())[:8],
"title": NEW_TITLE,
"date": datetime.now().strftime("%Y-%m-%d"),
"tags": [],
"summary": "",
"themes": NEW_THEMES,
"word_count": NEW_WORDS,
"file_path": NEW_FILE
}
history = []
if os.path.exists(HISTORY_FILE):
with open(HISTORY_FILE) as f:
history = json.load(f)
def extract_content(text):
text = re.sub(r'^#+\s+', '', text, flags=re.MULTILINE)
text = re.sub(r'\*\*([^*]+)\*\*', r'\1', text)
text = re.sub(r'---', '', text)
text = re.sub(r'\n{3,}', '\n\n', text)
return text.strip()
def char_bigrams(text):
words = text.split()
bigrams = set()
for i in range(len(words)-1):
bigrams.add(f"{words[i]}_{words[i+1]}")
return bigrams
def load_article(file_path):
try:
return extract_content(open(os.path.expanduser(file_path)).read())
except:
return ""
recent = history[-5:] if len(history) >= 5 else history
print("=== 相似度检查 ===")
for art in recent:
art_file = art.get("file_path", "")
if not art_file:
continue
prev_text = load_article(art_file)
new_text = extract_content(open(os.path.expanduser(NEW_FILE)).read())
if not prev_text or not new_text:
continue
prev_words = set(prev_text.split())
new_words = set(new_text.split())
jaccard = len(prev_words & new_words) / max(1, len(prev_words | new_words))
prev_bg = char_bigrams(prev_text)
new_bg = char_bigrams(new_text)
bg_jaccard = len(prev_bg & new_bg) / max(1, len(prev_bg | new_bg))
theme_overlap = set(NEW_THEMES) & set(art.get("themes", []))
flag = "⚠️" if jaccard > 0.05 or len(theme_overlap) >= 2 else ("⚡" if jaccard > 0.02 else "✅")
print(f" {flag} [{art['date']}] {art['title']}: 词Jaccard={jaccard:.2%} bg={bg_jaccard:.2%} 主题={theme_overlap}")
all_prev = " ".join([load_article(a.get("file_path","")) for a in recent])
if all_prev:
all_prev_words = set(all_prev.split())
new_words_set = set(extract_content(open(os.path.expanduser(NEW_FILE)).read()).split())
overall_jaccard = len(all_prev_words & new_words_set) / max(1, len(all_prev_words | new_words_set))
print(f"\n整体词Jaccard: {overall_jaccard:.2%}")
if overall_jaccard > 0.05:
print("⚠️ 整体相似度偏高 → 返回正文调整角度")
else:
print("✅ 相似度可接受 → 进入封面流程")
else:
print("✅ 无历史文章 → 直接进入封面流程")
history.append(new_entry)
with open(HISTORY_FILE, "w") as f:
json.dump(history, f, ensure_ascii=False, indent=2)
print(f"✅ 已存档: {NEW_TITLE}")
| 指标 | 阈值 | 结果 |
|---|---|---|
| 词集合 Jaccard | > 5% | ⚠️ 返回正文调整角度 |
| 词集合 Jaccard | 2–5% | ⚡ 可接受 |
| 词集合 Jaccard | < 2% | ✅ 直接通过 |
| 主题重叠 | ≥ 2 | ⚠️ 必须调整角度 |
完成后告知用户:
~/.hermes/research/article_*.mdwechat-post-image 生成封面和配图