欢迎光临
我们一直在努力

【Day 18】收官:四个Agent组成编辑部,自动生产文章

摘要

写技术文要选题、调研、写作、审核,一人全包有盲区。本文搭多Agent流水线:选题Agent选题、调研Agent搜素材、写作Agent写稿、审核Agent打分,不通过带反馈回退,文末附18篇知识地图。


你有没有这种经历:写完一篇文章,自己读觉得挺好,发出去才发现逻辑跳跃、论据薄弱、还有错别字。自己审自己的稿子,天然有盲区——你知道自己想表达什么,大脑会自动补全没写清楚的地方。

真实编辑部怎么解决这个问题?记者写稿、编辑审稿,编辑打回让记者改,改完再审。换人审,才能看到盲区。

我们用四个Agent模拟这个流程:

#mermaid-svg-KtezG3RNvwbCvrvu{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-KtezG3RNvwbCvrvu .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-KtezG3RNvwbCvrvu .error-icon{fill:#552222;}#mermaid-svg-KtezG3RNvwbCvrvu .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-KtezG3RNvwbCvrvu .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-KtezG3RNvwbCvrvu .marker{fill:#333333;stroke:#333333;}#mermaid-svg-KtezG3RNvwbCvrvu .marker.cross{stroke:#333333;}#mermaid-svg-KtezG3RNvwbCvrvu svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-KtezG3RNvwbCvrvu p{margin:0;}#mermaid-svg-KtezG3RNvwbCvrvu .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-KtezG3RNvwbCvrvu .cluster-label text{fill:#333;}#mermaid-svg-KtezG3RNvwbCvrvu .cluster-label span{color:#333;}#mermaid-svg-KtezG3RNvwbCvrvu .cluster-label span p{background-color:transparent;}#mermaid-svg-KtezG3RNvwbCvrvu .label text,#mermaid-svg-KtezG3RNvwbCvrvu span{fill:#333;color:#333;}#mermaid-svg-KtezG3RNvwbCvrvu .node rect,#mermaid-svg-KtezG3RNvwbCvrvu .node circle,#mermaid-svg-KtezG3RNvwbCvrvu .node ellipse,#mermaid-svg-KtezG3RNvwbCvrvu .node polygon,#mermaid-svg-KtezG3RNvwbCvrvu .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-KtezG3RNvwbCvrvu .rough-node .label text,#mermaid-svg-KtezG3RNvwbCvrvu .node .label text,#mermaid-svg-KtezG3RNvwbCvrvu .image-shape .label,#mermaid-svg-KtezG3RNvwbCvrvu .icon-shape .label{text-anchor:middle;}#mermaid-svg-KtezG3RNvwbCvrvu .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-KtezG3RNvwbCvrvu .rough-node .label,#mermaid-svg-KtezG3RNvwbCvrvu .node .label,#mermaid-svg-KtezG3RNvwbCvrvu .image-shape .label,#mermaid-svg-KtezG3RNvwbCvrvu .icon-shape .label{text-align:center;}#mermaid-svg-KtezG3RNvwbCvrvu .node.clickable{cursor:pointer;}#mermaid-svg-KtezG3RNvwbCvrvu .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-KtezG3RNvwbCvrvu .arrowheadPath{fill:#333333;}#mermaid-svg-KtezG3RNvwbCvrvu .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-KtezG3RNvwbCvrvu .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-KtezG3RNvwbCvrvu .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KtezG3RNvwbCvrvu .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-KtezG3RNvwbCvrvu .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KtezG3RNvwbCvrvu .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-KtezG3RNvwbCvrvu .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-KtezG3RNvwbCvrvu .cluster text{fill:#333;}#mermaid-svg-KtezG3RNvwbCvrvu .cluster span{color:#333;}#mermaid-svg-KtezG3RNvwbCvrvu div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-KtezG3RNvwbCvrvu .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-KtezG3RNvwbCvrvu rect.text{fill:none;stroke-width:0;}#mermaid-svg-KtezG3RNvwbCvrvu .icon-shape,#mermaid-svg-KtezG3RNvwbCvrvu .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-KtezG3RNvwbCvrvu .icon-shape p,#mermaid-svg-KtezG3RNvwbCvrvu .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-KtezG3RNvwbCvrvu .icon-shape .label rect,#mermaid-svg-KtezG3RNvwbCvrvu .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-KtezG3RNvwbCvrvu .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-KtezG3RNvwbCvrvu .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-KtezG3RNvwbCvrvu :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}

≥7分通过

<7分打回

💡 选题Agent出3个选题

🔍 调研Agent搜素材整理报告

✍️ 写作Agent写初稿

📋 审核Agent四维度打分

📄 输出文章

关键在最后那条回退线:审核Agent不通过时,把具体修改建议反馈给写作Agent重写,而不是默默输出一篇不合格的文章。这就是Day11讲的Reflexion闭环——执行、评估、带反馈修正。

四个Agent各司其职

每个Agent就是一个独立的system prompt,角色不同prompt不同:

import json
from llm_client import LLMClient

class Agent:
def __init__(self, role, llm):
self.role = role
self.llm = llm
def chat(self, msg, json_mode=False, temp=0.7):
if json_mode:
return json.loads(self.llm.chat_json(msg, system_prompt=self.role, temperature=temp))
return self.llm.chat(msg, system_prompt=self.role, temperature=temp)

选题Agent用chat_json返回结构化选题列表,调研Agent用低温度保证素材准确,写作Agent支持首次写和带反馈重写两种模式,审核Agent用最低温度保证打分稳定:

class ContentPipeline:
def __init__(self, max_rewrites=2):
self.llm = LLMClient(provider="glm")
self.max_rewrites = max_rewrites

def run(self, domain):
# 1. 选题:出3个候选,选第一个
topic = self._pick_topic(domain)

# 2. 调研:搜集素材
research = self._research(topic)

# 3. 写作 + 4. 审核(带回退循环)
article = self._write(topic, research)
for attempt in range(self.max_rewrites + 1):
review = self._review(topic, article)
if review["passed"]:
print(f"\\n✅ 审核通过({review['score']}/10),用了{attempt+1}稿")
break
if attempt < self.max_rewrites:
print(f"\\n❌ {review['score']}/10,打回重写:{review['feedback'][:60]}…")
article = self._rewrite(topic, research, article, review["feedback"])
return article, topic, review

max_rewrites=2是安全阀——如果两版都不达标,输出当前最优版本,不无限循环。

选题Agent

def _pick_topic(self, domain):
result = Agent(
"你是选题编辑。根据领域生成3个有吸引力的技术文章选题。",
self.llm).chat(
f'领域:{domain}\\n返回JSON:{{"topics":[{{"title":"标题","angle":"角度","why":"为什么有人看"}}]}}',
json_mode=True, temp=0.8)
topics = result["topics"]
pick = topics[0]
print(f"💡 选题:{pick['title']}")
print(f" 角度:{pick['angle']}")
return pick["title"]

调研和写作

def _research(self, topic):
print("🔍 调研中…")
# search_web是模拟搜索,实际替换为Tavily等真实API
raw = search_web(topic)
return Agent(
"你是调研员。根据搜索结果整理素材:背景、关键数据、主要观点、争议点。",
self.llm).chat(
f"主题:{topic}\\n搜索结果:{json.dumps(raw, ensure_ascii=False)}\\n整理为调研报告。",
temp=0.3)

def _write(self, topic, research):
print("✍️ 写作中…")
return Agent(
"你是技术作家。根据调研素材写文章,结构清晰、有代码示例、不说废话。",
self.llm).chat(
f"标题:{topic}\\n调研素材:{research}\\n写一篇1500字左右的技术文章。")

def _rewrite(self, topic, research, old_draft, feedback):
print("✍️ 根据反馈重写…")
return Agent(
"你是技术作家。根据审核意见修改文章。",
self.llm).chat(
f"标题:{topic}\\n调研素材:{research}\\n旧稿:{old_draft}\\n"
f"审核意见:{feedback}\\n请修改,保留优点,解决反馈中的问题。")

审核Agent:四个维度打分

def _review(self, topic, article):
return Agent(
"你是严格的主编。从切题度、信息量、可读性、原创性四个维度审核文章。",
self.llm).chat(
f'文章标题:{topic}\\n正文:\\n{article}\\n\\n'
f'返回JSON:{{"score":1-10,"passed":true/false,'
f'"feedback":"具体修改建议(每个问题说清楚怎么改)"}}',
json_mode=True, temp=0.1)

7分以上通过。审核反馈不是"写得不好"这种空话,而是"第三段缺少代码示例,建议补充一个实际调用的例子"这种可执行的建议——写作Agent拿到后才能针对性修改。

运行全过程

pipeline = ContentPipeline(max_rewrites=2)
article, topic, review = pipeline.run("AI Agent开发")
print(article)

💡 选题:为什么你的Agent总是答非所问?Function Calling避坑指南
角度:从反面案例切入,讲3个最常见的工具调用错误

🔍 调研中…
✍️ 写作中…

❌ 5/10,打回重写:文章缺少具体的错误代码示例,
建议展示一个LLM输出错误JSON的真实case,并给出修正后的Schema…
✍️ 根据反馈重写…

❌ 6/10,打回重写:代码示例有了,但第三段和第五段内容重复,
建议合并;结尾缺少总结和行动建议…
✍️ 根据反馈重写…

✅ 审核通过(8/10),用了3稿

上面是示意。下面是我实际跑一遍的真实输出(GLM-4.7-Flash,免费):

在这里插入图片描述

这次运行更有意思——选题阶段赶上GLM限流,脚本自动重试8次后成功;写作首稿6分被审核打回,重写后4分,再重写5分,始终没过7分线,最终触发max_rewrites=2安全阀输出当前版本。流水线统计:8次LLM调用、2次重写、3轮审核。

跑完生成的最终文章长这样:

在这里插入图片描述

示意里我写的是"5分→6分→8分通过"的理想剧本,实际跑起来结果更随机:6分→4分→5分,一直没到7分线。但两个版本说明了同一件事——审核打回真的能让文章变好:第一稿缺代码示例被点名,重写后代码有了;虽然模型输出不稳定导致分数波动,但每次打回都带着具体修改建议,写作Agent是真按建议改的。max_rewrites=2兜底,跑烂了也能出个能看的版本。如果只写一稿直接发,你发出去的就是6分那版。

这个流水线用了前面哪些知识

环节来自具体用法
Agent分工 Day13 四个角色各有独立prompt
流水线编排 Day13 前一个输出是后一个输入
质量回退 Day11 审核不通过→带反馈重写,Reflexion闭环
结构化输出 Day02 选题和审核用chat_json返回JSON
工具调用 Day02 调研Agent调用search_web
LLM客户端 Day01 全程复用llm_client.py

没有新东西,就是把18天学的零件组装成一个完整产品。

18篇知识地图

基础能力
├── Day01 Agent骨架:感知→规划→行动→观察→反思循环
├── Day02 Function Calling:让LLM主动调函数
└── Day03 工具设计:描述精准、参数约束、错误处理

流程管控
├── Day04 状态机:IDLE→PLANNING→EXECUTING→DONE
├── Day05 记忆架构:工作记忆+短期+长期三级
├── Day09 任务规划:Plan-and-Execute先拆后做
├── Day11 Reflexion:执行→评估→反思→重试
└── Day12 工具注册中心:插件化解耦

知识增强
├── Day06 向量数据库:ChromaDB+Embedding+余弦相似度
├── Day07 RAG基础:文档分块→检索→拼接上下文
└── Day08 高级RAG:查询重写+重排序+多轮检索

多工具与多Agent
├── Day10 多工具编排:路由→流水线→并行
├── Day13 分工型:研究员→分析师→写作者流水线
├── Day14 主从型:主管拆任务派活,Worker执行
└── Day15 群聊型:多角色讨论,主持人判共识

实战项目
├── Day16 文档问答系统:RAG+Function Calling+记忆
├── Day17 研究助手:规划+搜索+反思+报告
└── Day18 内容流水线:四Agent编辑部+质量回退 ← 你在这里

写在最后

18天前,Day01从一个最简单的Agent Loop开始——让LLM在"思考→行动→观察"之间循环。当时写的代码不到30行。

到今天,四个Agent组成编辑部,能自动选题、调研、写作、审核、打回重写,代码也不过100行出头。不是因为变复杂了,而是因为每一步都是可拆解的工程问题:Function Calling解决"LLM怎么调工具",状态机解决"Agent怎么不乱套",RAG解决"LLM知识不够",多Agent解决"一个角色干不好所有事"。

Agent不是魔法。把大问题拆成小问题,每个小问题找到对应的工程方案,然后组装起来——就这么简单。

GLM-4.7-Flash永久免费,200K上下文,全程零成本跑通所有代码。去智谱AI开放平台官网注册就能拿到API Key。

完整版支持PDF/Word导出、多风格模板(技术教程/行业分析/产品评测)、用户反馈长期记忆优化、多篇文章并行生产,放在CSDN下载区。


本文由「梅雅达编程笔记」原创,首发CSDN。 AI Agent实战系列共18篇,从Function Calling到多Agent协作,全程用免费模型GLM-4.7-Flash,点个关注不迷路✨ CSDN博客:https://blog.csdn.net/2601_96428997/


赞(0)
未经允许不得转载:171主机测评 » 【Day 18】收官:四个Agent组成编辑部,自动生产文章
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址