使用 Agent 编写个性化文章的一般步骤
使用 Agent 编写个性化文章的一般步骤
- 本文的结论和观点主要来自 Claude Code + DeepSeek V4 Pro 组合的使用体验
- 受限于出发视角,本文的内容可能只适用于工科尤其是只涉及到软件的结构化文本写作,但其它用途的写作可参考
目前流行的这些 Coding Agent 的能力大都不仅限于泛泛的“写代码”上,而包含几乎所有与文件相关的操作,例如读取、写入、编辑、探索目录结构、理解项目等。这些能力具体取决于 agent 框架背后使用的实际模型。通常只要模型是 general(而非 coding 专用、coder model)的,它便可以进行日常的文书工作。
使用 agent 来编写文章,简单来看,也是一个典型的使用提示词让模型给出相应产出的过程。只不过若想要让 agent 能够给出令人满意、符合要求乃至符合我们个人写作风格的结果,并尽可能解放我们自己的时间,我们需要对文章的一般编写流程有较为全面的理解。
如果你认为这些定制的步骤都没有必要,那么或许更适合处理你当前任务的是免费的网页版 AI,它们可以帮助你完成较简单的文书工作。
目录
大纲(OUTLINE.md)
已有大纲
如果大纲已经提供,例如某个课程的报告模板,我们可以使用这些大纲作为基础,编写适合 AI 的大纲。以某课程的大纲内容为例,该大纲的内容指示学生按照规范编写报告的内容,但不建议直接将这一大纲的内容抛给 AI,因为其中包含一些与我们最终文章无关的信息(见斜体部分)以及有待确定的信息。
- 系统概述:请描述系统的主要功能以及设计要求。若为团队项目,需要在这部分描述本人负责的子模块的功能定位、业务流程及核心技术难点。
- 系统设计:请综合运用文字、表格、图等方式,详细描述系统的功能模块设计、数据库设计、用户界面设计的思路。
- 系统实现:请以图或表格的方式给出应用程序的环境配置、运行说明、项目结构说明,并结合项目结构详细描述系统功能模块的实现过程。
- 系统测试:请给出测试用例、运行结果与运行情况分析(可以用截图的方式描述)。
- 总结与体会:请对本课程及大作业进行总结。总结内容可记录大作业的开发亮点、不足及未来优化方向,以及课程学习体会。
- 附件:报告的可选部分。可以在此部分附上主要模块的核心源代码及详细注释。
我们应该提供给 AI 的,是我们在阅读这份大纲之后,脑海里规划出的具体实施步骤。例如第一步给出了个人完成与团队完成时该部分的内容,如果我们是个人完成,那么就应该删掉与团队相关的要求,以此类推。这样,第一步就简化为
请描述系统的主要功能、设计要求以及实现目标。
第二步、第三步的内容较为具体,需要我们根据具体的代码实现进行改编、拓展或是删减。例如,如果我们不希望这个过程中出现表格,那么就不应该将表格包含在可选的方式中,而不是先说综合运用表格,再说不要用表格。如果在代码实现的过程中没有明确的规划,而原有的要求中包含了一定的框架结构,直接沿用也可以。
第四步的系统测试关乎实际的运行效果,我们不能简单地说“请给出测试用例、运行结果与运行情况分析”,这种情况下生成出来的内容大部分是幻觉驱使(illusion-driven)的,与实际的运行效果脱节且难以验证。像这种与实际关联紧密的内容,需要与具体的系统实现关联起来。
以系统测试为例,其本身有一套非常完善的步骤和方法。我们可以让模型自己去编写集成测试、单元测试或者生成测试数据,这样模型就有了与实际测试衔接的桥梁,从而有了编写依据。像端到端测试、界面的测试这类较为复杂、涉及用户交互的测试,在模型能力和 agent 框架可能无法实现的情形下,可能需要我们自己去进行,但可以让模型列出测试的步骤。
假设我们已经让模型生成了测试用例,可以在这里直接指明。
给出测试用例、运行结果与运行情况分析(用截图的方式描述)。测试用例可以参考backend/seed_data.py。
第五步是总结与体会,其中的体会环节与个人的体验相关,我们通常希望模型达到的效果是以我们自己的口吻去编写体会,这就涉及到模型的知识和经验与我们个人的知识和经验可能不匹配的问题,一般的解决方法是让模型贴合上文所编写的内容进行总结和编写体会,而不是深入到流程的深处。这一部分的内容通常可以写得很浅略。
在原先的提示词内容后面加上对紧贴正文内容的要求。
... 这部分需要紧贴正文内容,使用套话即可,不需要过于深入。
第六步是附件,这部分的要求很宽泛,留给我们自己发挥的空间很大。我们需要根据自己项目的内容来决定要在这里包含什么内容。
这一部分挑选模块的核心源代码(可以扩展:哪些功能模块的源代码?多少块源代码?...),加上详细注释,以供老师参考。
没有大纲
没有大纲的情况下,为了编写的效果,我们最好创建一个大纲,也就是做 plan。较为原始的方法是我们自己来编写这个大纲(plan)让大模型去实现,相当于是一个比较全面和完整的提示词,这一部分的编写方法因人和项目而异,在此省略。我们也可以让模型生成大纲。
对于有着明确要求的内容,我们可以将这些要求作为大纲的基础依据,加上一些具体的实现细节、字数要求等,并允许模型在拟定大纲的过程中参考具体的实现(关键,让模型给出符合实际的大纲内容)。最后让模型将大纲输出到本地 Markdown 文件中。
我现在要完成一篇论文,内容的要求是:
...
我的选题是...,该选题结合了...,目标是...,项目的主要实现位于 @impl/ 目录下面。
现在我需要你帮我拟定论文的大纲。其字数应当为4000字左右。
一个完整的大纲至少需要包含题目本身的介绍或者引入,正文实现,结论与最后的总结心得体会等。
请你将拟定好的大纲写入到./essay-outline.md中
以上提示词有一个问题:没有给出大纲应当包含的内容的具体范围。的确,我们不了解大纲具体应该包含什么内容,这正是我们需要模型帮我们生成大纲的原因;我们不能陷入一个为了大纲而列大纲的大纲的循环。为了方便,我们可能会倾向于给出一个较大的范围,例如让模型去读取整个 impl 实现目录的完整代码。在这种情况下,模型在探索了较多的上下文信息后,生成的大纲或者根据大纲生成的文章往往会出现过于全面和冗长的问题,字数的要求不能起到实质性的作用(例如你要求 4000 字,最终输出的内容也有可能超过 10000 字)。
这就需要我们审阅模型输出的大纲内容,去掉或者替换掉其中我们不需要的信息(或者我们也可以给出要求,让模型自行修改大纲)。这一步骤是自然且必要的,它让我们对大纲的拟定步骤保持为线性的而不是嵌套的。
当然,如果我们对项目的理解较为全面,我们也可以在模型生成大纲之前就在提示词中指出要包含的各个模块。在提供了足够的信息后,这部分的不确定性就可以被消除掉。
以上方法与做 plan 的过程非常类似,适合一些较为大型或者需要细致调整的文章的编写操作;这一方法强调我们自己对大纲的调整,大模型作为辅助。
对于一些较为简单的编写需求,则不需要大费周章地将大纲写入到本地文件中再去做调整。我们直接使用 agent 框架提供的 plan mode 即可进行:让模型像一般写代码做 plan 那样,在 plan 中给出文章的大纲。审核后,我们直接用提示词给出大纲的更改需求,让模型更新 plan,直到满意为止。最后 auto accept 实施 plan(开始编写)。
风格文档(STYLE.md)
为了降低模型输出内容的“AI 味”,我们需要指示 AI 主动减少其输出文本中 AI 常见的一些特征。这一点不仅仅是为了减少文档在观感上与AI的关联性,更是提升文档可读性的一个必要的措施——某些 conversational LLM 在未经过任何定制输出的长篇文本内容的可读性、严谨性均一般,因为其往往倾向于引入较多的列表格式与 Emoji,信息密度较低。
除了解决输出内容不严谨、信息密度低的问题外,风格文档还可以让我们进一步定制文章的叙述风格和措辞习惯。将一些我们过往的写作材料交给 AI 提取其中的风格,可以让模型直接模仿我们的写作风格(当然这个模仿的效果可能很一般)。
“AI味”的来源
以 DeepSeek 为例,其输出的文本的“AI 味”的来源大概有下面这些方面:
-
倾向于使用有序列表、无序列表。
有序列表和无序列表,尤其是无序列表,是正式的文档中不太常用的格式,它们更像是 Markdown 用来对应 HTML 中
<ul>和<ol>标签的排版元素。对于一个专注于叙述而非快速呈现想法的文章,频繁使用这两种格式会破坏文档的正式性和严谨性。用来代替这两者的可以是来自语言本身的一些句式和朴素的列表排版。这两者代替有序列表和无序列表的目的都是让文章的结构变得更加扁平,而不会出现突兀的列表项前缀图表或是缩进。
-
语言句式
语言中带有序数词的句子已经可以充当有序列表的作用:首先...其次...再次...最后;一是...二是...三是...最后是;第一点是...第二点是...还有...最后...;Firstly ..., Secondly ..., Thirdly ..., Finally ..., Last but not the least ...;...
对于无序列表,代替它的可以是分号或者排比句。
关于汉语中分号的具体用法,可以参考:
- 《論分號的定義和用法》https://www.cuhk.edu.hk/ics/clrc/crcl_80/zhong.pdf
- 如何简洁易懂地解释汉语中分号的用法? - 知乎 https://www.zhihu.com/question/49619188
- 百度百科 https://baike.baidu.com/item/%E5%88%86%E5%8F%B7/998579
-
朴素的列表排版
朴素的列表排版与有序列表类似,但没有引入额外的结构和缩进。这种方法将括号和表示数字的符号放在一段的开头来表示一个列表项。其效果类似于下面的 Word 文档排版形式(用
 来表示一个汉字的宽度)。  (1)... ... ...   (2)... ... ...   (3)...(1)、(2)、(3)还可以替换为(一)、(二)、(三)或(I)、(II)、(III)等。
-
-
在文章的一些词语或句子上添加粗体样式。
在较正式的文章的段落内部如无特殊需要,不应该出现粗体样式。粗体样式只应会出现在一些正文中的关键词、特别强调句和标题中,且会使用黑体等专门的字体来代替原字体的粗体字重。
即使不是在正式的文章中,减少粗体的使用也是值得的。粗体往往让一个句子的关注点变得模糊不清,会给人一种“这个地方是重要的”而“那个地方不重要”的暗示,但实际上往往饱含粗体的段落的内容整体都很重要。
-
过度使用破折号和冒号。
破折号和冒号都有一类用于引出下文、解释说明的用法,正是因为这一点,往往会出现先摆结论然后引出具体内容的句式。这种句式虽然通顺,但是在人类编写的情况下较为少见,且多数时候是用来表示强调的。这种句式本身也自带一种蜿蜒、顿挫感,可能降低文章的严肃性。
冒号也有类似的问题。
-
过度使用比喻。
在某些情况下,模型会选择一个较为少见的比喻来尝试形象地说明一个概念。这种比喻通常不够自然也没有必要。过度使用比喻的典型特征是模型用双引号包围一个你可能几乎没有见过或者想到过的词语来形容一个前文中的概念。
-
不正式的符号使用、中英文混杂、不恰当地使用某类句式或词语(往往发生在国外训练的模型)等。
对于中英文混杂这个问题,在部分场景下可能可以接受,因为一些词语确实不需要强行翻译为中文。但在较为严肃严谨的写作中,中英文混杂往往无法接受,一个解决的方法是先放其汉语词语,然后加上一个括号标注英文,从而澄清这个概念是来自于英文而非中文的原始词。
不正式的符号使用在这里指的一些正式写作中几乎不会用到的符号组合,例如用来表示组合关系的“Python 3.14+Flask”中的加号,应当用汉字“和”来代替。
不恰当地使用某类句式或词语,问题主要分为(这些问题可以组合地发生)
- 频繁重复使用某类句式,例如“不是...而是...”、“是...而不是...”
- 语气节奏突兀不自然,例如“恰好...”、“做...(某个动作或操作)”、“直接...(某个动作或操作)”、过于急促的“A并B”
- 罕见或不符合语境的词语,例如“分野”、“收口”、“兜底”等
-
手动中西文间距
模型在中文与西文、数字之间加上空格来表示中西文在排版时的间距。实际上,任何成熟的排版引擎,例如 Word、TeX,均有该考虑,而不需要多余的空格。
需要注意的是 HTML 排版引擎并没有这样的考虑,因此你在本文以及过往的所有文章中看到的均为(真正的)手动中西文间距。这样做的目的是让文章更为正式。
自然段叙述与格式定制
让模型能够以一个适合篇幅文章的形式输出的最重要的提示词要素是提醒其使用自然段进行输出,而不是像询问生活小妙招一样这里列举几条,那里解释几条。在这里我们可以参考 Claude Blog Best practices for prompt engineering 这篇文章中提到的一个提示词
I prefer responses in natural paragraph form rather than bullet points because I find flowing prose easier to read and more conversational. Bullet points feel too formal and list-like for my casual learning style.
自然段叙述的一个目的是让输出的文本更加符合真正文章的格式,使其适合以不同层次标题划分的典型文章结构。为了让模型切换到“散文(prose)模式”,提示词至少需要包含下面的要求:
请你以自然段的形式,自然地分隔不同的话题,西文、数字与中文之间不要带空格。仅在列表确实提高可读性的情况下使用有序或无序列表。
仿照上述思路,我们可以专门点出某一类格式,并给出使用这类格式的条件和要求,例如
-
使模型只有在信息较多、需要对比或呈现数据的情况下给出表格。
使用信息密度较大的表格形式来论述数据的对比或者呈现数据。从而为模型指明何时应该使用表格的依据,以避免模型过度使用表格或者完全不使用表格。
-
让模型充分利用 Markdown 格式来给出图片的占位符以及额外信息。
请你将图片在文章中的题注文本写在alt中。对于尚不存在的图片,请你根据具体叙述的需要,插入占位符,并在这些图片后方用斜体给出图片的具体内容,我稍后会根据这一提示进行补充。以上提示词的意图适合需要截图、实际运行图等需要后续插图的场景:虽然模型不能帮你截图,但可以给出指示。
这里潜在的一个问题是,一些模型可能不会真的根据叙述的需求来设置 placeholder,而只在看似需要的地方象征性地加上一些 placeholder。解决方法是减少这类“后插入”的截图需求,而多使用模型可以直接接触到的方法,例如用 matplotlib 来根据数据构建图表等。
当然,如果你不在意模型为你添加 placeholder 的位置以及上下文衔接,而只在乎有没有的话,就无需管理。模型给出的 placeholder 与上下文至少应该是有逻辑可言的。
机械方式优于生成方式
这是我在使用大模型进行一些文本的操作后的一个体会或者说结论,它的前提是你已经掌握了目标信息的另外一种形式,或者生成该目标信息的材料。
例如,我从微信读书中导出了一本书的 300 条划线笔记,得到了一个一行一句话的纯文本文件(.txt)。现在,我希望让模型帮我根据某个主题,从中抽取出一些句子,放到 extracted.txt 下面。如果只给模型一个简单的“帮我提取关于...” prompt,那么它将以原始的纯文本文件为依据(输入),生成出 extracted.txt 的内容。当数据量过大而导致上下文腐化(context rot)时,它所生成的内容将会受到影响,发生变形、不准确乃至幻觉的情况。
在 DeepSeek V4 Flash 上测试,在提示词中没有给出任何其它条件,而仅表明“提取”的意向时,它所生成的 extracted.txt 中没有一句话遵循了原文。它所输出的内容,更像是一些转述,或者它在读取了原文后的复述。我相信即使在提示词中添加“请原样输出”也无法 100% 避免出现这种现象,而往往这类需求所需要的正是精确。
为了精确,一个更好的方式是使用机械的方式提取,而非让其生成。同样是 DeepSeek V4 Flash,将提示词从“帮我提取”改为“帮我找出相应的句子,并编写脚本将它们提取到...”,它便能生成正确的行号和 Python 脚本,完成精确的提取。这个过程中,模型只是一个执行者,它的依据是原文,生成的是行号而非具体的内容,这就避免了具体内容的变形。从本质上来看,这种方式才是对“提取”这一目的的精确描述。
在上面提到要让模型真的按照自己的叙述节奏为图片留好 placeholder 的需求,似乎是不可能一次性实现的,因为它并不知道自己的叙述节奏是啥物,也不知道你想要“后插入”哪一类图片。但例如,让它根据具体的代码以及代码生成的数据,通过 matplotlib 生成出确定数量的图表然后插入进去,在这个过程中它便能知道这个图表的具体含义,进而给出正确的叙述(即使是无法读图的模型,也可以根据原数据大致复述出图表的大概内容);图表生成的机械过程也确保了图表的正确性。
上文中提到的让模型自行编写测试自行运行,从而编写系统测试这一节的内容也是一种机械优于生成的体现。
- 让模型按照语义要求划分章节。
使用Markdown的一级标题来表示大章节,剩余的小章节依次使用二级、三级标题来表示,最深达到三级。 一级标题格式为1 XXX、2 YYY、3 ZZZ等; 二级标题格式为1.1、1.2、1.3等; 三级标题格式为1.1.1、1.1.2等。 请你根据具体内容的需要划定标题。其中三级标题的划定要十分慎重:只有那些涉及到较多细节,且每一个细节的篇幅较大且可被归类的场景下,才需要划分到三级标题;其余情况下,应当使用一般的自然段进行列举。
行文风格
除了基本的格式,文章还可以有行文风格相关的定制。
适当使用“笔者”、“我们”的正式的叙述口吻,适当拉近距离。但不要使用“我”来进行叙述,避免距离过近。
更进一步地,可以让模型从我们过往写过的文章中总结出一些特质来。需要注意,让AI分析的文章不宜过多,并且建议选择同一个时期编写的文本以确保风格的稳定性(如果你的风格从未变化,则可以忽略)。
1. **真诚**:不假装自己什么都懂,不确定的地方标出来,错了就更新
2. **WHY > WHAT**:解释原因永远比罗列事实重要
3. **有人味**:保持个人风格和幽默感,技术文章不应该是冷冰冰的说明书
4. **渐进**:从简单到复杂,带读者一步步跟上思路
5. **具体**:所有论述都要有具体代码、截图或数据支撑,不空谈
将这些要求保存在一个专门的文件,例如 STYLE.md 中,并在让模型开始实施的提示词中加上参考要求即可。
输出形式
模型原生的输出形式是纯文本、Markdown 或者(La)TeX。
如果我们需要用 Word 进行排版,一个思路是让模型先按照我们给定的格式要求输出到 Markdown 后,再将其粘贴到 Word 中。这个粘贴的过程也是我们审阅和修改模型输出内容的过程。
Markdown 支持我们在 Word 中需要用到的一些主要格式,例如标题、自然段、列表、表格等。
- 表格的内容和格式可能需要我们自行调整
- 行内代码块,根据文章的排版要求而定。通常不会有对于此类项目的排版要求,因此在 Word 排版中不需要特殊设置,也不需要设置成 monospace 字体徒增工作量
- 对于块级代码块,可以用带框线的若干段落表示
- 脚注需要我们让模型按照某种给定格式生成后,自行在 Word 中调整
- 题注、文献引用需要我们让模型生成后,自行在 Word 中插入并进行交叉引用
另外一种思路是直接使用 LaTeX。LaTeX 相比于 Word 更适合 agent 进行操作,因为它的本质是一个文本文件,且模型本身具有 LaTeX 排版语言的知识,除了编写文本外,还可以满足包括字体设置、页面划分、图片宽度设置、表格格式设计、文献引用、公式生成等需求,而标题的编号、图表或代码或公式的交叉引用、脚注等则由 LaTeX 排版引擎根据指令自动处理。但 LaTeX 的排版效果可能更加偏向于学术和正式场景,对于有给定模板或是对版面限制较多的写作可能较难调整。
除了 LaTeX 外,还可以考虑使用 Typst,但为了让模型编写正确的 Typst 代码,可能需要为模型引入一些扩展(如 MCP、Skills),在此就不展开了。
文献管理
不推荐直接让 AI 给出要引用哪些文献,原因至少有二:
- 文献的参考需要根据具体的内容提出,且大部分文献在列大纲的时候就已经确定;
- AI 所使用的文献局限于其世界知识,并且有较大的幻觉驱动概率,即使主动指示 AI 根据内容去搜索文献,也不一定能够找到真正的、适合的文献。对于严肃的学术写作,文献的搜集和阅读是必须经历的一个环节;对于拼凑文献的需求,一个简单的方法是根据文中的一些名词或技术,直接在相关仓库中寻找其对应的论文或技术报告即可,这一步不一定需要 AI 的帮助。
但 AI 可以帮助对文献进行整理。要使用自然语言对 AI 文献格式做出准确的指示,我们必须了解文献的常见格式。可以参考清华大学图书馆的这则帮助文本:https://lib.tsinghua.edu.cn/info/1147/3359.htm
大写的 Markdown 文件的魔力
当我们将一类步骤根据自己的知识拆解并形成文字,进而变为限制(帮助)agent 行动和决策的大框架后,我们似乎就已经发明了自己的“大写 Markdown 文件”也就是 [SOME_WORD_IN_UPPER_CASE__BE_AS_SIMPLE_AS_POSSIBLE__DO_NOT_IMITATE_THIS].md。我们可以根据它的功能将其命名,例如上面的大纲文件我们可以自然地将其称为 OUTLINE.md,文本风格文件我们也可以将其称为 STYLE.md——或许我们可以将其封装到一个文件夹里?加上一些领域限制?黑话?术语?条例?让模型可以自由调用的 helper scripts?我们(大概)发明了 Skills。
总结
本文主要叙述了如何借助现有的 agent 框架提供的目录知识探索、Plan、文件读写能力来实现半自动或全自动的较正式文章内容的编写。通过调整、简化以上步骤,还可以让 agent 输出适合不同场景下或正式或随意的文章或文档内容。总体上的思路是为 agent 提供确切但又不过分的参考,使其可以在我们为其规划的大框架下,自动地完成余下的工作(通常是大头),从而节省我们的个人时间。
既然使用 agent 写作,我们大概率只是希望 agent 能够代替我们进行大部分的工作而不是彻底简化掉自己的所有工作,换句话说,我们希望最终产物中仍然能有我们的想法或构思。所以本文的方法需要一定程度的人的参与,并且对选题以及其背后项目或实现的理解有一定的要求。当然,本文的步骤经过简化之后便没有了这些要求,也足以应付一些较为简单的写作要求,例如项目的 README(其实 README 甚至不需要做 plan);一些指令例如 /init 无需*提示词就可以生成 CLAUDE.md。需要具体情况具体分析。