笔记
0工具
0此页用于记录用户反馈问题后的每一次改进
关于
“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
不想公开、只想临时给人看:点“分享”生成一条带密码和有效期的链接,到期自动失效,你也能随时撤销。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
趋势
AI Agent 入门指南
最近我在 freeCodeCamp 的 YouTube 频道上看了一门挺不错的课程,讲的是 AI Agent(人工智能代理)从零到上手。讲师是 CodeCloud 的创始人 Mumshad Mannambeth,整个课程差不多 3 小时,内容非常扎实,从 LLM(大语言模型)的基础概念一直讲到构建多智能体系统。我把课程里的核心知识点、代码示例、操作步骤都整理成了这篇笔记,希望能帮你少走弯路。
老实说,我之前对 Agent 的理解就是“调 API 写个循环”,但学完才发现,这里面坑不少:工作流(Workflow)和真正的 Agent 到底有啥区别?怎么让 Agent 自主决策而不是死板地走预设路径?还有生产环境里那些安全、记忆、结构化输出的问题,每个都值得好好琢磨。
下面我会按照课程的结构,把每个关键点都展开讲清楚,尽量还原讲师的原意,同时加上我自己的理解和补充。
1. LLM 核心概念:搞清楚基础再动手
在开始写 Agent 之前,你至少得知道 LLM 是怎么工作的。课程从这里入手,我觉得特别对——很多教程一上来就让你调 LangChain,结果出了问题根本不知道为啥。
1.1 什么是 GPT(生成式预训练 Transformer)
GPT 的全称是 Generative Pre-trained Transformer。简单说,它是一个基于 Transformer 架构的神经网络,在大规模文本数据上做过预训练。预训练阶段它学会了语言的统计规律——比如“苹果”后面大概率跟着“水果”或者“手机”,而不是“恐龙”。
但注意:GPT 不是“理解”语言,它只是通过概率预测下一个词。这一点很重要,后面讲 Agent 决策时你会看到,这种概率性质既是优势也是局限。
1.2 Token 与 Tokenization:模型的“原子单位”
LLM 处理文本时,不是按字符或单词来切的,而是用 token(令牌)。一个 token 可能是一个单词、一个子词,甚至一个字符。比如:
- “Hello” 可能是一个 token
- “unbelievable” 可能被切成 “un”, “believe”, “able” 三个 token
Tokenization 就是把这个切分过程。不同的模型用不同的 tokenizer,比如 GPT 系列用的是 Byte-Pair Encoding (BPE)。为什么关心这个?因为:
- 计费:大部分 API 按 token 收费,输入输出都算
- 上下文窗口:模型能处理的 token 数量有限(比如 4K、8K、128K),超出就截断
- 性能:长文本会消耗更多计算资源
举个例子,如果你用 GPT-4 处理一篇 3000 字的文章,大概会消耗 4000-5000 个 token。如果上下文窗口只有 4096,那文章后半段可能就被截掉了。
1.3 Temperature:控制模型的“创造力”
Temperature 是一个超参数,控制模型输出的随机性。它的取值范围通常是 0 到 2(有些模型到 1)。
- Temperature = 0:模型总是选概率最高的 token,输出确定性强,适合事实性任务(比如代码生成、数据提取)
- Temperature = 0.7:模型会偶尔选概率稍低的 token,输出有一定多样性,适合创意写作
- Temperature = 1.0 以上:模型几乎随机选 token,输出可能很发散,但也可能胡说八道
课程里特别强调:在 Agent 场景中,如果你让 Agent 做工具调用(比如执行代码、查询数据库),temperature 最好设低一点(0-0.2),否则它可能“自由发挥”出一些不存在的函数名。如果你让它写文案或做头脑风暴,可以设高一点(0.7-0.9)。
2. Workflow vs. Agent:两种架构,两种哲学
这是课程里最让我醍醐灌顶的部分。很多人把“调大模型”和“用 Agent”混为一谈,但这两者在架构上根本不同。
2.1 Workflow(工作流):预设路径,像铁路系统
Workflow 就是你把一系列步骤写死在代码里。比如:
1. 接收用户输入
2. 调用 LLM 生成摘要
3. 调用另一个函数检查摘要长度
4. 如果太长,截断
5. 返回结果
每一步的顺序、条件、分支都是程序员预先定义的。LLM 只是其中一个组件,像调用一个函数一样。
优点:可控、可预测、容易调试
缺点:僵化,无法应对未预见的场景
2.2 Agent(智能体):自主循环,像探险家
Agent 是一个自主的循环系统。它自己决定下一步做什么:
1. 接收用户目标
2. 思考:为了完成目标,我需要什么信息?
3. 选择一个工具(搜索、计算、查数据库等)
4. 执行工具,得到结果
5. 根据结果更新“思考”
6. 重复 2-5,直到目标达成或无法继续
关键是:Agent 自己选择工具和顺序,程序员只提供工具集和安全约束。
课程里用了一个很好的比喻:Workflow 是自动扶梯,Agent 是自动驾驶汽车。自动扶梯只能走固定路线,但可靠;自动驾驶汽车能灵活应对路况,但可能撞车。
2.3 什么时候用哪个?
- 如果任务明确、步骤固定(比如“每天生成一份销售报告”),用 Workflow
- 如果任务开放、需要探索(比如“研究一下量子计算的现状”),用 Agent
- 实际项目中,往往是 Workflow 套 Agent:外层是固定流程,内层用 Agent 处理复杂子任务
3. 动手实现:四个 Agent 角色
课程最硬核的部分是手写四个 Agent,每个都有不同的专长。讲师用 Python 从零实现,没有用 LangChain 之类的框架——这样你能真正理解底层逻辑。
3.1 Zippy:编排者(Orchestrator)
Zippy 的角色是“老板”——它不直接干活,而是把任务分解,分派给其他 Agent,然后汇总结果。
核心机制:Zippy 维护一个任务队列,每次从 LLM 获取下一步指令。LLM 的输出是一个结构化的 JSON,包含 action(动作类型)和 parameters(参数)。
代码示例(简化版):
import json
from openai import OpenAI
client = OpenAI()
class Zippy:
def __init__(self):
self.task_queue = []
self.context = {}
def think(self, user_input):
# 让 LLM 决定下一步
prompt = f"""
你是一个任务编排者。当前用户输入:{user_input}
已有上下文:{json.dumps(self.context)}
请输出 JSON 格式的下一步计划:
{{
"action": "delegate | gather | finalize",
"target_agent": "savvy | meshi | cody",
"task": "具体任务描述",
"reasoning": "为什么这样做"
}}
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.1, # 低温度保证确定性
response_format={"type": "json_object"}
)
decision = json.loads(response.choices[0].message.content)
return decision
def execute(self, user_input):
while True:
decision = self.think(user_input)
if decision["action"] == "finalize":
return self.context.get("final_answer", "任务完成")
# 实际会调用对应的 Agent 子类
print(f"Zippy 决定: {decision}")
关键点:Zippy 的 output 必须是结构化 JSON,这样下游代码才能解析。课程里用了 response_format 参数强制 JSON 输出,这是一个生产级技巧。
3.2 Savvy:研究专家(使用 ReAct 模式)
Savvy 是真正的“思考者”。它使用了 ReAct(Reasoning + Acting) 模式,这是目前 Agent 最流行的设计范式。
ReAct 循环:Thought(思考)→ Action(行动)→ Observation(观察)→ 重复
代码示例:
class Savvy:
def __init__(self, tools):
self.tools = tools # 工具列表,比如搜索、计算器
self.memory = [] # 短期记忆
def react_loop(self, question, max_steps=5):
step = 0
while step < max_steps:
# 1. Thought: 让 LLM 分析当前状态
thought_prompt = f"""
问题:{question}
历史步骤:{self.memory}
可用工具:{list(self.tools.keys())}
下一步应该思考什么?输出 JSON:
{{
"thought": "你的推理",
"action": "工具名称或 'final'",
"action_input": "工具参数"
}}
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": thought_prompt}],
temperature=0.2
)
decision = json.loads(response.choices[0].message.content)
# 2. Action: 执行工具
if decision["action"] == "final":
return decision["thought"]
elif decision["action"] in self.tools:
tool = self.tools[decision["action"]]
observation = tool(decision["action_input"])
# 3. Observation: 记录结果
self.memory.append({
"step": step,
"action": decision["action"],
"observation": observation
})
step += 1
return "达到最大步数,未完成"
为什么 ReAct 有效?因为它模仿了人类的推理过程:先想“我需要知道什么”,然后去查,查完再想“接下来怎么办”。这种交替循环让 LLM 不会“跑偏”。
实战注意:max_steps 要设上限,否则可能陷入死循环。另外,每一步的 memory 要包含完整上下文,否则 LLM 会忘记之前做了什么。
3.3 Meshi:记忆管理器
Meshi 负责长期记忆。LLM 的上下文窗口有限,而且每次对话结束后就忘了。Meshi 用一个向量数据库(Vector DB)来存储和检索历史信息。
核心流程:
- 写入:当 Agent 完成一个子任务,Meshi 把关键信息(文本 + 向量嵌入)存入数据库
- 检索:新任务来时,Meshi 根据语义相似度找到相关的历史记录,注入到 prompt 中
代码示例(使用简单的 FAISS 作为向量库):
import faiss
import numpy as np
from sentence_transformers import SentenceTransformer
class Meshi:
def __init__(self):
self.encoder = SentenceTransformer('all-MiniLM-L6-v2')
self.index = faiss.IndexFlatL2(384) # 384维向量
self.texts = []
def remember(self, text):
vector = self.encoder.encode([text])
self.index.add(vector)
self.texts.append(text)
def recall(self, query, top_k=3):
query_vec = self.encoder.encode([query])
distances, indices = self.index.search(query_vec, top_k)
results = [self.texts[i] for i in indices[0] if i != -1]
return results
def inject_memory(self, prompt):
memories = self.recall(prompt)
if memories:
memory_text = "\n".join([f"[记忆] {m}" for m in memories])
return f"{prompt}\n\n相关历史记录:\n{memory_text}"
return prompt
为什么需要 Meshi?假设你的 Agent 在做一个长期项目,比如“研究竞争对手的产品”。第一天它查了 A 公司,第二天查 B 公司。如果没有 Meshi,第二天它完全忘了 A 公司的信息,导致结论片面。Meshi 让 Agent 有了“长期记忆”。
生产级替代:课程里用 FAISS 演示,实际生产常用 Pinecone、Weaviate 或 Qdrant。另外,嵌入模型的选择也很重要——text-embedding-3-small 比 all-MiniLM 效果更好,但成本也更高。
3.4 Cody:代码与自动化专家
Cody 专门负责写代码、执行代码、返回结果。这是 Agent 中最危险也最强大的角色——因为让 LLM 生成的代码直接运行,相当于给了它一把枪。
安全设计:Cody 在沙箱(sandbox)中执行代码。课程里用了 Docker 容器 + 超时控制。
import subprocess
import tempfile
import os
class Cody:
def __init__(self, sandbox_dir="/tmp/sandbox"):
self.sandbox_dir = sandbox_dir
os.makedirs(sandbox_dir, exist_ok=True)
def generate_code(self, task):
prompt = f"""
根据任务生成 Python 代码。只输出代码,不要解释。
任务:{task}
代码必须:
- 使用标准库或已安装的包
- 不访问网络(除了指定API)
- 不修改系统文件
- 有错误处理
"""
response = client.chat.completions.create(
model="gpt-4",
messages=[{"role": "user", "content": prompt}],
temperature=0.0
)
return response.choices[0].message.content
def execute_safely(self, code, timeout=10):
# 写入临时文件
with tempfile.NamedTemporaryFile(mode='w', suffix='.py',
dir=self.sandbox_dir, delete=False) as f:
f.write(code)
fpath = f.name
try:
# 在子进程中运行,限制时间和资源
result = subprocess.run(
["python3", fpath],
capture_output=True,
text=True,
timeout=timeout,
cwd=self.sandbox_dir
)
output = result.stdout if result.returncode == 0 else result.stderr
except subprocess.TimeoutExpired:
output = "代码执行超时"
finally:
os.unlink(fpath) # 清理文件
return output
关键安全措施:
- 沙箱隔离:代码在独立目录运行,无法访问系统敏感文件
- 超时控制:防止死循环或无限等待
- 资源限制:生产环境应该限制 CPU、内存、磁盘使用(比如用
resource模块或 Docker 的--memory参数) - 代码审查:如果是生产系统,最好加一个人工审核步骤(Human-in-the-loop)
4. 生产模式与安全:别让 Agent 搞砸了
课程最后一部分讲的是生产级设计模式。这些不是锦上添花,而是必须——否则你的 Agent 可能在线上胡说八道、泄露数据、甚至执行危险操作。
4.1 结构化 JSON 输出
前面 Zippy 和 Savvy 的代码里已经用了 response_format={"type": "json_object"}。这是 OpenAI 提供的一个强大功能,强制模型输出合法 JSON。
为什么重要:
- 解析可靠:不用写一堆正则去猜模型输出的格式
- 错误处理简单:如果模型输出非 JSON,直接重试或报错
- 下游代码清晰:
json.loads()一步到位
但是:这个功能只保证格式合法,不保证字段正确。比如你要求 {"action": "search"},它可能输出 {"action": "fly"}。所以还是要加校验逻辑。
4.2 输入/输出护栏(Guardrails)
护栏是指在 Agent 的输入和输出端加过滤机制,防止它处理危险内容或泄露敏感信息。
输入护栏:检查用户输入是否包含注入攻击、敏感词、过长文本等。
def input_guardrail(user_input):
# 检查长度
if len(user_input) > 4000:
raise ValueError("输入过长")
# 检查注入模式(简单示例)
forbidden_patterns = ["ignore previous instructions", "system prompt", "你的名字是"]
for pattern in forbidden_patterns:
if pattern.lower() in user_input.lower():
raise ValueError("检测到注入尝试")
return user_input
输出护栏:检查模型输出是否包含个人身份信息(PII)、API 密钥、冒犯性内容等。
def output_guardrail(model_output):
# 检查是否包含敏感信息(正则示例)
import re
# API 密钥模式
if re.search(r'sk-[a-zA-Z0-9]{20,}', model_output):
return "输出包含敏感信息,已拦截"
# 邮箱模式
if re.search(r'[\w\.-]+@[\w\.-]+\.\w+', model_output):
return "输出包含邮箱地址,已拦截"
return model_output
生产建议:不要自己写正则,用现成的库如 guardrails、neMo-guardrails。它们内置了更多检测规则。
4.3 人在回路中(Human-in-the-loop)
对于高风险操作(比如执行代码、发送邮件、修改数据库),Agent 不应该自主决定。应该先暂停,等待人工确认。
def human_approval(action_description):
print(f"⚠️ Agent 请求执行:{action_description}")
response = input("是否批准?(y/n): ")
return response.lower() == 'y'
# 在 Cody 中集成
if decision["action"] == "execute_code":
if human_approval(f"执行代码:{code[:100]}..."):
result = cody.execute_safely(code)
else:
result = "操作被用户取消"
设计哲学:Agent 应该是一个“建议者”,而不是“执行者”。尤其是金融、医疗、法律等领域,人工审核是刚需。
4.4 安全沙箱执行
前面 Cody 部分已经讲了沙箱。这里补充几点生产级实践:
- 使用 Docker 容器:每个代码执行任务启动一个临时容器,用完销毁
- 网络隔离:默认禁止网络访问,除非白名单
- 文件系统隔离:只允许读写特定目录
- 资源配额:限制 CPU 核数、内存大小、磁盘空间
- 审计日志:记录每次执行的代码、输入、输出、耗时
5. OpenClaw 案例研究:一个真实的生产级系统
课程最后剖析了 OpenClaw——一个开源的个人助手框架。它不是玩具,而是真正在生产环境中使用的系统。
5.1 五阶段循环
OpenClaw 的核心是一个五阶段循环:
- 感知(Sense):收集输入(文本、语音、传感器数据)
- 推理(Reason):用 LLM 分析当前状态,决定下一步
- 行动(Act):调用工具或 API
- 记忆(Memory):将关键信息存入长期记忆
- 学习(Learn):根据结果调整未来行为(可选)
5.2 会话状态管理
OpenClaw 维护一个会话状态对象,包含:
- 当前用户身份
- 对话历史(摘要 + 完整记录)
- 活跃的任务列表
- 已获取的上下文信息
这个状态在每次循环中更新,并且可以被持久化到数据库,以便断电恢复。
5.3 动态系统提示(19 个部分)
最让我震惊的是:OpenClaw 的系统提示(System Prompt)不是固定的,而是动态构建的。它根据当前会话状态、用户历史、可用工具等信息,组装出一个包含 19 个部分的超长提示。
这 19 个部分包括:
- 角色定义
- 可用工具列表(带参数说明)
- 用户偏好(从长期记忆提取)
- 当前会话上下文
- 安全规则
- 输出格式要求
- 错误处理策略
- ... 等等
为什么这样做?因为 LLM 的上下文窗口有限,你不能把所有的工具说明、历史记录、规则都塞进去。动态构建只加载当前需要的信息,既节省 token,又提高精度。
实现思路:
class DynamicPromptBuilder:
def __init__(self):
self.sections = {
"role": "你是一个个人助手...",
"tools": None, # 懒加载
"user_prefs": None,
"safety": "禁止执行任何金融操作..."
}
def build(self, session_state):
prompt_parts = []
# 1. 角色固定
prompt_parts.append(self.sections["role"])
# 2. 工具列表:只加载当前会话可能用到的
active_tools = session_state.get_active_tools()
prompt_parts.append(f"可用工具:{json.dumps(active_tools)}")
# 3. 用户偏好:从向量数据库检索
prefs = meshi.recall(f"用户{session_state.user_id}的偏好")
if prefs:
prompt_parts.append(f"用户偏好:{prefs}")
# ... 其他部分
return "\n\n".join(prompt_parts)
总结与下一步
学完这门课,我觉得最大的收获不是具体的代码,而是思维方式:Agent 不是“调大模型”,而是设计一个循环系统,让 LLM 在这个循环中扮演推理引擎的角色。真正的工作量在工具设计、安全控制、记忆管理这些外围组件上。
如果你想自己动手试试,我建议:
- 从简单的 ReAct 循环开始,不要一上来就搞多 Agent 系统
- 先加护栏,再放飞 Agent——安全永远第一
- 记录所有 Agent 的决策日志,否则出了问题你都不知道它为什么这么干
- 渐进式增加复杂度:先单 Agent + 单工具,再单 Agent + 多工具,最后多 Agent 协作
最后,强烈建议你去 freeCodeCamp 看原课程(3 小时,链接在原文里)。Mumshad 讲得很清楚,而且有代码演示,比我这篇文字笔记直观得多。
如果你在实践过程中遇到问题,欢迎留言讨论。Agent 这个领域还在快速发展,很多 best practice 都是社区摸索出来的。我们一起学。