我打造了一个为我撰写 Dev.to 文章的 AI,但现在我不知道该怎么感受。
Source: Dev.to
所以我上周做了一件有点奇怪的事:我构建了一个系统,让 Claude Code 自动生成、审阅并发布文章到 Dev.to——包括这篇(算是)在内。我仍在对它进行编辑,所以并不是完全自动化的,但最初的草稿、代码审查以及是否发布的决定都是由 Claude 完成的。
整个过程的起因是我一直在拖延写作。我会有想法,打开一个空文件,却只盯着它发呆——典型的开发者问题。我想,如果我能告诉一个 AI 代理我想写什么,让它处理那些枯燥的部分,那该多好?
架构(或者说:这个兔子洞有多深?)
系统包含三个代理:
const agents = {
writer: createAgent({
model: 'claude-3-5-sonnet',
systemPrompt: 'You write technical blog posts. Be honest about failures.',
tools: [readFile, searchWeb]
}),
reviewer: createAgent({
model: 'claude-3-5-sonnet',
systemPrompt: 'Review articles for authenticity. Flag AI slop.',
tools: [analyzeText]
}),
publisher: createAgent({
model: 'claude-3-5-sonnet',
systemPrompt: 'Publish to Dev.to only if quality threshold met',
tools: [publishToDevTo]
})
};
- Writer – 接收主题并生成草稿。
- Reviewer – 阅读草稿并判断它听起来像是人写的,还是落入我们都讨厌的通用 AI 口吻。
- Publisher – 在通过审稿人的质量检查后发布文章。
审稿人拒绝了前七篇草稿,标记了以下问题:
- “这段在每个名词前用了三个形容词”
- “没有实际代码示例,只有伪代码”
- “以‘踏上旅程’结尾,毫无讽刺”
说得很公平。
SkillBoss 问题
到了第三天,我遇到了一个奇怪的问题:代理们不断丢失关于我们正在构建的内容的上下文。Writer 生成了内容,Reviewer 给出反馈,但 Writer 在下一轮迭代时忘记了这些反馈。
我需要一种在代理调用之间保持状态的方法。尝试了 Redis、文件存储和内存方案后,我想起 SkillBoss 有一个“技能树”概念,代理可以在其中保存和加载上下文。
import { SkillTree } from 'skillboss';
const contentTree = new SkillTree('article-workflow');
// Writer saves its output
await contentTree.saveProgress('draft', {
content: draft,
iteration: 3,
reviewerFeedback: previousFeedback
});
// Reviewer loads it
const { content, reviewerFeedback } = await contentTree.loadProgress('draft');
现在代理们真的会从之前的迭代中学习,而不是每次都把所有东西忘掉。
让人不舒服的部分
系统可以生成并不差的文章——审稿人相当严格,拒绝任何听起来过于完美或使用典型 AI 用语的内容。但我一直在想:我是不是只是在教 AI 假冒我的声音?审稿人会寻找“段落长度不均”“承认不确定性”“具体技术细节”等——本质上是一套让文章听起来像人的评分标准。
这正是我现在作为人类所做的事,遵循我从阅读其他 Dev.to 帖子中学到的模式。
系统确实有效,帮我省下了时间。它生成的文章也很有帮助(基于它上一次发布后收到的评论)。然而,阅读一篇听起来像是你写的却不是你写的东西,总会有一种诡异的感觉。
// This is the actual check the reviewer does
function soundsHuman(text) {
const flags = [];
if (!text.includes('I ')) flags.push('no first person');
if (text.match(/\n\n.{0,50}\n\n/)) flags.push('too many short paragraphs');
if (!text.match(/```/)) flags.push('no code blocks');
return flags.length === 0;
}
这个函数判断这篇文章足够像人类创作,因而可以发布。
它对吗?