LlamaIndex ReAct Agent 系统提示模板(System Header Template)深度解析与自定义指南 LlamaIndex ReAct Agent 系统提示模板System Header Template深度解析与自定义指南【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index导读system_header_template.md是 LlamaIndex ReActReasoning ActingAgent 的系统提示骨架定义了 Agent 如何感知可用工具、如何组织 Thought / Action / Action Input 输出、以及何时以 Answer 收尾的完整行为协议。本文将以该模板文件为主体结合 prompts.py、formatter.py、output_parser.py 与 react_agent.py 的源码实现逐段拆解模板结构、占位符机制、上下文注入原理并给出基于ReActChatFormatter的完整自定义实战方案。读完本文你将理解 ReAct Agent 提示词从模板到最终 LLM 输入消息的完整流水线并能够按需定制自己的系统提示模板。一、模板文件在仓库中的位置与加载方式该模板位于仓库路径 llama-index-core/llama_index/core/agent/react/templates/system_header_template.md是 ReAct Agent 默认系统提示的唯一数据源。它并不是被静态引用的文档而是在模块导入时被程序化读取的运行时资源# llama-index-core/llama_index/core/agent/react/prompts.py with ( Path(__file__).parents[0] / Path(templates) / Path(system_header_template.md) ).open(r, encodingutf-8) as f: __BASE_REACT_CHAT_SYSTEM_HEADER f.read()这段代码通过Path(__file__).parents[0] / templates / system_header_template.md定位模板文件即prompts.py同级的templates/目录读取全文后得到原始模板字符串。这意味着模板以UTF-8 编码的 Markdown 文本形式参与运行时 prompt 构建修改模板文件即可全局改变所有默认 ReAct Agent 的系统提示仓库只读实际使用中请通过代码自定义而非直接改文件模板中的占位符{tool_desc}、{tool_names}、{context_prompt}在后续环节被替换为真实内容。二、模板内容逐段拆解模板全文由四个功能段落组成每一段都对应 Agent 行为协议的一个关键约束1. 角色定位段You are designed to help with a variety of tasks, from answering questions to providing summaries to other types of analyses.这段定义了 Agent 的通用助手身份不限定具体领域为后续工具调用与多轮推理预留了开放性。在实际业务中开发者通常会在自定义模板中将其替换为更聚焦的角色描述例如你是一名金融顾问。2. 工具使用说明段## Tools You have access to a wide variety of tools. You are responsible for using the tools in any sequence you deem appropriate to complete the task at hand. This may require breaking the task into subtasks and using different tools to complete each subtask. You have access to the following tools: {tool_desc} {context_prompt}这里出现两个关键占位符{tool_desc}由 formatter.py 中的get_react_tool_descriptions()生成对每个注册工具输出如下固定格式 Tool Name: {tool.metadata.name} Tool Description: {tool.metadata.description} Tool Args: {tool.metadata.fn_schema_str}其中fn_schema_str是工具函数的 JSON Schema 字符串即工具参数的类型签名这保证了 LLM 能准确了解每个工具叫什么、干什么、参数长什么样。{context_prompt}上下文提示占位符。源码 prompts.py 基于原始模板派生了两个公开常量REACT_CHAT_SYSTEM_HEADER将{context_prompt}替换为空字符串replace({context_prompt}, , 1)即无额外上下文的默认版本CONTEXT_REACT_CHAT_SYSTEM_HEADER将{context_prompt}替换为一段带{context}占位符的上下文说明Here is some context to help you answer the question and plan: {context}两者的选择逻辑见ReActChatFormatter.from_defaults()未提供context时使用前者提供context时自动切换为后者确保自定义系统提示system prompt能被注入到模板中。3. 输出格式协议段ReAct 循环的核心## Output Format Please answer in the same language as the question and use the following format: Thought: The current language of the user is: (users language). I need to use a tool to help me answer the question. Action: tool name (one of {tool_names}) if using a tool. Action Input: the input to the tool, in a JSON format representing the kwargs (e.g. {{input: hello world, num_beams: 5}}) Please ALWAYS start with a Thought. NEVER surround your response with markdown code markers. You may use code markers within your response if you need to. Please use a valid JSON format for the Action Input. Do NOT do this {{input: hello world, num_beams: 5}}. If you include the Action: line, then you MUST include the Action Input: line too, even if the tool does not need kwargs, in that case you MUST use Action Input: {{}}. If this format is used, the tool will respond in the following format: Observation: tool response You should keep repeating the above format till you have enough information to answer the question without using any more tools. At that point, you MUST respond in one of the following two formats: Thought: I can answer without using any more tools. Ill use the users language to answer Answer: [your answer here (In the same language as the users question)] Thought: I cannot answer the question with the provided tools. Answer: [your answer here (In the same language as the users question)]这是模板信息密度最高的部分它定义了 ReAct 循环的完整状态机协议动作分支Thought:→Action:工具名取值来自{tool_names}→Action Input:必须为合法 JSON单引号形式被明确禁止观测回环工具执行结果以Observation:形式返回Agent 需循环Thought → Action → Observation直到信息充足终止分支信息充足或无法回答时必须以Thought:Answer:收尾语言要求必须使用与用户提问相同的语言回答格式约束必须以Thought:开头、禁止用 Markdown 代码块包裹输出、Action:出现则Action Input:必须同时出现无参数时也必须给Action Input: {}。这些协议并非仅停留在提示词层面——output_parser.py 用正则严格实现了同一套协议构成提示约束 解析校验的双重保障。例如extract_tool_use()用正则(?:\s*Thought: (.*?)|(.))\nAction: ([^\n\(\) ]).*?\nAction Input: .*?(\{.*\})提取 Thought / Action / Action Input而ReActOutputParser.parse()则按Action 优先于 Answer的规则action_idx answer_idx时优先解析为动作步骤从 LLM 输出中判定当前步是调用工具还是直接回答。这意味着模板怎么写解析器就怎么读两者必须保持一致。4. 对话历史锚点段## Current Conversation Below is the current conversation consisting of interleaving human and assistant messages.模板末尾的## Current Conversation标题是给后续消息的位置锚点提示 LLM 在此标题之后是交替出现的用户与助手消息序列。实际运行时formatter.py 会将模板渲染结果作为roleMessageRole.SYSTEM的首条消息其后依次拼接chat_history与推理历史reasoning_history推理步骤中ObservationReasoningStep以MessageRole.USER角色呈现其余以ASSISTANT角色呈现从而形成完整的 LLM 输入消息列表。三、模板如何被 ReAct Agent 使用完整调用链模板从静态文件到最终 LLM 输入经历了如下调用链prompts.py 读取模板文件派生出REACT_CHAT_SYSTEM_HEADER与CONTEXT_REACT_CHAT_SYSTEM_HEADER两个常量formatter.py 的ReActChatFormatter以system_header为字段默认值为REACT_CHAT_SYSTEM_HEADER在format()中调用self.system_header.format(**format_args)完成占位符替换tool_desc来自工具描述拼接tool_names来自工具名逗号拼接context在设置了self.context时注入react_agent.py 的ReActAgent.take_step()调用formatter.format(tools, chat_history, current_reasoning)得到input_chat交给 LLMLLM 输出经 output_parser.py 的ReActOutputParser.parse()解析为ActionReasoningStep继续调工具或ResponseReasoningStep终止并回答。值得注意的是workflow 版 ReActAgent 还内置了模板自动切换逻辑当设置了system_prompt时model_validator会把system_prompt写入formatter.context并检测当前system_header是否包含{context}占位符——若不含则自动替换为CONTEXT_REACT_CHAT_SYSTEM_HEADER保证自定义系统提示真正出现在系统消息中。这一行为在 test_prompt_customization.py 中有明确测试断言。四、实战自定义 ReAct 系统提示模板掌握了模板结构与注入机制后可以通过ReActChatFormatter进行三种层级的自定义。方式一注入上下文system prompt这是最常见的用法——通过from_defaults(context...)让模板自动切换为带{context}的版本from llama_index.core.agent.react.formatter import ReActChatFormatter formatter ReActChatFormatter.from_defaults( contextYou are a helpful financial advisor specializing in quarterly reports. ) # 此时 formatter.system_header 自动为 CONTEXT_REACT_CHAT_SYSTEM_HEADER # 渲染后系统消息中将包含 Here is some context to help you answer the question and plan:\n{context}等价地在使用 workflow 版ReActAgent时直接传system_promptfrom llama_index.core.agent.workflow import ReActAgent agent ReActAgent(system_promptYou are a helpful financial advisor.)源码 react_agent.py 会自动完成 context 写入与模板切换。测试 test_prompt_customization.py 还验证了当同时传入自定义 formatter 的context与system_prompt时system_prompt会被前置拼接到已有 context 之前。方式二整体替换系统提示模板如果你需要完全重写角色定义、工具说明或输出格式可直接传入自定义system_header字符串模板中必须保留{tool_desc}与{tool_names}占位符否则工具信息将无法注入from llama_index.core.agent.react.formatter import ReActChatFormatter custom_header \ You are a coding assistant. You must always use tools to answer. ## Tools {tool_desc} ## Output Format Always reply with: Thought: ... Action: one of {tool_names} Action Input: {{arg: value}} ## Current Conversation formatter ReActChatFormatter.from_defaults(system_headercustom_header)方式三通过update_prompts运行时更新workflow 版ReActAgent将系统提示以react_header为键暴露给提示词更新接口react_agent.py可结合PromptTemplate做部分格式化from llama_index.core import PromptTemplate from llama_index.core.agent.workflow import ReActAgent from textwrap import dedent agent ReActAgent() prompt PromptTemplate( dedent( \ Required template variables: {tool_desc} {tool_names} Additional variables: {dummy_var} ) ) agent.update_prompts({react_header: prompt.partial_format(dummy_vardummy_context)})该用法在 test_prompt_customization.py 中有对应测试部分格式化后的dummy_var会保留在agent.formatter.system_header中说明update_prompts支持携带额外模板变量的部分格式化。此外ReActChatFormatter是普通 Pydantic 模型可被继承重写test_react_chat_formatter.py 展示了继承并重写format()的 Mock 形式适合需要完全控制消息组装顺序的高级场景。五、模板与输出解析器的契约关系深入原理模板的输出格式协议段与 output_parser.py 的正则解析逻辑是一一对应的硬契约模板协议要求解析器实现output_parser.py动作分支Thought: ...\nAction: name\nAction Input: jsonextract_tool_use()正则提取三元组parse_action_reasoning_step()用dirtyjson宽松 JSON 解析解析 Action Input终止分支Thought: ...\nAnswer: answerextract_final_response()用正则\s*Thought:(.*?)Answer:(.*?)(?:$)提取最终答案必须以Thought:开头ReActOutputParser.parse()用re.search(rThought:, output, re.MULTILINE)定位起始未按格式输出时的兜底三个关键字Thought/Action/Answer都未命中时将整段输出视为隐式回答(Implicit) I can answer without any more tools!解析器还体现了两个与模板呼应的设计细节Action 优先于 Answer当输出同时包含Action:与Answer:时按位置先后判断action_idx answer_idx则走动作分支防止模型在调工具的同时试图结束对话弱模型容错注释明确说明较弱的 LLM 可能生成糟糕的 Action Input JSON因此先用dirtyjson解析失败后再回退到正则化的action_input_parser()output_parser.py。也就是说如果你自定义模板修改了输出协议必须同步重写或扩展ReActOutputParser否则解析器将无法从新格式中提取工具调用与最终答案。这是自定义 ReAct 提示词时最容易踩的坑。六、与 workflow 版 ReActAgent 的集成要点在基于 Workflow 的新版 ReAct Agentreact_agent.py中模板相关的集成要点可归纳为formatter是ReActAgent的 Pydantic 字段默认工厂default_formatter()会读取system_prompt并调用ReActChatFormatter.from_defaults(context...)take_step()每轮都会基于ctx.store中缓存的current_reasoning推理步骤列表重新格式化输入因此模板注入发生在每一轮而不是只在首轮当 LLM 返回空内容或解析失败时Agent 会构造携带格式纠正提示的retry_messages回传给 LLM这些纠正提示同样复用了模板中定义的两种输出格式工具调用格式 / 直接回答格式可见模板协议在容错路径上也被一致遵循react_agent.py工具执行结果通过ObservationReasoningStep追加进current_reasoning并在下一轮以 USER 角色回填到消息列表与模板重复循环直到信息充足的指令闭环吻合。七、总结与最佳实践system_header_template.md虽然只是一份 Markdown 文本却是 LlamaIndex ReAct Agent 提示工程的总纲。结合源码可以提炼出以下实践建议保持输出协议不变只改角色与上下文绝大多数业务定制领域角色、背景知识、回答风格通过context/system_prompt注入即可无需改动输出格式段避免与默认解析器失配如需整体替换模板务必保留{tool_desc}与{tool_names}占位符并同步定制ReActOutputParser确保提示约束与解析校验两条链路一致善用update_promptsPromptTemplate它支持部分格式化携带额外变量是实现多 Agent 共享模板 差异化参数的轻量手段关注模板与容错机制的联动默认的格式纠正消息retry_messages假定模型遵循模板中的两种输出格式自定义时需评估容错路径是否仍然成立以测试为行为基准仓库中 test_react_chat_formatter.py 与 test_prompt_customization.py 完整覆盖了 formatter 继承、context 注入、模板自动切换与部分格式化等关键行为是验证自定义模板是否符合预期的现成参考。理解这份模板及其背后的实现就等于掌握了 LlamaIndex ReAct Agent 提示工程的核心入口——从模型知道有哪些工具到模型以什么格式调用工具再到模型何时停止调用并作答全部由这一份系统提示骨架所驱动。【免费下载链接】llama_indexLlamaIndex is the document processing platform for AI项目地址: https://gitcode.com/GitHub_Trending/ll/llama_index创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考