从噪音到博客
将任意粗糙输入(要点、语音转录、推文堆、或短篇草稿)打磨成一篇可直接发表的博客文章。文章中的每一条主张都追溯到原始输入或经过 Tavily 验证的研究。
关键规则:不要捏造具体内容。 博客文章中的每一条主张、每个指标、每个例子都必须来自原始输入或 Tavily 搜索结果。绝不可编造数据、引文或结果。
第一步:环境检查
确认所需环境变量已设置:
echo "GEMINI_API_KEY: ${GEMINI_API_KEY:+set}"
echo "TAVILY_API_KEY: ${TAVILY_API_KEY:-未设置,Tavily 增强将被跳过}"
如果缺少 GEMINI_API_KEY: 立即停止,并告知用户:“需要 GEMINI_API_KEY。请从 aistudio.google.com → 获取 API 密钥。然后将其添加到您的 .env 文件中。”
如果缺少 TAVILY_API_KEY: 继续执行,并注明将跳过 Tavily 增强步骤。博客将完全基于用户提供的内容生成。这对于个人故事、经验教学或观点类文章来说是完全可以接受的。
确认输入内容已提供。 用户必须提供以下其中一项:
- 粘贴的文本(要点、粗糙笔记、转录稿、推文堆、短篇草稿)
- 可获取内容的 URL
如果没有输入,请询问:“请分享您的粗糙笔记、要点或转录稿。可以直接粘贴文本,或者提供可获取源内容的 URL。”
第二步:阅读并分析输入
如果输入是 URL: 使用 WebFetch 获取页面内容。提取:标题、作者、发布日期、全部正文、关键统计数据、编号列表、子标题、引用。
如果输入是粘贴文本: 直接阅读。识别输入类型:
- 要点或粗糙笔记:零散的想法、不完整的句子、意识流
- 语音转录:口语化、重复、有填充词(嗯、啊、就是、你知道)、句子松散
- 推文堆:短片段、@提及、话题标签、“1/8”编号
- 短篇草稿:有结构但内容单薄,需要扩充和润色
**质量控制检查点:**在继续之前,明确说明:
- 检测到的输入类型
- 用一句话概括核心论点或主要论据
- 原始内容中最有力的 3-5 个见解、事实或观点
- 任何需要外部验证的主张(基准测试、统计数据、产品对比、研究成果)
如果无法识别核心论点,请询问:“您最希望读者从这篇文章中记住的一件事是什么?”
第三步:选择博客风格
四种风格。根据内容信号自动检测。用户可随时覆盖。
| 风格 | 使用场景 | 信号 |
|---|---|---|
| 技术教程 | 分步指南、操作指南、代码讲解 | 编号步骤、命令、代码片段、内容中含有“如何” |
| 案例分析 | 前后对比故事、构建日志、经验教训 | 具体结果、时间线、第一人称经历 |
| 思想领导力 | 观点、论证、反常识主张 | “我认为”、“X 的问题在于”、对立立场、辩论框架 |
| 解释性文章 | 什么是 X、为什么重要、如何运作 | 概念先行、大量对比、“大多数人不了解” |
检测逻辑:
- 内容有编号步骤或命令 → 技术教程
- 内容有前后对比、具体指标或叙事弧线 → 案例分析
- 内容挑战常识或做出强烈观点主张 → 思想领导力
- 内容向不熟悉的人解释概念、工具或趋势 → 解释性文章
说明所选风格及其理由。如果不明确,选择一个,并注明该选择。
第四步:通过 Tavily 研究增强内容
如果未设置 TAVILY_API_KEY,则静默跳过此步骤。
搜索支持性证据,用于验证原始内容中可能受益于验证或数据支撑的主张。好的搜索候选项包括:
- 产品基准测试或性能数字
- 市场统计数据或行业趋势
- 技术比较(“X 比 Y 快”)
- 用户凭记忆提到但未注明来源的任何数字
每个需要验证的主张执行一次 Tavily 搜索。最多执行 3 次搜索,避免过度依赖外部来源:
curl -s -X POST "https://api.tavily.com/search" \
-H "Content-Type: application/json" \
-d '{
"api_key": "'"$TAVILY_API_KEY"'",
"query": "具体主张或话题",
"search_depth": "advanced",
"max_results": 5,
"include_answer": true
}'
保留评分 >= 0.65 的结果。提取:标题、URL、内容片段。
使用 Tavily 结果的规则:
- 仅在原始输入中已有的主张基础上提供支持或验证。绝不可引入搜索结果中的全新主张。
- 在文本中自然地标明来源:“根据[来源]”、“来自[X]的数据显示”。
- 如果没有 Tavily 结果能确认某个主张,则保持该主张未经验证,而不是用不相关的结果来替代。
第五步:生成博客文章
完整阅读 references/blog-format.md。从 references/output-template.md 中选择匹配的模板。在生成之前内化所有规则。
将 Gemini 请求写入临时文件,以安全处理特殊字符:
cat > /tmp/noise2blog-request.json << 'ENDJSON'
{
"system_instruction": {
"parts": [{
"text": "你是一位听起来像真人一样的科技写作者。规则:只用主动语态。段落要短,每段最多 1-3 行,然后空一行。自然使用缩写(don't, won't, it's, can't, you're, they're)。不要使用破折号——改用逗号或句号。不要使用分号。每个句子都需要一个具体细节:数字、工具名、文件名、命令、结果。不要使用填充语:不要用“在当今快速发展的时代”、“让我们深入探讨”、“值得一提的是”、“总的来说”、“希望这有帮助”。不要使用禁用词:惊人的、令人惊叹的、利用、协同、颠覆性的、革命性的、突破性的、范式、尖端的、无缝的、稳健的、前所未有的、深入的、驾驭、利用、变革性的、开启、全面的、可执行的、关键的、至关重要的。标题不能以“我”、“我的”或“我们”开头。开头要使用一个钩子段落,不要直接宣告主题。结尾要给出具体可行的建议。不要捏造源材料中不存在的观点、指标或结果。"
}]
},
"contents": [{
"parts": [{
"text": "RAW_CONTENT_AND_INSTRUCTIONS_HERE"
}]
}],
"generationConfig": {
"temperature": 0.7,
"maxOutputTokens": 4096
}
}
ENDJSON
将 RAW_CONTENT_AND_INSTRUCTIONS_HERE 替换为:
- 原始输入内容
- 博客风格和结构说明(来自所选模板)
- 在第四步中收集的任何 Tavily 研究结果
- 字数目标:800-1800 字
发送请求:
curl -s -X POST \
"https://generativelanguage.googleapis.com/v1beta/models/gemini-2.0-flash:generateContent?key=$GEMINI_API_KEY" \
-H "Content-Type: application/json" \
-d @/tmp/noise2blog-request.json \
| python3 -c "import sys,json; d=json.load(sys.stdin); print(d['candidates'][0]['content']['parts'][0]['text'])"
同时生成:
- (B) 用于 SEO 预览的 1-2 句元描述
- (C) 一个使用不同切入角度的备选标题
第六步:自我检查
在展示之前,运行每一项检查并修正违规:
- 标题不以“我”、“我的”或“我们”开头
- 标题具体且口语化(不是“关于 X 的全面指南”或“Y 终极指南”)
- 开头段落用钩子吸引读者,而非直接宣告主题(“在这篇文章中我将……”)
- 每一行都没有破折号
- 没有分号
- 每段不超过 3 行,且段后有空行
- 没有禁用词:令人惊讶的、令人惊叹的、利用、协同、颠覆性的、革命性的、突破性的、范式、尖端的、无缝的、稳健的、前所未有的、深入的、驾驭、利用、变革性的、开启、全面的、可执行的、关键的、至关重要的
- 没有编造的数据:每一条主张都追溯到原始输入或 Tavily 结果
- 文章不以“总的来说”、“综上所述”或“希望这有帮助”结尾
- 字数在 800-1800 之间(说明字数)
- 逻辑流程:开头 → 问题/背景 → 主体部分 → 可操作的结尾
在展示之前修正任何违规。说明最终字数。
第七步:输出
将完整的博客文章放在一个代码块中展示。
在博客文章下方展示元描述和备选标题。
询问:“准备好复制到您的编辑器了吗?如果您要发布到特定平台,请告知,我可以为您格式化 frontmatter。”
平台特定请求:
Ghost:
---
title: "文章标题"
date: YYYY-MM-DD
tags: [标签1, 标签2]
status: draft
---
dev.to:
---
title: 文章标题
description: 元描述
tags: [标签1, 标签2, 标签3]
published: false
---
Substack:以纯 Markdown 呈现。Substack 的编辑器可直接导入 markdown。
Hashnode:
---
title: 文章标题
subtitle: 元描述
tags: [标签1, 标签2]
---