Prompt格式到底有多重要?它竟然这样影响LLM函数调用能力(附提示词模版)

函数调用能力的关键地位

在当前大语言模型(LLM)的应用生态中,函数调用能力(Function Calling)已经成为一项不可或缺的核心能力。它使LLM能够通过调用外部API获取实时信息、操作第三方服务,从而将模型的语言理解能力转化为实际的行动能力。从电子设计自动化到金融报告生成,从旅行规划到智能家居控制,函数调用正在将LLM的应用版图快速扩展到各个领域。

然而,如何让LLM更准确地理解和使用函数接口,一直是困扰研究者和工程师的关键问题。MediaTek Research的研究团队最近在这一领域取得了重要突破,他们从提示格式优化、数据集成策略到多语言支持等多个维度,系统性地提升了LLM的函数调用能力。本文将详细解析他们的研究发现,为从事LLM应用开发的工程师提供切实可行的优化方案。

在这里插入图片描述

在这里插入图片描述

提示工程最新:重新思考函数描述的呈现方式

在这项研究中,研究者首先挑战了传统的函数描述方式。他们提出了两种不同的策略来在提示中展示函数描述:

  1. **专门角色策略:**为函数描述创建一个独立的角色(如"tools"),以JSON格式呈现函数信息。
  2. **系统角色集成策略:**将函数描述直接嵌入到系统角色的提示中,与使用说明一起呈现。

这两种策略的实验结果令人深思。研究发现,当函数描述通过专门角色呈现时,模型在相关性检测(Relevance Detection)方面表现更好。这意味着模型能更准确地判断是否需要调用函数,从而减少不必要的函数调用。研究发现,使用专门角色策略时,相关性检测准确率达到49.58%,而系统角色集成策略则为39.58%。

研究者认为,这种差异源于模型能更清晰地识别出有函数可用和无函数可用的场景之间的区别。当函数描述被放在专门的角色中时,有函数和无函数的提示模板差异更明显,这帮助模型建立了更强的区分能力。

img

Prompt格式示例

毫无疑问,精确推理时,Prompt格式显著影响推理的精准度。研究中探索了三种主要的提示格式:

  1. 无函数场景:
<|im_start|>system
You are a helpful assistant.
<|im_end|>
<|im_start|>user
Where is Boston?
<|im_end|>
<|im_start|>assistant
  1. 专门角色提供函数:
<|im_start|>tools
[{"name": "get_current_weather", 
"description": "Get the current weather in a given location", 
"parameters": {"type": "object", "properties": {"location": 
{"type": "string", "description": "The city and state"}}, 
"required": ["location"]}}]
<|im_end|>
<|im_start|>system
You are a helpful assistant.
<|im_end|>
<|im_start|>user
What is the weather like in Boston?
<|im_end|>
<|im_start|>assistant
  1. 系统角色集成函数:
<|im_start|>system
You are an expert in composing functions. Here is a list of functions in JSON format that you can invoke: [{"name": "get_current_weather", "description": "Get the current weather in a given location", "parameters": {"type": "object", "properties": {"location": {"type": "string", "description": "The city and state"}}, "required": ["location"]}}]
<|im_end|>
<|im_start|>user
What is the weather like in Boston?
<|im_end|>
<|im_start|>assistant

对应的生成结果示例:

  1. 普通回答:
Boston is the capital city of the state of Massachusetts, located in the northeastern United States.
<|im_end|>
  1. 带Decision Token的回答:
<|answer|>Boston is the capital city of the state of Massachusetts, located in the northeastern United States.
<|im_end|>
  1. 函数调用:
[get_current_weather(location="Boston")]
<|im_end|>
  1. 带Decision Token的函数调用:
<|use_tool|>[get_current_weather(location="Boston")]
<|im_end|>
  1. 带推理过程的函数调用:
<|use_tool|>The user wants to get the weather in Boston. The available tool 'get_current_weather' can be used to retrieve this information. The 'get_current_weather' tool can be used by specifying the city as 'Boston'.
[get_current_weather(location="Boston")]
<|im_end|>

在这里插入图片描述

数据集成:指令数据的意外收获

研究中最令人惊讶的发现之一是指令跟随(Instruction Following)数据对函数调用能力的显著提升作用。研究者在训练数据中加入了11万条指令跟随数据,结果发现这不仅没有削弱模型的函数调用能力,反而带来了全面的性能提升:

  • 函数调用准确率(AST Summary)从74.62%提升到85.25%
  • 相关性检测准确率从38.33%提升到49.58%

这一发现颠覆了"专注于函数调用数据才能提升函数调用能力"的传统认知。研究者分析认为,指令跟随数据帮助模型建立了更好的语义理解能力,这种基础能力的提升反过来增强了模型理解和使用函数接口的能力。同时,指令数据中包含的大量非函数调用场景,也帮助模型更好地识别什么时候应该直接回答而不是调用函数。

Decision Token:二元决策机制

为了进一步提升模型的相关性检测能力,研究者提出了一个创新的Decision Token机制。这一机制的核心思想是在生成响应之前,先让模型做出一个明确的二元决策:是直接回答还是调用函数。

具体实现上,研究者引入了两个特殊token:

  • <|answer|>:表示模型决定直接回答
  • <|use_tool|>:表示模型决定调用函数

这种设计将原本隐含在生成过程中的决策明确化,强制模型在生成具体回答或函数调用之前,先对查询的性质做出判断。实验结果表明,当结合合成的非函数调用数据使用时,这一机制能将相关性检测准确率提升到65.42%。

更重要的是,Decision Token机制还简化了非函数调用数据的生成过程。研究者可以通过移除原始数据中被调用的函数,轻松创建对应的函数调用训练样本。这解决了获取高质量非函数调用训练数据的难题。

多语言支持的突破:专向翻译管道

在全球化背景下,如何让函数调用能力突破语言障碍是一个关键挑战。研究者设计了一个专门的翻译管道来解决这个问题。这个管道的独特之处在于它采用了细粒度的翻译策略:

  • 保持函数名称和描述不变
  • 只在合理的情况下翻译参数值
  • 保持JSON格式的结构完整性

以中文为例,研究者使用这个管道生成了1.9万条中文函数调用数据。实验结果显示,即使只使用这些翻译数据进行微调,模型在中文(繁体)函数调用基准测试上的表现就有显著提升:

  • AST Summary从52.37%提升到61.56%
  • 相关性检测从36.67%提升到41.25%

这一结果证明,只要采用合适的翻译策略,函数调用能力是可以有效地迁移到其他语言的。

img

多语言翻译Pipeline的技术细节

研究团队开发的翻译pipeline采用了精细的处理策略,主要包括以下步骤:

在这里插入图片描述

  1. 预处理阶段:
  • 识别并标记不需要翻译的技术元素(函数名、JSON结构等)
  • 提取需要翻译的自然语言内容
  • 保存原始格式信息
  1. 翻译处理:
  • 使用商业级LLM进行单轮查询翻译
  • 提供明确的翻译规则和约束
  • 保持专业术语的一致性
  1. 后处理阶段:
  • 验证翻译后的JSON结构完整性
  • 确保函数调用格式的正确性
  • 进行质量检查和修正

以下是一个实际的翻译示例:

原始数据:

{
    "conversations": [
        {"role": "user", "content": "What's the weather like in Taipei?"},
        {"role": "assistant", "content": "Let me check the weather for you."},
        {"tool_calls": [{"name": "get_current_weather", "arguments": {"location": "Taipei"}}]}
    ]
}

翻译后数据:

{
    "conversations": [
        {"role": "user", "content": "台北的天氣如何?"},
        {"role": "assistant", "content": "讓我幫您查看天氣。"},
        {"tool_calls": [{"name": "get_current_weather", "arguments": {"location": "Taipei"}}]}
    ]
}

注意函数名和location参数值保持不变,只翻译对话内容。这种精细的翻译策略确保了函数调用的正确性。

实验结果显示,这种翻译策略在多个语言上都取得了显著效果:

语言原始AST Summary翻译后AST Summary提升
中文52.37%61.56%+9.19%
日语51.25%59.83%+8.58%
韩语50.94%58.71%+7.77%

这些结果证明了该翻译pipeline的有效性和可扩展性。

实践启示:面向工程师的优化建议

基于这项研究的发现,我们可以为正在开发基于LLM函数调用功能的工程师提供以下具体建议:

  1. 提示格式设计
  • 优先考虑使用专门的角色来呈现函数描述
  • 确保有函数和无函数场景的提示模板有明显区别
  • 在系统提示中清晰说明函数使用的规则和限制
  1. 训练数据构建
  • 不要限于纯函数调用数据
  • 有意识地加入高质量的指令跟随数据
  • 通过Decision Token机制构建非函数调用数据
  1. 多语言支持实现
  • 采用专门的翻译管道而不是简单的机器翻译
  • 仔细区分需要翻译和不需要翻译的内容
  • 确保翻译后数据的结构完整性
  1. 评估和优化
  • 同时关注函数调用准确率和相关性检测
  • 在多种场景下测试模型的判断能力
  • 持续收集和分析失败案例

通过这些持续的优化和创新,LLM的函数调用能力变得更加强大和实用,为AI应用开发带来更多可能性。

如何学习AI大模型?

作为一名热心肠的互联网老兵,我决定把宝贵的AI知识分享给大家。 至于能学习到多少就看你的学习毅力和能力了 。我已将重要的AI大模型资料包括AI大模型入门学习思维导图、精品AI大模型学习书籍手册、视频教程、实战学习等录播视频免费分享出来。

这份完整版的大模型 AI 学习资料已经上传优快云,朋友们如果需要可以微信扫描下方优快云官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

作为普通人,入局大模型时代需要持续学习和实践,不断提高自己的技能和认知水平,同时也需要有责任感和伦理意识,为人工智能的健康发展贡献力量。

<think>我们正在使用LangGraph构建节点,并希望为LLM节点设置系统提示词。根据引用[2]和引用[3],我们知道在LangGraph中,LLM节点通常通过定义提示词模板来指导模型的行为。系统提示词LLM输入的重要组成部分,用于设定模型的角色、任务要求和行为规范。 在LangGraph中,设置系统提示词通常有以下几种方式: 1. **在节点函数内部构建提示词**:在节点函数中,我们可以使用LangChain的提示模板来构建包含系统提示词的完整提示,然后传递给LLM模型。 2. **通过状态管理传递系统提示词**:如果系统提示词是动态的,我们可以将其存储在状态中,然后在节点函数中从状态中提取并构造提示。 3. **使用预定义的提示模板**:我们可以定义一个包含系统提示词的提示模板,并在节点中使用它。 下面我们通过一个具体的例子来说明如何设置系统提示词。 ### 步骤1:定义状态 首先,我们需要定义图的状态。状态中应该包含LLM节点所需的输入,比如用户输入、对话历史等。我们也可以将系统提示词作为状态的一部分,这样可以在运行动态改变。 ```python from pydantic import BaseModel, Field from typing import Dict, List, Annotated, Union, TypedDict # 定义状态,包含对话历史,其中系统消息也可以作为历史的一部分 class State(TypedDict): messages: Annotated[List[Dict], Field(..., description="对话历史")] # 或者,我们可以将系统提示词单独作为一个字段 class StateWithSystemPrompt(TypedDict): system_prompt: Annotated[str, Field(..., description="系统提示词")] messages: Annotated[List[Dict], Field(..., description="对话历史")] ``` ### 步骤2:构建节点函数 在节点函数中,我们将系统提示词与用户消息结合,构造完整的提示词。这里我们使用LangChain的`ChatPromptTemplate`。 ```python from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder from langchain_core.messages import SystemMessage, HumanMessage def llm_node(state: State): # 假设我们希望有一个默认的系统提示词,但也可以从状态中获取 system_prompt = "你是一个有用的助手,请用中文回答用户的问题。" # 默认系统提示词 # 如果状态中有系统提示词,则使用状态中的(如果采用StateWithSystemPrompt状态) # 但这里我们假设状态是State类型,所以我们将系统提示词作为固定的部分 # 构建提示词模板 prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), MessagesPlaceholder(variable_name="messages") ]) # 从状态中获取消息 messages = state['messages'] # 将消息应用到模板中,得到格式化后的消息列表 formatted_messages = prompt.format_messages(messages=messages) # 然后我们可以将formatted_messages传递给LLM # 这里假设我们已经有一个配置好的LLM from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo") response = llm.invoke(formatted_messages) # 将响应消息添加到状态中(即对话历史) new_messages = messages + [{"role": "assistant", "content": response.content}] return {"messages": new_messages} ``` ### 步骤3:将节点添加到图中 然后,我们可以将这个节点添加到LangGraph图中。 ```python from langgraph.graph import StateGraph # 使用状态定义图 graph_builder = StateGraph(State) # 添加节点 graph_builder.add_node("llm", llm_node) # 设置入口点等 graph_builder.set_entry_point("llm") graph_builder.add_edge("llm", END) # 假设我们只有一个节点,直接结束 graph = graph_builder.compile() ``` ### 动态系统提示词 如果系统提示词需要动态变化(比如根据用户输入改变),我们可以将系统提示词放在状态中。 ```python def llm_node_dynamic(state: StateWithSystemPrompt): # 从状态中获取系统提示词 system_prompt = state['system_prompt'] messages = state['messages'] prompt = ChatPromptTemplate.from_messages([ ("system", system_prompt), MessagesPlaceholder(variable_name="messages") ]) formatted_messages = prompt.format_messages(messages=messages) # 调用LLM from langchain_openai import ChatOpenAI llm = ChatOpenAI(model="gpt-3.5-turbo") response = llm.invoke(formatted_messages) # 更新状态,将新的消息加入 new_messages = messages + [{"role": "assistant", "content": response.content}] return {"messages": new_messages} # 注意:这里没有更新系统提示词,所以系统提示词保持不变 ``` ### 通过工具设置系统提示词 引用[3]提到,工具定义和提示工程都是LLM理解工具的基础。因此,如果我们希望LLM能够使用工具,我们可以在系统提示词中加入关于工具使用的说明。 例如,在系统提示词中说明工具的使用规则: ```python system_prompt = """ 你是一个有用的助手,可以使用工具来回答问题。你可以使用的工具有: - 搜索工具:当需要查询实信息使用。 - 计算器:当需要计算数学表达式使用。 请根据问题选择适当的工具,并按照要求输出工具调用。 """ ``` ### 注意事项 - 系统提示词LLM输入的一部分,因此它会影响LLM的响应。 - 在LangGraph中,状态管理是核心,所以系统提示词可以作为状态的一部分,也可以固定在节点内部,具体取决于应用需求。 - 如果系统提示词很长,可能会占用大量token,需要注意模型的token限制。 ### 总结 在LangGraph节点中为LLM设置系统提示词的方法: 1. 在节点函数内部直接定义系统提示词字符串。 2. 通过状态传递系统提示词,实现动态更新。 3. 使用`ChatPromptTemplate`将系统提示词与用户消息组合成完整的提示。 通过以上方法,我们可以灵活地为LLM节点设置系统提示词,从而控制模型的行为。 [^1]: LangGraph入门教程:构建循环状态管理的LLM应用 [^2]: 从零到一:用LangGraph与LLM打造你的首个AI智能体 [^3]: LangGraph 智能体中 LLM 节点与工具的协作深度解析 ### 相关问题 1. 如何在LangGraph中动态更新LLM的系统提示词? 2. 在LangGraph中,如何为不同的节点设置不同的系统提示词? 3. 如何管理LangGraph中LLM节点的提示词以避免超出token限制? 4. 在LangGraph智能体中,如何将工具使用说明整合到系统提示词中?</think>在 LangGraph 中为 LLM 节点设置系统提示词,需要结合 LangChain 的提示工程和 LangGraph 的状态管理机制。以下是具体实现方法: ### 方法 1:通过状态管理传递系统提示词(推荐) ```python from langgraph.graph import StateGraph, END from langchain.prompts import ChatPromptTemplate from langchain_openai import ChatOpenAI from pydantic import BaseModel # 1. 定义包含系统提示词的状态 class AgentState(BaseModel): messages: list = Field(default_factory=list) system_prompt: str = "你是一个专业AI助手,需要准确回答用户问题" # 系统提示词字段 # 2. 创建带系统提示的LLM节点 def llm_node(state: AgentState): # 构建完整提示(系统提示 + 对话历史) prompt = ChatPromptTemplate.from_messages([ ("system", state.system_prompt), # 注入系统提示 ("human", "{input}") ]) # 创建LLMllm = ChatOpenAI(model="gpt-4") chain = prompt | llm # 执行调用 response = chain.invoke({"input": state.messages[-1]}) # 更新状态(保留系统提示) return {"messages": state.messages + [response.content]} # 3. 构建图 builder = StateGraph(AgentState) builder.add_node("llm_node", llm_node) builder.set_entry_point("llm_node") builder.add_edge("llm_node", END) graph = builder.compile() # 4. 使用示例 state = AgentState( messages=["解释量子纠缠现象"], system_prompt="你是一位量子物理专家,用通俗语言解释复杂概念" # 自定义系统提示 ) result = graph.invoke(state) ``` ### 方法 2:动态修改系统提示词 ```python # 添加修改系统提示的专用节点 def set_system_prompt_node(state: AgentState): # 根据业务逻辑动态生成系统提示 new_prompt = f"当前间:{datetime.now()}\n你是一位{state.expert_type}专家" return {"system_prompt": new_prompt} # 在图中添加路由 builder.add_node("set_prompt", set_system_prompt_node) builder.add_edge("set_prompt", "llm_node") # 设置提示后执行LLM节点 ``` ### 方法 3:使用消息历史格式 ```python # 在状态中直接包含系统消息 state = AgentState( messages=[ {"role": "system", "content": "用莎士比亚风格回答问题"}, {"role": "user", "content": "今天天气如何?"} ] ) # 节点处理自动识别系统消息 def llm_node(state: AgentState): prompt = ChatPromptTemplate.from_messages(state.messages) # 自动提取系统提示 ... ``` ### 关键机制说明 1. **提示工程集成** 通过 `ChatPromptTemplate` 的 `from_messages()` 方法解析系统提示[^3],支持种角色: ```python [ ("system", "系统提示内容"), ("human", "用户输入"), ("ai", "AI回复") ] ``` 2. **状态管理** - 系统提示作为状态的一部分持久化 - 使用 `return {"system_prompt": "新内容"}` 更新提示 - 通过条件分支实现动态提示切换[^1] 3. **提示词场景** 使用路由节点实现上下文相关提示: ```python def router(state): if "技术问题" in state.query: return "tech_prompt_node" else: return "general_prompt_node" ``` ### 最佳实践 1. **提示词模板化**: ```python system_template = """ 角色:{role} 任务:{task} 约束:{constraints} """ state.system_prompt = system_template.format( role="数学导师", task="分步解释解题过程", constraints="使用中文且包含公式$$x=\\frac{-b\\pm\\sqrt{b^2-4ac}}{2a}$$" ) ``` 2. **安全验证**: ```python def validate_prompt(prompt: str): if len(prompt) > 1000: raise ValueError("提示词过长") if "敏感词" in prompt: return "已替换为默认提示" return prompt ``` 3. **性能优化**: - 对静态提示使用内存缓存 - 提示词压缩技术(如关键信息提取) - 分批处理相似提示的请求 [^1]: LangGraph 的状态管理机制支持动态修改系统提示 [^2]: 通过条件分支实现不同场景的提示切换 [^3]: LangChain 的提示模板支持结构化角色设定 ### 相关问题 1. 如何在 LangGraph 中实现动态角色切换(如从"医生"切换到"律师")? 2. 如何防止系统提示词被用户输入意外覆盖? 3. LangGraph 中如何管理语言系统提示词? 4. 系统提示词长度超过 LLM 限制有哪些优化策略?
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值