LLM智能体技能寻踪框架:基于查询-技能图的可组合任务规划 📅 发布时间:2026/8/18 2:51:25 👁 浏览次数: 1. 项目概述当LLM智能体学会“技能寻踪”最近在搞LLM智能体LLM Agents落地的朋友估计都遇到过同一个头疼的问题任务稍微复杂一点智能体就懵了。你让它“帮我分析一下上周的销售数据然后写个总结报告顺便预测下季度趋势”它要么卡在第一步出不来要么生成一堆无关信息最后交给你一个四不像。问题出在哪核心在于现有的智能体架构大多还是“一锤子买卖”——给个指令模型自己琢磨着生成一个长序列的“思考-行动”链。这种模式对于简单、线性的任务还行一旦任务需要组合多个离散的、专业的子技能比如先“数据查询”再“统计分析”最后“文本生成与预测”就显得力不从心缺乏系统性的规划和回溯能力。这正是“SkillTrace: Traversing a Query-Skill Graph for Composable LLM Agents”这个项目要啃的硬骨头。它不是一个具体的应用而是一个框架级的设计思路核心是引入“查询-技能图”Query-Skill Graph和“技能寻踪”SkillTrace机制让LLM智能体能够像老练的工程师一样面对复杂需求时不是埋头硬干而是先“翻看技能手册”动态地规划、调用、组合甚至回溯调整一系列基础技能最终稳健地完成任务。简单来说它想让智能体变得更“模块化”和“可追溯”。想象一下你是一个项目经理接到一个复杂项目。你不会自己从头干到尾而是会拆解任务看看团队里谁擅长市场调研技能A谁擅长财务分析技能B谁擅长撰写方案技能C然后协调他们按顺序或并行工作并时刻关注每个人的进度和产出追溯必要时调整分工。SkillTrace就是为LLM智能体配备这样一个“虚拟项目经理”和一份清晰的“团队技能表”。这个框架对于任何希望构建能处理多步骤、可复用、高可靠复杂任务的智能体系统开发者来说都具有很强的吸引力。无论是自动化数据分析流水线、智能客服工单处理还是代码生成与审查只要任务能分解SkillTrace的思路就能提供一种更优雅、更可控的解决方案。2. 核心架构查询-技能图与寻踪机制详解要理解SkillTrace必须吃透它的两大基石Query-Skill Graph查询-技能图和SkillTrace技能寻踪机制。这不仅仅是两个新名词更代表了一种组织和管理智能体能力的范式转变。2.1 查询-技能图构建智能体的“技能宇宙”传统的智能体技能管理可能是简单的列表或通过提示词描述。这种方式松散、难以检索更无法体现技能之间的关系。查询-技能图则将其结构化、图谱化。1. 图的构成要素技能节点Skill Node这是图的核心。每个节点代表一个可执行的最小功能单元。例如search_web: 使用搜索引擎获取信息。python_calculate: 执行一段Python代码进行数值计算。sql_query: 对数据库执行SQL查询。text_summarize: 对长文本进行摘要。send_email: 发送邮件。 每个技能节点都需要精确定义其输入格式、输出格式、功能描述以及所需的工具/API接口。查询节点Query Node / 状态节点State Node代表用户提出的原始问题或任务执行过程中的中间状态。例如用户查询“公司Q3营收增长率是多少”就是一个初始查询节点。经过search_web技能后得到的“网页文本内容”就是一个新的状态节点。边Edge连接节点与节点。边是有向的并且带有“条件”或“转化关系”。它定义了从哪个状态通过哪个技能可以转化到哪个新状态。例如(状态: “用户原始问题”) --[技能: parse_intent]-- (状态: “解析后的意图: {action: ‘查询’, entity: ‘Q3营收’})。2. 图是如何构建的图的构建不是一蹴而就的而是随着智能体系统的成长而演化的通常有两种方式人工设计冷启动对于垂直领域由领域专家预先定义一组核心技能及其关系。这是保证初期系统稳定可靠的关键。自动挖掘与学习通过分析历史任务执行日志利用LLM或图学习算法自动发现频繁共现的技能序列并将其抽象为图中的常见路径。例如系统发现“查询天气-生成出行建议-格式化日历事件”经常连续发生就可以在图中强化这条路径。3. 图的优势显式化知识将隐式的“模型可能知道怎么做”变成了显式的“系统明确提供了这个技能”。可组合性通过图的遍历可以自然地组合多个技能形成工作流。可发现性给定一个查询可以通过图搜索算法如基于嵌入的相似度搜索快速找到相关的技能和路径。2.2 技能寻踪机制智能体的“动态导航仪”有了静态的技能图还需要一个动态的执行引擎这就是SkillTrace。它的工作流程可以类比为导航软件意图解析与图匹配接收到用户查询后首先不是让LLM直接行动而是让一个轻量级的LLM或分类器解析查询意图并将其映射到查询-技能图中的初始节点。同时在图中的相关技能节点附近进行“激活”。路径规划基于当前状态初始查询和目标状态任务完成在图中进行搜索规划出一条或多条可能的技能执行路径。这个过程可以由一个专门的“规划器”LLM来完成它参考图谱结构进行推理。例如对于“总结A公司最新财报”规划器可能规划出路径[search_web - extract_financial_data - text_summarize]。迭代执行与状态追踪按照规划路径依次调用技能。关键在这里每执行完一个技能都会生成一个明确的状态节点记录执行结果和当前上下文。SkillTrace会持续维护一个执行轨迹这个轨迹就是一系列状态技能新状态的三元组序列。这提供了完整的可追溯性。动态调整与回溯这是SkillTrace区别于链式调用的精髓。如果某个技能执行失败如API错误或产生的结果不符合预期由验证器或LLM判断系统不会直接报错终止。而是可以回溯回到上一个状态节点。重规划基于当前可能是失败的状态重新在图中寻找替代路径。例如sql_query失败后可能回溯并尝试search_web来获取近似信息。并行探索在不确定性高的分支可以同时尝试多条路径最后选择结果最好的。注意这个“规划-执行-观察-重规划”的循环与ReAct、AutoGPT等框架的思想一脉相承但SkillTrace通过显式的图结构为规划和回溯提供了更坚实、更高效的依据避免了纯LLM推理带来的幻觉和效率低下问题。3. 实操构建从零搭建一个简易SkillTrace系统理解了原理我们动手搭建一个简化版的SkillTrace系统以“获取某科技公司股价并判断其涨跌趋势”为例。我们将使用Python和LangChain作为基础工具但核心逻辑是框架无关的。3.1 第一步定义技能库与构建技能图我们首先定义几个核心技能并用网络图库如networkx在内存中构建图结构。import networkx as nx from typing import Dict, Any, Callable from langchain.tools import Tool from langchain.agents import AgentExecutor # 假设我们有一些基础的LangChain Tool from some_tools import StockPriceTool, NewsSearchTool, SentimentAnalysisTool, CalculationTool class SkillNode: def __init__(self, name: str, description: str, tool: Tool, input_schema: Dict, output_schema: Dict): self.name name self.description description # 用于图匹配时的技能描述 self.tool tool # 实际执行的工具 self.input_schema input_schema self.output_schema output_schema # 初始化技能节点 skill_fetch_price SkillNode( namefetch_stock_price, descriptionFetches the current and recent historical price for a given stock ticker symbol., toolStockPriceTool(), input_schema{ticker: string}, output_schema{price: number, history: list} ) skill_search_news SkillNode( namesearch_company_news, descriptionSearches for the latest news articles related to a given company name., toolNewsSearchTool(), input_schema{company_name: string}, output_schema{news: list} ) skill_analyze_sentiment SkillNode( nameanalyze_sentiment, descriptionAnalyzes the sentiment (positive/negative/neutral) of a given text or list of texts., toolSentimentAnalysisTool(), input_schema{text: string}, output_schema{sentiment: string, confidence: number} ) skill_calculate_trend SkillNode( namecalculate_trend, descriptionPerforms simple statistical calculations (e.g., moving average) on a series of numerical data to determine trend., toolCalculationTool(), input_schema{data_series: list, window: number}, output_schema{trend: string, slope: number} ) # 构建查询-技能图 skill_graph nx.DiGraph() # 添加技能节点 all_skills [skill_fetch_price, skill_search_news, skill_analyze_sentiment, skill_calculate_trend] for skill in all_skills: skill_graph.add_node(skill.name, node_typeskill, objskill) # 添加状态节点和边这里简化用字符串代表状态 # 状态节点用户查询 - 解析后的意图 - 股价数据 - 新闻数据 - 情感结果 - 趋势结果 skill_graph.add_node(user_query, node_typestate) skill_graph.add_node(parsed_intent, node_typestate) skill_graph.add_node(stock_data, node_typestate) skill_graph.add_node(news_data, node_typestate) skill_graph.add_node(sentiment_result, node_typestate) skill_graph.add_node(trend_result, node_typestate) # 添加边定义状态如何通过技能转换 # 边(from_state, to_state, key{skill: skill_name}) skill_graph.add_edge(user_query, parsed_intent) # 由LLM解析不算技能边 skill_graph.add_edge(parsed_intent, stock_data, skillfetch_stock_price) skill_graph.add_edge(parsed_intent, news_data, skillsearch_company_news) skill_graph.add_edge(stock_data, trend_result, skillcalculate_trend) skill_graph.add_edge(news_data, sentiment_result, skillanalyze_sentiment) # 可以定义更复杂的边例如情感结果也能影响趋势判断作为上下文 skill_graph.add_edge(sentiment_result, trend_result, skillcalculate_trend) # 这里calculate_trend技能需要能接收额外上下文这个图虽然简单但已经刻画了核心关系从解析后的意图可以并行获取股价和新闻然后分别进行趋势计算和情感分析。3.2 第二步实现SkillTrace执行引擎执行引擎需要处理规划、执行和状态追踪。class SkillTraceEngine: def __init__(self, graph: nx.DiGraph, llm): self.graph graph self.llm llm # 用于规划和决策的LLM self.execution_trace [] # 记录轨迹[ (state, skill, result_state) ] def parse_intent(self, user_query: str) - Dict: 使用LLM将用户查询解析为结构化意图 prompt f 将用户查询解析为意图。可用的技能有{[s.name for s in all_skills]}。 查询{user_query} 输出JSON格式{{goal: 任务目标描述, required_data: [需要获取的数据类型], potential_skills: [可能用到的技能名]}} response self.llm.invoke(prompt) # 简化为解析JSON实际需要更健壮的解析 import json return json.loads(response.content) def plan_path(self, start_state: str, goal_description: str) - list: 在图上游走规划一条从起始状态到目标状态的技能路径 # 简化版使用LLM基于图结构进行规划 # 1. 获取从start_state出发的所有出边即可能的下一步技能 possible_next list(self.graph.edges(start_state, dataTrue)) skill_options [edge[2].get(skill) for edge in possible_next if edge[2].get(skill)] prompt f 你是一个任务规划器。当前状态是{start_state}。 可用技能选项{skill_options}。 你的目标是{goal_description}。 请根据目标选择最合适的一个或多个技能按顺序并说明理由。输出格式[skill_a, skill_b, ...] plan_response self.llm.invoke(prompt) # 解析出技能列表 # ... 解析逻辑 ... planned_skills [fetch_stock_price, calculate_trend] # 假设解析结果 return planned_skills def execute_skill(self, skill_name: str, input_data: Dict) - Dict: 执行单个技能 # 找到技能节点 skill_node None for n in self.graph.nodes(dataTrue): if n[1].get(node_type) skill and n[0] skill_name: skill_node n[1][obj] break if not skill_node: raise ValueError(fSkill {skill_name} not found in graph.) # 调用工具 result skill_node.tool.run(input_data) return {skill: skill_name, input: input_data, output: result} def run(self, user_query: str): 主运行循环 print(f开始处理查询: {user_query}) # 1. 解析意图 intent self.parse_intent(user_query) current_state parsed_intent self.execution_trace.append((user_query, None, current_state)) # 2. 规划初始路径目标来自intent[goal] goal intent[goal] skill_plan self.plan_path(current_state, goal) # 3. 迭代执行 for skill_name in skill_plan: print(f准备执行技能: {skill_name}) # 准备输入数据这里需要根据当前状态和技能输入模式来构建是难点 # 简化假设输入数据可以从上一个状态的结果中提取 skill_input self._prepare_input_for_skill(skill_name, current_state) try: result self.execute_skill(skill_name, skill_input) # 创建新状态节点可以用技能名结果哈希来命名 new_state fstate_after_{skill_name} self.execution_trace.append((current_state, skill_name, new_state)) print(f技能 {skill_name} 执行成功。结果摘要: {str(result[output])[:100]}...) current_state new_state # 这里可以将result[output]存储到状态上下文中供后续技能使用 except Exception as e: print(f技能 {skill_name} 执行失败: {e}) # 触发回溯与重规划 recovery_plan self._replan_on_failure(current_state, skill_name, e) if recovery_plan: skill_plan recovery_plan # 调整后续计划 print(f已重新规划路径: {recovery_plan}) else: print(重规划失败任务终止。) break # 4. 汇总最终结果 final_result self._aggregate_results(self.execution_trace) print(f任务完成。最终结果: {final_result}) print(f完整执行轨迹: {self.execution_trace}) return final_result def _prepare_input_for_skill(self, skill_name: str, current_state: str) - Dict: 根据当前状态准备技能输入。这是一个复杂的状态管理问题此处简化。 # 实际项目中需要维护一个全局的“状态上下文字典”记录每个状态节点对应的具体数据。 # 这里返回一个示例输入。 if skill_name fetch_stock_price: return {ticker: AAPL} # 假设从意图中解析出了股票代码 elif skill_name calculate_trend: return {data_series: [150, 152, 149, 155, 158], window: 3} return {} def _replan_on_failure(self, failed_state: str, failed_skill: str, error: Exception) - list: 失败回溯与重规划逻辑 # 1. 回溯到上一个安全状态 # 从execution_trace中找到failed_state的上一个状态 # 2. 基于当前状态和错误信息重新规划路径可能选择替代技能 # 例如如果 fetch_stock_price API失败可以尝试 search_company_news 来间接获取股价信息 replan_prompt f 执行失败。当前状态{failed_state}。失败技能{failed_skill}。错误{error}。 请尝试规划一条替代路径来完成目标。可用的其他技能有{[s.name for s in all_skills if s.name ! failed_skill]}。 输出新的技能序列。 # 调用LLM进行重规划... new_plan [search_company_news, analyze_sentiment] # 假设的替代方案 return new_plan这个引擎实现了最基础的运行循环解析、规划、执行、简单回溯。在实际应用中_prepare_input_for_skill和_replan_on_failure是最需要精心设计的部分它们直接决定了系统的智能程度和鲁棒性。3.3 第三步集成与测试将上述模块集成并用一个查询进行测试。# 假设我们已经有了一个LLM实例如通过LangChain调用OpenAI API from langchain_openai import ChatOpenAI llm ChatOpenAI(modelgpt-3.5-turbo) # 初始化引擎 engine SkillTraceEngine(skill_graph, llm) # 运行测试 user_query 苹果公司最近的股价趋势怎么样 # 注意由于我们使用了模拟的LLM和工具这里实际运行需要真实的API配置。 # final_result engine.run(user_query) print(引擎初始化完成技能图已加载。) print(用户查询示例, user_query) print(规划路径可能为[fetch_stock_price, calculate_trend])通过这个简易实现我们可以看到SkillTrace框架的核心代码形态。它把任务分解、技能调用、状态管理都纳入了图结构的管控之下为构建更复杂的智能体提供了清晰的蓝图。4. 关键挑战与优化策略实录在实际构建和运用SkillTrace这类系统时你会遇到一系列教科书上不会写的挑战。下面是我从实验和项目实践中总结的几个核心痛点及应对策略。4.1 技能图的构建与演化质量决定天花板挑战一技能粒度的把握技能定义得太粗比如一个“分析财报”技能内部逻辑复杂难以复用和调试。定义得太细比如“打开文件”、“读取一行”、“解析逗号”会导致图过于庞大规划复杂度爆炸。实操心得遵循“单一职责”和“高内聚”原则。一个技能应该完成一件边界清晰、输入输出明确、功能相对独立的事情。一个好的检验标准是这个技能是否可以被其他完全不同的任务流轻松调用例如“提取文本中的日期”是一个好技能“处理PDF文档”就太粗了应该拆分为“PDF转文本”、“解析文本结构”等更细的技能。挑战二边的条件与动态性图中如果只有固定的边系统会非常僵化。现实任务中从状态A到状态B是否启用技能C往往取决于A的具体内容。优化策略给边加上“条件函数”或“权重”。例如从“解析后的意图”到“执行SQL查询”这条边可以附加一个条件if intent[entity_type] structured_data。或者使用一个小的分类器模型来预测给定状态下各条出边的适用概率作为规划器的参考。挑战三图的冷启动与自动化生长手动维护一个大图是痛苦的。如何让图自我生长记录与挖掘详细记录每个任务的执行轨迹即SkillTrace本身。定期离线分析这些轨迹发现频繁出现的技能序列A-B-C如果这个序列稳定且通用就可以考虑将其抽象为一个新的“复合技能节点”加入图中或者在图里添加一条高权重的“快捷路径”。LLM辅助生成用LLM分析任务描述和已有的技能库让其建议新的技能或边。例如给LLM看“我们现有技能爬取网页、总结文本。用户常问‘对比A和B产品的优缺点’”LLM可能会建议新增一个“对比分析”技能或建议建立从“网页内容A”和“网页内容B”状态到一个新的“对比结果”状态的边。4.2 规划器的设计在探索与效率间平衡挑战四规划搜索空间爆炸对于复杂的图从起点到终点的路径可能成千上万。穷举搜索不现实。分层规划借鉴经典AI的HTN分层任务网络。先进行高层抽象规划如“获取信息-分析-呈现”再对每一层在子图中进行细化规划。启发式搜索为图中的边赋予代价如预估执行时间、调用成本、可靠性评分使用A*等算法搜索代价最小的路径。LLM可以作为优秀的启发式函数评估某个技能对当前目标的“有用性概率”。Few-shot规划在提示词中给LLM规划器提供几个类似的、成功的规划示例能极大提高其规划准确率。挑战五处理不确定性LLM规划器可能出错技能执行可能返回意外结果。规划-执行-验证循环不要一次性规划完整路径然后盲目执行。采用“滚动的视野”。例如每次只规划未来2-3步执行一步后用验证器可以是规则也可以是另一个LLM检查结果是否符合预期再基于新状态规划下一步。这增加了灵活性但也会增加延迟。多路径探索与投票对于关键分支同时规划几条备选路径并行执行如果成本允许最后用一个“裁决器”选择最佳结果。这类似于集成学习的思想。4.3 状态管理与上下文传递挑战六技能间的数据流转这是最繁琐但最重要的工程细节。技能A的输出如何精准地变成技能B的输入统一状态上下文对象维护一个全局的、版本化的上下文字典。每个状态节点对应上下文的一个快照或一个命名空间。技能执行时从上下文中按需提取参数执行后将输出写回上下文指定位置。输入输出模式匹配为每个技能定义严格的输入模式JSON Schema和输出模式。规划器或调度器负责在运行时将上游技能的输出模式“适配”到下游技能的输入模式。这可能需要一些简单的数据转换函数如提取字段、转换格式。LLM作为数据协调员对于复杂的、非结构化的数据传递可以让一个小型LLM如GPT-3.5充当“协调员”阅读上游输出然后按照下游输入的要求重新组织或总结信息。这虽然增加了调用但极大地增强了灵活性。4.4 评估与调试让系统变得可观测挑战七如何评估SkillTrace系统的优劣不能只看最终答案对不对。多维度指标任务成功率最核心的指标。平均路径长度完成任务的技能调用次数。过短可能技能太粗过长可能规划低效。回溯/重规划频率频率高可能说明图不完善或规划器不稳定。技能利用率是否有技能从未被调用是否有技能成为瓶颈可视化追踪将每一次执行的SkillTrace即状态-技能序列可视化出来是调试的利器。你能一眼看出系统在哪里“绕了远路”在哪里“卡住循环”。这比看日志直观得多。避坑技巧在项目早期不要过度追求全自动的图学习和复杂的动态规划。先用一个小而精的、手工构建的核心技能图跑通几个核心用例。这个“最小可行图”能帮你快速验证架构的可行性并暴露出状态管理、错误处理等底层基础设施的问题。在此基础上再通过记录轨迹、分析日志逐步自动化图的扩展和优化。很多团队一开始就想做一个“万能大脑”结果在无限复杂中迷失不如先做一个在特定领域可靠的“专家系统”。5. 典型应用场景与扩展思考SkillTrace框架的思想并不局限于我们演示的简单示例。它的核心价值在于为复杂、可组合的智能体任务提供了结构化的管理范式。下面看几个更深度的应用场景。场景一企业级数据洞察助手在一个大型企业里业务人员经常需要跨多个系统获取数据并分析。可以构建一个企业内部的SkillTrace系统。技能库query_sales_db(查询销售数据库)、fetch_crm_record(获取客户信息)、call_bi_api(调用商业智能平台API)、generate_powerpoint_snippet(生成PPT图表代码)、translate_to_chinese(翻译)。工作流用户提问“请帮我准备一份关于华东区上周高端客户销售额的简报并对比前一周数据”。系统规划路径parse_query-query_sales_db(按区域、时间、客户层级筛选) -fetch_crm_record(获取高端客户详情) -call_bi_api(计算环比) -generate_powerpoint_snippet(生成趋势图) -translate_to_chinese(最终简报)。如果query_sales_db因系统维护失败可以回溯并尝试从数据仓库的备份表另一个技能中获取近似数据。优势将散落在各处的数据API和能力统一管理提供了稳定、可追溯的数据服务流水线。场景二自动化代码生成与审查流水线对于开发任务可以构建一个编码智能体。技能库analyze_requirement(分析需求)、search_similar_code(搜索类似代码片段)、generate_function(生成函数)、run_unit_test(运行单元测试)、static_analysis(静态代码检查)、explain_code(解释代码)。工作流用户提出“帮我写一个Python函数用归并排序算法排序列表”。路径可能为analyze_requirement-search_similar_code(寻找排序算法示例) -generate_function-run_unit_test(测试函数正确性)。如果测试失败回溯到generate_function步骤结合测试错误信息重新生成。甚至可以并行执行static_analysis确保代码风格和质量。优势将代码生成从单次LLM调用变成了一个可调试、可验证、可迭代的工程化流程。场景三研究助理与知识整合辅助研究人员快速调研一个陌生领域。技能库academic_search(学术搜索)、pdf_download_and_parse(下载并解析PDF)、extract_key_claims(提取核心观点)、find_citations(查找引用关系)、synthesize_report(综合报告)。工作流用户输入“关于‘注意力机制在医疗影像中的应用’的最新研究进展”。系统规划academic_search- (对多篇文献并行)pdf_download_and_parse-extract_key_claims-find_citations(构建文献网络) -synthesize_report(生成综述报告)。优势自动化了从信息搜集到知识整合的全过程并且每个步骤都可追溯保证了最终报告的信息来源可靠。扩展思考SkillTrace与AI Agent生态的融合SkillTrace的理念可以很好地与现有的Agent框架结合提升其能力上限与AutoGen / CrewAI 结合在这些多智能体框架中每个Agent可以视为一个“宏技能”。SkillTrace可以用于管理这些Agent之间的协作流程规划哪个Agent在何时被激活处理它们之间的交互状态。与LangChain / LlamaIndex 结合LangChain的Tool和Agent本身就是技能和简单规划的体现。SkillTrace可以作为其上层的“元协调器”管理更复杂的、涉及多个Tool和多个Agent调用序列的任务并提供更强的回溯和错误恢复能力。走向“技能市场”如果SkillTrace的接口标准化个人或组织开发的技能可以发布到一个公共的“技能市场”。智能体在需要时可以动态地发现、下载并集成新技能到自己的图中实现能力的无限扩展。这将是构建真正通用人工智能AGI的重要一步。构建SkillTrace系统的过程本质上是在为LLM智能体注入“结构化思维”和“系统化记忆”。它可能不会在每一个简单任务上都超越直接的Prompt工程但对于那些需要可靠性、可解释性和复杂组合能力的生产级应用它提供了一条值得深入探索的路径。这个框架目前还在学术界和工业界的探索前沿相关的开源项目和实践案例会越来越多但核心思想——用图来组织知识用寻踪来管理过程——已经为我们点亮了一盏明灯。