尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

TRACE框架:让LLM智能体通过跨步骤证据聚合实现深度推理

TRACE框架:让LLM智能体通过跨步骤证据聚合实现深度推理 1. 项目概述当LLM智能体学会“复盘思考”最近在折腾LLM驱动的自主智能体LLM Agents时我总被一个问题困扰智能体在复杂任务中比如写一份多步骤的市场分析报告或者调试一段有多个依赖的代码经常表现得像个“健忘的探险家”。它走一步看一步执行到后面步骤时很容易忘记或忽略前面步骤中已经发现的关键线索比如第一步从网页抓取的数据里提到了一个关键竞争对手但第三步做竞品分析时却完全没用到这个信息。这种“短视”行为严重限制了智能体处理长链条、需要全局规划任务的潜力。这正是“TRACE: Trajectory Reasoning through Adaptive Cross-Step Evidence Aggregation for LLM Agents”这个研究试图解决的核心痛点。简单来说TRACE 是一种让LLM智能体学会“复盘”和“关联思考”的推理框架。它不再把任务执行看作一连串孤立的动作而是视为一个完整的“轨迹”Trajectory。在这个轨迹中TRACE 会动态地、自适应地聚合跨越多个步骤的“证据”Evidence帮助智能体在每一步都能基于更全面的信息做出更明智的决策。想象一下你是一位侦探在破案。传统的智能体就像只盯着手头最新的一条线索而TRACE则像一位老练的侦探他有一个线索板会把所有已发现的线索证据按照关联性整理好。每获得一个新线索他不仅看这个新线索本身还会回头审视线索板看看新线索和哪些旧线索能联系起来从而修正或深化对案件的理解。TRACE做的就是这个“线索板”和“动态关联”的工作只不过它的“线索”是智能体在任务执行过程中产生的观察、工具调用结果、中间结论等。对于任何正在开发或研究LLM智能体的工程师、研究员或是希望将智能体应用于复杂业务流程自动化的开发者来说理解TRACE的原理和实现思路都极具价值。它能显著提升智能体在规划、工具调用、反思和长期任务执行中的稳定性和成功率。2. TRACE核心设计思路拆解从“线性执行”到“证据图谱”要理解TRACE我们得先看看主流LLM智能体通常是怎么工作的。目前大多数架构无论是ReAct、AutoGPT还是LangChain的AgentExecutor其核心循环可以概括为思考Think- 执行动作Act- 观察结果Observe。这个循环的上下文Context通常是固定长度的或者采用简单的滑动窗口。这就导致了一个根本性问题随着步骤增加早期步骤的关键信息很容易被挤出上下文窗口或者即使还在窗口内也因为距离当前步骤太远而被模型“忽视”。智能体缺乏一种机制去主动地、结构化地记住和利用整个任务历史中的精华。TRACE的设计哲学是颠覆性的。它认为任务轨迹中的每一步都产生“证据”这些证据的价值并非均等且它们之间的关联网络才是支持深度推理的关键。因此TRACE的核心思路围绕两点展开证据的抽象与存储以及证据的自适应聚合。2.1 证据的抽象从原始观察到结构化知识单元首先TRACE并不直接将每一步的原始文本如工具调用的输出扔进一个“杂物堆”。它引入了一个“证据抽象”层。每当智能体完成一个Observe步骤TRACE会调用一个“证据提取器”Evidence Extractor。这个提取器通常本身也是一个LLM调用其任务是对当前的观察结果进行分析和摘要提炼出结构化的知识单元。例如智能体执行了一个动作“搜索‘2024年新能源汽车电池技术最新进展’”并得到了一个长达十段的网页摘要。原始观察是冗长的。证据提取器可能会生成如下几条结构化证据证据1类型事实: “固态电池能量密度预计在2024年底达到400Wh/kg。”证据2类型公司: “公司A和公司B在硫化物固态电解质路径上领先。”证据3类型趋势: “钠离子电池因成本优势在低端车型渗透加速。”这些证据被存储在一个可扩展的“证据池”Evidence Pool或“证据图谱”Evidence Graph中。每条证据可能附带元数据如来源步骤、置信度、类型标签等。这一步至关重要它将非结构化的任务历史转化为了一个结构化的、可查询的知识库。2.2 自适应跨步骤聚合动态相关的信息检索这是TRACE的“灵魂”所在。当智能体进入新一步的Think阶段时它不再仅仅依据上一步的观察和固定长度的历史来思考。TRACE会启动一个“证据检索与聚合”Evidence Retrieval Aggregation模块。这个模块的工作流程如下理解当前上下文基于智能体当前的状态、最新的动作意图或初步的“思考”形成一个“查询”Query。这个查询旨在描述当前步骤需要什么样的背景信息。从证据池中自适应检索不是检索所有历史证据而是根据“查询”与每条证据的“相关性”进行检索。相关性计算可能基于向量相似度将查询和证据编码为向量也可能基于LLM的直接判断。关键在于这种检索是“跨步骤”的可以召回步骤1、步骤5等任何历史步骤中的高相关证据。证据聚合与呈现检索到的多条证据会被整合、去重并可能根据与当前问题的逻辑关系进行排序或重述然后以清晰、简洁的形式注入到当前LLM智能体的提示词Prompt中。这个过程是“自适应”的因为每一步检索的证据集合都是不同的完全取决于当前步骤的需求。它模拟了人类在解决问题时从记忆中动态提取相关经验片段的能力。注意证据聚合不是简单拼接。直接将10条证据文本塞进Prompt可能会超出上下文长度并造成干扰。TRACE在实践中通常采用“摘要式聚合”或“选择性注入”即用另一个LLM调用对检索到的证据进行二次摘要只保留与当前步骤最核心相关的信息或者以关键点列表的形式呈现。2.3 整体架构与工作流结合以上两点TRACE增强的LLM智能体工作流如下图所示此处以文字描述初始化任务开始证据池为空。循环开始 a.规划/思考ThinkLLM接收包含以下内容的提示 - 任务目标 - 允许的动作工具 -从证据池中自适应检索并聚合的、与当前思考方向相关的历史证据- 上一步的观察标准部分 LLM基于此生成下一步动作Action。 b.执行动作Act执行LLM指定的动作如调用API、运行代码。 c.观察结果Observe获取动作的原始输出。 d.证据提取Extract Evidence调用证据提取器将原始观察提炼为一条或多条结构化证据存入证据池。判断终止检查任务是否完成或达到终止条件。若未完成回到步骤2a。这个流程使得“思考”环节的输入质量发生了质变智能体具备了持续的、结构化的“记忆”和“联想”能力。3. 核心模块深度解析与实操要点理解了宏观思路我们来深入拆解TRACE的几个核心模块并探讨在实际实现中的关键细节和“坑”。3.1 证据提取器Evidence Extractor的设计与调优证据提取器是将原始文本转化为知识单元的第一关其质量直接决定了证据池的“营养”价值。设计模式基于指令的LLM调用这是最灵活的方式。设计一个详细的Prompt要求模型从文本中提取特定类型、格式的证据。指令示例 你是一个信息提取专家。请从以下文本中提取关键证据。证据应以“- [证据类型] 证据内容”格式列出确保内容客观、简洁。 证据类型包括[事实 数据 观点 方法 问题 结论]。 文本{原始观察文本}微调专用模型对于垂直领域如医疗、法律可以微调一个中小型模型如Llama-3-8B专门做信息抽取以降低成本和延迟。混合模式先用规则或NER模型抽取实体、日期、数字等结构化信息再用LLM进行关系归纳和摘要。实操要点与避坑指南控制证据粒度证据太粗如“本文介绍电池技术”则无用太细如“某实验电压为3.7V”则会导致证据池碎片化。需要根据任务域调整。一个经验法则是一条证据应能表达一个相对完整的事实、发现或观点。处理不确定性原始观察可能包含矛盾或不确定信息。可以在证据元数据中加入置信度字段或让提取器标记“可能”、“据说”等不确定性词汇。避免信息丢失LLM做摘要时可能过度简化。重要数据如具体数值、百分比应优先保留。可以设计模板如“[指标]从[旧值]提升至[新值]”来强制结构化。性能考量每一步都调用LLM进行证据提取会显著增加延迟和成本。可以考虑异步提取或在确定原始观察信息量大时才触发提取。3.2 证据池Evidence Pool的实现方案证据池是TRACE的存储核心其设计影响检索效率和效果。方案选择向量数据库方案推荐将每条证据文本通过嵌入模型如text-embedding-3-small转换为向量存入向量数据库如Chroma, Weaviate, Pinecone。检索时将当前查询也向量化进行相似度搜索。这是实现“自适应”检索最自然的方式。优势支持语义检索能发现字面不匹配但含义相关的证据。挑战需要维护向量库嵌入模型的质量直接影响相关性。图数据库方案如果证据间的关系非常重要如A证据支持B证据C证据与D证据矛盾可以将证据作为节点关系作为边存入图数据库如Neo4j。检索可以通过图遍历进行。优势能显式建模和利用证据间的逻辑关系支持更复杂的推理。挑战构建和维护图结构更复杂需要更精细的证据提取来定义关系。混合方案用向量数据库做初步的语义召回再用一个轻量级逻辑层或另一个LLM调用对召回的证据进行精排和关系分析。实操配置示例以Chroma为例import chromadb from sentence_transformers import SentenceTransformer # 初始化嵌入模型和客户端 embedder SentenceTransformer(all-MiniLM-L6-v2) # 轻量级效果不错 chroma_client chromadb.PersistentClient(path./evidence_db) collection chroma_client.get_or_create_collection(nametask_evidence) # 存储证据 def store_evidence(evidence_text, step_id, metadata): embedding embedder.encode(evidence_text).tolist() collection.add( documents[evidence_text], embeddings[embedding], metadatas[{**metadata, step: step_id}], ids[fev_{step_id}_{len(collection.get()[documents])}] ) # 检索相关证据 def retrieve_evidence(query, top_k5): query_embedding embedder.encode(query).tolist() results collection.query( query_embeddings[query_embedding], n_resultstop_k ) # results 包含 documents, metadatas, distances return results注意向量检索的“相关性”不一定等于“有用性”。一个在向量空间接近当前查询的历史证据可能在逻辑上已经过时或被推翻。因此精排re-ranking步骤有时是必要的。3.3 自适应聚合器Adaptive Aggregator的策略检索到一批相关证据后如何将它们有效地整合到给LLM的提示中常见策略列表摘要式将检索到的证据如top-5以编号列表的形式直接放入Prompt。简单直接但可能占用大量Token。相关历史证据 1. [证据A文本] 2. [证据B文本] ...LLM摘要式调用LLM对检索到的证据集合进行总结生成一个连贯的段落。这能节省Token并提高可读性但存在摘要过程中丢失关键细节的风险。请基于以下多条证据生成一个简洁的摘要突出与当前问题“{当前查询}”最相关的部分 证据列表[证据1 证据2...]动态选择式不聚合所有证据而是让一个“路由”模型或基于启发式规则如证据来源步骤的新旧、置信度选择最关键的1-2条证据注入。这在上下文长度紧张时非常有效。分层注入式在Prompt中开辟两个部分“核心相关证据”1-2条和“背景参考证据”列表形式。让LLM优先关注核心部分。选择依据任务复杂度对于需要严密逻辑链的任务如数学证明、代码调试建议使用“列表摘要式”保留原始细节供LLM推敲。上下文窗口如果模型上下文有限如4K必须采用“动态选择式”或“LLM摘要式”。延迟要求“LLM摘要式”会增加一次模型调用增加延迟。如果对延迟敏感应选择其他方式。4. 实现TRACE一个模块化代码框架理论说了这么多我们来动手搭建一个简化版的TRACE框架。我们将使用LangChain作为智能体基础但核心思想是框架无关的。4.1 环境准备与依赖安装首先确保你的环境已安装必要库。我们使用OpenAI的GPT-4作为核心LLMChroma作为向量存储LangChain来编排流程。pip install langchain langchain-openai chromadb sentence-transformers tiktoken设置你的OpenAI API密钥或其他LLM提供商密钥import os os.environ[OPENAI_API_KEY] your-api-key-here4.2 构建证据管理模块这是TRACE的核心。我们创建一个EvidenceManager类来统一处理证据的提取、存储和检索。from langchain.schema import BaseOutputParser from langchain.prompts import PromptTemplate from langchain_openai import ChatOpenAI, OpenAIEmbeddings from langchain.vectorstores import Chroma from langchain.schema import Document import json class EvidenceManager: def __init__(self, embedding_modeltext-embedding-3-small, persist_directory./chroma_evidence): # 用于证据提取的LLM self.extraction_llm ChatOpenAI(modelgpt-4-turbo-preview, temperature0) # 用于证据检索的嵌入模型和向量库 self.embeddings OpenAIEmbeddings(modelembedding_model) self.vectorstore Chroma( embedding_functionself.embeddings, persist_directorypersist_directory ) self.evidence_pool [] # 也可用内存列表备份 self.step_counter 0 # 证据提取提示词模板 self.extraction_prompt PromptTemplate( input_variables[raw_observation], template 你是一个精准的信息提取器。请从以下智能体执行动作返回的文本中提取出关键、具体、可被后续步骤复用的证据。 要求 1. 每条证据应是一个完整的句子或事实陈述。 2. 尽可能保持客观避免主观臆断。 3. 如果信息中有数据、名称、结论请优先提取。 4. 输出格式为JSON列表[\证据1文本\, \证据2文本\, ...] 原始观察文本 {raw_observation} 请输出JSON列表 ) def extract_evidence(self, raw_observation: str, step_info: dict) - list: 从原始观察中提取结构化证据 chain self.extraction_prompt | self.extraction_llm response chain.invoke({raw_observation: raw_observation}) try: # 解析LLM返回的JSON列表 evidence_list json.loads(response.content) if not isinstance(evidence_list, list): evidence_list [response.content] except json.JSONDecodeError: # 如果LLM没有返回标准JSON回退到按行分割 evidence_list [line.strip() for line in response.content.split(\n) if line.strip()] # 为每条证据创建Document对象存入向量库 docs [] for idx, ev_text in enumerate(evidence_list): doc Document( page_contentev_text, metadata{ step: self.step_counter, step_action: step_info.get(action, ), evidence_id: f{self.step_counter}_{idx} } ) docs.append(doc) if docs: self.vectorstore.add_documents(docs) self.evidence_pool.extend(evidence_list) # 内存备份 self.step_counter 1 return evidence_list def retrieve_relevant_evidence(self, query: str, top_k: int 3) - list: 根据当前查询检索相关证据 if not self.evidence_pool: # 证据池为空 return [] # 使用向量库进行相似度检索 retrieved_docs self.vectorstore.similarity_search(query, ktop_k) # 格式化返回结果 formatted_evidence [] for doc in retrieved_docs: formatted_evidence.append({ content: doc.page_content, source_step: doc.metadata.get(step, unknown), source_action: doc.metadata.get(step_action, ) }) return formatted_evidence def get_evidence_summary_for_prompt(self, current_thought: str) - str: 为提示词生成证据摘要部分 relevant_evidences self.retrieve_relevant_evidence(current_thought, top_k3) if not relevant_evidences: return 暂无相关历史证据。\n summary_lines [回顾以下历史证据可能对当前决策有帮助] for ev in relevant_evidences: summary_lines.append(f- (来自步骤{ev[source_step]}) {ev[content]}) return \n.join(summary_lines) \n4.3 集成TRACE的智能体执行循环接下来我们修改标准的ReAct循环将EvidenceManager集成进去。from langchain.agents import AgentExecutor, create_react_agent from langchain.tools import Tool from langchain import hub class TraceEnhancedAgentExecutor: def __init__(self, tools, llm): self.evidence_manager EvidenceManager() self.tools tools self.llm llm # 使用LangChain的ReAct提示词稍作修改以加入证据部分 self.prompt hub.pull(hwchase17/react) # 修改提示词模板加入证据占位符 self.prompt.template Answer the following questions as best you can. You have access to the following tools: {tools} Use the following format: Question: the input question you must answer Thought: you should always think about what to do. You have access to historical evidence that might help. Historical Evidence: {evidence} Thought: I now need to use a tool. Action: the action to take, should be one of [{tool_names}] Action Input: the input to the action Observation: the result of the action ... (this Thought/Action/Action Input/Observation can repeat N times) Thought: I now know the final answer Final Answer: the final answer to the original input question Begin! Question: {input} Thought: {agent_scratchpad} self.agent create_react_agent(llm, tools, self.prompt) self.agent_executor AgentExecutor(agentself.agent, toolstools, verboseTrue, handle_parsing_errorsTrue) def run(self, task_input: str, max_steps: int 10): 运行TRACE增强的智能体 intermediate_steps [] step_info {} for step in range(max_steps): # 1. 构建当前思考的上下文用于证据检索 # 这里简化处理将上一步的Observation和当前任务作为查询 retrieval_query fTask: {task_input}. Last observation: {intermediate_steps[-1][1] if intermediate_steps else None} # 2. 获取相关历史证据摘要 evidence_context self.evidence_manager.get_evidence_summary_for_prompt(retrieval_query) # 3. 准备Agent的输入注入证据上下文 # 这里需要根据具体的Agent框架调整输入格式 # 以LangChain ReAct为例我们需要动态修改prompt的输入 agent_input { input: task_input, evidence: evidence_context, # 注入的关键 agent_scratchpad: self._format_scratchpad(intermediate_steps) } # 4. 调用Agent进行思考和行动 try: response self.agent_executor.invoke(agent_input) action, action_input, observation self._parse_agent_response(response) except Exception as e: print(fStep {step} Agent execution error: {e}) break # 记录步骤 intermediate_steps.append((action, action_input, observation)) step_info {action: action, input: action_input} # 5. 从观察中提取证据并存储 self.evidence_manager.extract_evidence(observation, step_info) # 6. 检查是否完成 if Final Answer in response.get(output, ): print(fTask completed at step {step}) return response[output] return Max steps reached without final answer. def _format_scratchpad(self, steps): # 将历史步骤格式化为Agent所需的scratchpad字符串 # 实现略根据具体Agent类型定义 pass def _parse_agent_response(self, response): # 解析Agent返回的动作和观察 # 实现略根据具体Agent类型定义 pass4.4 示例一个简单的调研任务让我们定义一个简单的工具并看TRACE如何工作。# 模拟一个网络搜索工具 def web_search(query: str) - str: # 这里模拟一个固定的返回实际应调用搜索API mock_data { 特斯拉2024年销量: 根据最新财报特斯拉2024年Q1全球交付量约为42.3万辆同比增长约15%。, 比亚迪2024年销量: 比亚迪2024年第一季度新能源汽车销量达62.6万辆继续领跑全球市场。, 固态电池量产时间: 丰田宣布将于2027-2028年实现全固态电池的量产装车。宁德时代则表示其凝聚态电池已具备量产能力。 } return mock_data.get(query, fNo information found for {query}.) # 创建工具列表 tools [ Tool( nameWebSearch, funcweb_search, descriptionUseful for searching current information from the web. Input should be a search query string. ) ] # 初始化智能体 llm ChatOpenAI(modelgpt-4-turbo-preview, temperature0) trace_agent TraceEnhancedAgentExecutor(tools, llm) # 执行一个多步骤调研任务 result trace_agent.run( task_input请调研并比较特斯拉和比亚迪在2024年第一季度的市场表现并关注电池技术的最新进展。, max_steps6 ) print(result)在这个模拟流程中TRACE将如何工作步骤1智能体决定搜索“特斯拉2024年销量”。得到观察结果后证据提取器会生成类似“特斯拉2024年Q1交付量约42.3万辆同比增长15%”的证据存入池中。步骤2智能体思考“现在需要比亚迪的数据”。在思考阶段retrieve_relevant_evidence会以“比亚迪 2024 销量”为查询但可能也会召回步骤1中关于“销量”和“2024年”的证据提醒智能体关注同比数据。步骤3智能体搜索“比亚迪2024年销量”得到证据“比亚迪2024年Q1销量62.6万辆”。步骤4智能体思考“比较两者并关注电池”。此时检索查询可能包含“电池技术”它会召回步骤1和2中关于“销量”的证据用于比较同时指导下一步动作。步骤5智能体搜索“固态电池量产时间”得到丰田和宁德时代的信息作为新证据。步骤6智能体综合所有证据来自步骤1,2,5的历史证据被聚合到提示词中生成最终比较报告。可以看到在最后一步生成答案时智能体的提示词里包含了来自不同步骤的关键证据使其能进行真正的“跨步骤”比较和整合而不是仅基于最后一步的搜索结果。5. 效果评估、常见问题与优化策略实现了一个基础TRACE框架后我们如何评估其效果又会遇到哪些实际问题5.1 如何评估TRACE带来的提升不能只靠感觉需要设计评估指标任务完成率在基准测试任务集如WebArena、HotPotQA上对比使用TRACE和未使用TRACE的智能体成功完成任务的百分比。平均步骤数完成同一任务TRACE智能体是否能用更少的步骤更高效答案质量对于生成性任务使用LLM作为裁判LLM-as-a-Judge对比最终答案的准确性、完整性和连贯性。证据利用率人工或自动检查最终答案中有多少结论是直接基于被聚合的历史证据得出的。这可以衡量TRACE是否真的促进了信息复用。5.2 常见问题与排查技巧在实际部署中你可能会遇到以下问题问题1证据提取噪声大产生大量无用或重复证据。排查检查证据提取提示词是否足够明确。观察提取出的证据列表是否过于琐碎或包含大量无关信息。解决优化提示词在指令中强调“关键”、“具体”、“可复用”。指定更具体的证据类型。设置过滤阈值可以为提取的证据计算一个“信息量”分数如基于嵌入向量的范数或与查询的初始相关性过滤掉分数过低的证据。后处理去重在存入证据池前计算新证据与池中现有证据的相似度若高于阈值则合并或丢弃。问题2向量检索召回的证据不相关干扰决策。排查检查检索查询Query的构建是否合理。查询是否准确反映了当前步骤的信息需求解决优化查询构建不要简单使用上一步的观察。可以用一个小型LLM根据当前任务状态和上一步观察生成一个更精准的检索查询。使用混合检索结合关键词检索BM25和向量检索提高召回率。引入重排序Re-ranking使用一个交叉编码器模型如cross-encoder/ms-marco-MiniLM-L-6-v2对向量检索召回的前N个结果进行精排选择最相关的1-2个。元数据过滤例如可以设置只检索最近K个步骤的证据避免过于陈旧的证据干扰。问题3聚合后的证据文本过长挤占主要Prompt空间。排查检查top_k参数是否设置过大以及证据文本本身是否冗长。解决动态压缩对检索到的证据集合再次调用LLM进行极端摘要生成一句话总结。令牌预算管理为证据上下文设置固定的令牌预算如512 tokens。当证据文本超限时优先保留与查询相似度最高的或进行截断。分层注入如前所述将证据分为“核心”和“参考”只将核心证据详细展开。问题4智能体过度依赖历史证据陷入循环或不敢探索新动作。排查观察智能体轨迹是否反复检索和引用同一早期证据而忽略了新的、矛盾的观察结果。解决证据衰减机制为证据引入“新鲜度”或“权重”概念。随着步骤推进早期证据的权重逐渐降低。矛盾检测当新提取的证据与池中旧证据明显矛盾时触发一个“证据冲突解决”子流程让LLM判断哪个更可信或标记为“有争议”。在Prompt中强调当前观察在Prompt模板设计上明确区分“历史证据仅供参考”和“当前观察决策主要依据”。5.3 高级优化策略当基础版本运行稳定后可以考虑以下进阶优化证据关系图谱不仅存储证据节点还用LLM推断证据间的关系如“支持”、“矛盾”、“详述”构建证据图谱。检索时不仅可以找相关证据还可以沿着关系边找到关联证据簇实现更深度的推理。反思Reflection作为证据将智能体对自身行动的反思例如“上一步搜索的关键词太宽泛”也作为一种特殊类型的证据存入池中。这能帮助智能体避免重复犯错。子任务证据隔离对于非常复杂的任务可以自动识别子任务边界为不同的子任务创建不同的证据池或命名空间防止证据交叉污染。与长期记忆结合TRACE的证据池本质是任务的“工作记忆”。可以将其与智能体的“长期记忆”如向量数据库存储的过往任务知识连接起来在任务开始时先从长期记忆中召回相关背景知识作为初始证据。TRACE框架为LLM智能体赋予了更强大的轨迹推理能力但其引入的复杂性和额外开销延迟、成本也需要仔细权衡。在实际应用中建议从简单的任务和基础版本开始逐步迭代优化证据提取和检索策略使其真正成为提升智能体性能的利器而不是负担。
返回列表