
1. 背景与核心概念当 LLM Agent 有了“成长”需求如果你最近在关注大模型应用开发一定对 LLM Agent大语言模型智能体不陌生。简单来说Agent 是能够感知环境、做出决策并执行动作的 AI 程序而 LLM 在其中扮演“大脑”的角色负责理解任务、拆解步骤、调用工具和生成结果。从自动写代码到操作浏览器从数据分析到客服对话LLM Agent 正在成为 AI 落地的重要形态。但这里有一个非常关键的问题大多数 Agent 是“一次性”的。什么意思比如你让 Agent 帮你完成一个数据分析任务它通过调用 Python 代码、读取 CSV、画图最终交付了结果。整个过程看起来不错但下次你再给它一个类似任务它还会重复一遍完全相同的探索过程既不会记住上次的处理经验也不会调用已经沉淀下来的分析模板。它没有“越用越顺手”的成长性。这就引出了本文的核心主题ContinualSkillBench——一个用来评估 LLM Agent 是否能持续获取技能、真正实现能力演进的基准框架。从标题来看这个项目聚焦于一个非常尖锐的问题LLM Agent 真的能演化自身能力吗“演化”这个词很重。它不是指模型参数在训练阶段被更新而是指 Agent 在部署使用过程中能否像人类一样通过完成任务积累经验把经验转化为可复用的技能并在未来任务中主动使用这些技能。换句话说我们要评估的不是“这个 Agent 在某个任务上表现多好”而是“这个 Agent 在经历一系列任务之后是否变得更强了”。这个方向的价值在于当前主流的 Agent 评估基准比如 HotpotQA、ALFWorld、WebArena 等多数是静态的、单次任务的。它们能告诉我们 Agent “当前能做什么”但无法回答“Agent 能否持续成长”。而如果 Agent 无法从经验中学习那么它在真实业务中的价值就会大打折扣——因为真实业务中同一类型的任务会反复出现每一次都应该比上一次做得更快、更好。ContinualSkillBench 正是冲着这个缺口来的。它试图构建一套可复现、可量化的评估方法用来回答三个层次的问题Agent 能否从已完成的任务中提取出可复用的技能Agent 能否在后续任务中主动应用已学到的技能这种“技能获取-技能应用”的过程能否持续闭环形成能力跃迁下面我会从概念出发逐步拆解 ContinualSkillBench 的设计思路、核心模块、评估指标以及对 Agent 开发实践的启示。即使你没有读过原论文跟着这篇文章走一遍也能理解这个基准的骨架和背后逻辑。2. 环境准备与版本说明如何搭建一个可运行的 Agent 评估环境虽然 ContinualSkillBench 是一个研究型基准但理解它最好的方式还是亲手跑一个 Agent 任务流观察它如何在“任务执行—经验沉淀—技能复用”的循环中运行。下面我们先搭建一个最小可运行的 LLM Agent 环境。2.1 环境依赖本文示例以常见环境为例版本需要根据你的实际项目调整重点是演示配置思路。操作系统Ubuntu 20.04 / macOS 12 / Windows 10建议 Linux/macOSPython3.9 或 3.10大模型访问方式OpenAI API 或兼容接口如本地部署的 vLLM、Ollama依赖库openai、langchain可选、pandas、numpy、rich建议使用虚拟环境隔离项目依赖python -m venv agent_env source agent_env/bin/activate # Windows 下使用 agent_env\Scripts\activate pip install openai langchain pandas numpy rich2.2 项目结构我们按下面结构组织代码方便后续扩展成完整的持续学习评估流程continual_skill_demo/ ├── agent.py # Agent 核心逻辑 ├── experience_pool.py # 经验池用来存储和检索历史技能 ├── task_router.py # 任务路由判断当前任务是否需要调用已有技能 ├── data/ │ └── tasks.json # 测试任务流 └── main.py # 主流程执行多轮任务2.3 基础 Agent 实现我们先用一个最简单的 Agent 原型来演示“执行任务”的部分。它接收一个用户指令调用 LLM 生成答案# 文件路径agent.py import os from openai import OpenAI client OpenAI( api_keyos.getenv(OPENAI_API_KEY), base_urlos.getenv(OPENAI_BASE_URL) # 兼容本地模型服务 ) SYSTEM_PROMPT 你是一个善于总结和解决问题的智能助手。 def run_agent(task: str, context: str ) - str: 执行单个任务返回 Agent 的回答。 messages [ {role: system, content: SYSTEM_PROMPT}, ] if context: messages.append({role: system, content: f历史技能提示\n{context}}) messages.append({role: user, content: task}) resp client.chat.completions.create( modelos.getenv(LLM_MODEL, gpt-4o-mini), messagesmessages, temperature0.2 ) return resp.choices[0].message.content这里的关键是context参数。当 Agent 从经验池中检索到相关技能时它会以系统提示的形式注入到上下文里从而影响当前任务的执行方式。这也对应了 ContinualSkillBench 中“技能复用”的基本机制。3. 核心设计拆解ContinualSkillBench 在评估什么现在我们已经有了一个可运行的 Agent 雏形。但 ContinualSkillBench 关心的不是“Agent 能不能做任务”而是“Agent 能不能越做越好”。要做到这一点我们需要把评估框架拆开来看。3.1 三个核心评估维度基于项目标题所传递的信息ContinualSkillBench 的设计至少应该覆盖三个维度第一个维度是技能获取能力。Agent 在完成一个任务后能否从执行过程中提炼出可复用的方法论比如Agent 完成了一个“从网页中批量提取商品标题”的任务它能否总结出“使用 BeautifulSoup 定位 HTML 标签时应该先分析目标网站的 DOM 结构”这样的技能这个维度衡量的是“经验的转化率”。第二个维度是技能调用能力。当 Agent 遇到一个新任务时能否主动检索并应用之前学到的技能这远比“是否学会了”更难因为它涉及到任务匹配、技能检索和上下文融合。很多 Agent 的问题在于经验池里存了很多技能卡片但遇到新任务时它不知道“这个问题和之前的那个问题是同一类”。第三个维度是持续累积能力。Agent 经历的每一个任务都应该成为后续任务的垫脚石。如果一个 Agent 在 10 个任务后表现得和 1 个任务后一样那它没有真正的演化。这个维度关注的是“能力曲线的斜率”。3.2 任务流从单任务到多任务序列传统评估中每个任务都是独立采样的。ContinualSkillBench 则会设计一系列存在内在关联的任务序列。举个例子任务 1写一个 Python 函数读取 CSV 文件并统计每列的缺失值。任务 2写一个 Python 函数读取 JSON 文件并统计嵌套字段的缺失值。任务 3写一个 Python 函数读取 SQLite 数据库中的表并统计每列的缺失值。任务 4写一个 Python 函数针对一个包含 CSV、JSON、SQLite 三种数据源的数据集输出统一格式的缺失值报告。可以看到任务 4 是一个综合性任务它要求 Agent 把前三项任务中积累的经验融合成一个更通用的解决方案。如果 Agent 没有持续学习的机制它会在任务 4 中从零开始思考如果 Agent 具备技能沉淀与复用能力它在任务 4 中应该能直接调用“数据源探测”“缺失值统计”“统一格式化输出”等技能效率和质量都会有明显提升。这种设计思路的核心是用任务序列的递进关系来模拟真实业务中的经验积累场景。3.3 技能表达形式自然语言 vs 代码模板在 ContinualSkillBench 这类框架中技能的表达方式决定了后续检索和复用的效果。目前主流做法有两种。第一种是自然语言技能描述。Agent 在完成任务后会生成一段结构化的文本比如技能名称CSV 缺失值统计 适用场景读取本地 CSV 文件并统计缺失值 核心步骤 1. 使用 pandas.read_csv 读取文件 2. 使用 df.isnull().sum() 统计每列缺失值 3. 用 df.dtypes 确认列类型注意空字符串会被视为非缺失 注意事项 - 文件编码建议使用 utf-8-sig避免中文乱码 - 大文件建议使用 dtype 参数减少内存占用这种表达方式的好处是语义丰富易于被 LLM 理解和改写坏处是检索时依赖 embedding 匹配的精度。第二种是代码模板技能。Agent 保存的是一个带占位符的代码片段比如def load_data(file_path: str, file_type: str) - pd.DataFrame: if file_type csv: return pd.read_csv(file_path, encodingutf-8-sig) elif file_type json: return pd.read_json(file_path) else: raise ValueError(fUnsupported file type: {file_type})这种方式的好处是复用起来直接、执行可靠坏处是灵活性不足难以应对任务变化较大的场景。ContinualSkillBench 的价值在于它提供了一个标准化的评估机制让我们可以量化比较“用自然语言技能”和“用代码模板技能”哪种方式对 Agent 的能力演化贡献更大。这一点对 Agent 工程实践非常有指导意义。3.4 评估指标不只是任务准确率如果只看“任务完成率”我们无法判断 Agent 是否发生了能力演化。ContinualSkillBench 这类基准通常会引入更精细的指标。一个常用指标是技能获取率即 Agent 在完成 N 个任务后成功沉淀出的高质量技能数量占可提取技能总量的比例。一个只会执行任务、不会总结经验的 Agent这项指标会很低。另一个指标是技能复用率即在后续任务中Agent 主动调用了之前学到的技能的比例。这个指标可以直接反映 Agent 是否具备“记忆”和“联想”能力。还有一个指标是性能增益即随着任务序列的推进Agent 在同类任务上的完成时间、调用步数、最终质量是否有显著提升。如果 Agent 学了 10 个技能但第 11 个任务的表现和第 1 个任务没有任何差异那说明它没有学会“举一反三”。更严格的设计还会加一个遗忘测试在 Agent 完成前 10 个任务并学习了相关技能后过一段时间再给出一个与任务 3 类似但略有变化的任务考察 Agent 是否还记得、能否正确应用。这与人类的“记忆衰减”和“知识巩固”概念非常相似。4. 实战案例实现一个带经验池的持续学习 Agent理论讲完了下面我们动手实现一个简化版的持续学习 Agent。这个案例虽然没有完全复刻 ContinualSkillBench 的完整实验设计但能让你直观感受到“技能沉淀—检索—复用”的完整闭环。4.1 经验池模型我们用字典存储技能用 embedding 做语义检索# 文件路径experience_pool.py import numpy as np from openai import OpenAI client OpenAI() class ExperiencePool: def __init__(self): self.skills [] # 技能文本列表 self.embeddings [] # 技能向量列表 def add_skill(self, skill_text: str): 新增一条技能并计算 embedding 存入经验池。 vec client.embeddings.create( modeltext-embedding-3-small, inputskill_text ).data[0].embedding self.skills.append(skill_text) self.embeddings.append(vec) def retrieve(self, task: str, top_k: int 2) - str: 根据当前任务检索最相关的技能描述。 if not self.skills: return task_vec client.embeddings.create( modeltext-embedding-3-small, inputtask ).data[0].embedding scores [] for skill_vec in self.embeddings: score np.dot(task_vec, skill_vec) / ( np.linalg.norm(task_vec) * np.linalg.norm(skill_vec) ) scores.append(score) top_idx np.argsort(scores)[-top_k:][::-1] context_blocks [] for i in top_idx: context_blocks.append(f【已有技能 {i1}】\n{self.skills[i]}) return \n\n.join(context_blocks)4.2 技能提取函数Agent 完成任务后我们会调用 LLM 生成一份结构化的技能描述并过滤掉无效内容# 文件路径agent.py追加 def extract_skill(task: str, experience: str) - str | None: 从执行经验中提取可复用技能无效时返回 None。 prompt f 根据以下任务和 Agent 执行经验总结一条可复用的技能描述。 - 技能名称 - 适用场景 - 核心步骤 - 注意事项 只输出技能内容本身不要多余解释。 如果经验中没有值得复用的内容请输出NULL 任务{task} 执行经验{experience} resp client.chat.completions.create( modelos.getenv(LLM_MODEL, gpt-4o-mini), messages[{role: user, content: prompt}], temperature0.1 ) content resp.choices[0].message.content.strip() return None if content.upper().startswith(NULL) else content4.3 主流程主流程模拟了“连续执行 5 个任务并在第 3、第 4、第 5 个任务时注入历史技能”的完整过程# 文件路径main.py from agent import run_agent, extract_skill from experience_pool import ExperiencePool TASKS [ 写一个 Python 函数读取 CSV 文件并返回每列的缺失值数量。, 写一个 Python 函数读取 JSON 文件并统计嵌套字典中每个键的缺失情况。, 写一个 Python 函数读取 SQLite 数据库中的表并统计每列的空值数量。, 写一个 Python 函数自动识别数据文件类型csv/json/sqlite并统一输出缺失值报告。, ] def main(): pool ExperiencePool() for i, task in enumerate(TASKS, 1): print(f\n 执行第 {i} 个任务 ) # 1. 检索历史技能 context pool.retrieve(task) if context: print(f检索到已有技能注入上下文。) else: print(未检索到相关技能从零开始执行。) # 2. 执行任务 result run_agent(task, contextcontext) print(fAgent 输出片段{result[:100]}...) # 3. 提取技能并存入经验池 skill extract_skill(task, result) if skill: pool.add_skill(skill) print(f已沉淀技能{skill[:50]}...) else: print(本次任务未提取到有效技能。) if __name__ __main__: main()4.4 运行与验证配置好OPENAI_API_KEY后直接运行python main.py预期输出中可以看到前两个任务因为经验池为空Agent 从零开始推理到第 3 个任务时经验池中已经存在“CSV 缺失值统计”和“JSON 缺失值统计”两条技能Agent 会得到相似任务的上下文提示第 4 个任务是一个综合性任务它会融合多个技能片段输出更高效的实现。这里需要特别说明一点由于我们没有定义自动化的答案质量评估器所以这个演示只能看到“技能是否被检索和注入”无法量化“技能注入后效果提升了多少”。ContinualSkillBench 的完整设计中会加入人工评估或 LLM 评测器为每个任务的输出质量打分从而计算出能力演化曲线。5. 常见问题与排查思路持续学习 Agent 的工程陷阱在构建带经验池的 Agent 过程中你可能会遇到几个高频问题。下面整理成表格方便快速定位。问题现象常见原因解决思路检索到的技能与当前任务无关embedding 模型区分度不足或技能描述过于泛化在技能文本中增加“适用场景”和“排除场景”使用更强的 embedding 模型调整 top_k 值Agent 忽略了注入的技能提示技能上下文太长挤占了模型注意力窗口精简技能文本只保留步骤和注意事项把技能放在用户消息末尾而不是 system prompt 中技能越存越多检索越来越慢经验池无上限且每次任务都全量计算相似度增加技能数量上限或引入周期性压缩使用向量数据库如 Milvus、Chroma替代内存数组提取的技能质量参差不齐温度参数过高或 LLM 模型本身总结能力不足调低 temperature 到 0.1 以下使用更强模型做技能提取加入格式约束和人工抽检同一类型技能重复存储缺少去重机制存入前先与已有技能计算相似度超过阈值则合并或跳过早期错误经验被不断复用没有负反馈机制在技能描述中保留“已知局限”建立失败案例池标记不可用技能这些问题的根源往往不是某一个环节而是“提取—存储—检索—注入”这条链路缺乏闭环反馈。在工程实践中除了做好每个环节还需要记录每次技能注入后的效果形成数据驱动的技能淘汰机制。6. 最佳实践与工程建议如何打造真正会成长的 AgentContinualSkillBench 不仅仅是学术界的评估基准它的设计思想可以直接借鉴到生产环境的 Agent 架构中。下面我从工程落地的角度给出几条具体建议。第一条建议是技能分层管理。不要把所有内容都塞进一个经验池。建议拆成三层第一层是领域常识比如“CSV 文件默认使用 utf-8-sig 编码读取”这类知识稳定且通用第二层是任务模板比如“数据缺失值报告的输出格式”这类模板适用于一类任务第三层是项目专属经验比如“某个内部系统的 API 调用方式”这类经验只在特定场景下有效。不同层级的技能要有不同的索引策略和生命周期管理策略。第二条建议是技能存储结构要结构化。不要只存一段自然语言文本。建议使用统一的技能 Schema至少包含技能名称、触发条件、核心步骤、预期输出、已知局限、适用范围、创建时间、最后使用时间等字段。结构化存储让检索和过滤变得更容易也让未来的技能去重、合并算法有了操作基础。第三条建议是主动引入负面经验。大多数 Agent 只会总结“怎么做成功”却不知道“什么不能做”。ContinualSkillBench 如果只是衡量正向技能的增长会忽略一个关键问题Agent 可能记住了失败的方法导致同样的错误反复出现。工程上我们应该在经验池中加入负例标签比如“使用 str.split() 处理嵌套 JSON 时会产生 KeyError应改用递归遍历”。当一个技能被多次标记为“使用后出错”系统应该自动降低它的检索权重。第四条建议是让技能注入具有可追溯性。在实际项目中你一定遇到过“Agent 突然输出变了但不知道为什么”的情况。这就是因为技能注入是黑盒的。推荐在每次 Agent 运行前打印检索到的技能编号和相关性分数运行后记录最终效果这样既方便调优也方便事故定位。第五条建议是评估闭环要制度化。如果只是上线了一个带经验池的 Agent却不持续评估它的能力变化那这个经验池很快会变成垃圾堆。建议借鉴 ContinualSkillBench 的任务流设计每周准备一组新的测试任务集一部分与历史任务相似一部分与历史任务存在潜在关联一部分是完全新颖的任务。分别记录 Agent 在三种任务上的表现就能动态刻画它的“能力演化曲线”——技能是否在被复用、是否在发生迁移、是否存在灾难性遗忘。7. 总结与下一步学习方向回到标题中的问题Can LLM Agents Truly Evolve Their Capabilities从 ContinualSkillBench 的设计思路来看答案不是简单的“能”或“不能”而是“取决于我们如何设计 Agent 的学习闭环”。如果我们只把 Agent 当做一个单次调用的大模型接口那它当然不会演化但如果我们给它引入经验池、技能提取、语义检索、任务路由、负反馈机制它就有可能在一次次任务中形成能力积累表现出持续进化的特征。这篇文章从评估框架的角度拆解了 ContinualSkillBench再带你实现了一个简化版的经验池 Agent。如果你对这个方向感兴趣下一步可以从这几个方面深入读一下持续学习Continual Learning的相关论文理解灾难性遗忘和知识巩固的数学原理。尝试用更强的开源模型替代 GPT 系列配合本地向量数据库搭建一套完整的离线持续学习 Agent。关注 Agent 评估方法学特别是如何设计任务序列来避免数据泄漏和技能互污染。在自己业务场景中选取一个高频重复的任务类型设计一套“执行—总结—沉淀—复用”的闭环测量技能复用前后的效率差异。如果你正在做 LLM Agent 开发建议把“持续技能积累”作为系统设计的一等公民而不是事后补丁。真正让 Agent 在业务中产生价值的地方不是它第一次完成任务的惊艳表现而是它在第 100 次任务时已经比第 1 次更熟练、更稳定、更聪明。