Skip to content
LangSmith 文档版本 跟随上游 源快照 e858ba7e 更新于 2026-10-18

提示模板格式指南

本页描述 提示模板 在 Playground、提示 hub 和评估器中受支持的格式。提示模板让你能创建带动态占位符的可复用提示,占位符在运行时被填充。

TIP

有关提示工程和提示模板的通用概览,参阅 概念页。

LangSmith 支持两种提示模板格式,它们适用于不同的复杂度层级:

格式语法最适合
f-string{variable}带基本变量替换的简单提示
mustache{variable}带循环、条件、嵌套数据或评估器的复杂提示

F-string 语法 适合直白的提示。Mustache 提供处理复杂数据结构和逻辑的特性,对评估器和高级用例有帮助。

你可以在 UI 中切换格式。尽可能时 LangSmith 会自动转换你的模板,尽管某些 mustache 特性(如循环和条件)无法转换成 f-string 格式。

INFO

用 Playground 来测试本页的例子。在 Playground 中,通过提示设置下的 Prompt format 切换

菜单。

F-string 语法

F-string 模板用单花括号的 Python 风格格式 {variable}。LangSmith 用一个简化子集的 Python f-string 语法:它只支持基本的变量替换,不支持 Python 表达式和格式化选项的完整范围。当你有一个扁平数据结构、只需把值插入你的提示时,f-string 很理想。

基本变量

变量被它们从输入数据里的值替换。变量名必须精确匹配(区分大小写):

python
# Template
Hello, {name}! Welcome to {company}.

# Input
{
  "name": "Ashley",
  "company": "LangChain"
}

# Output
Hello, Ashley! Welcome to LangChain.

当模板运行时,LangSmith 在输入对象中查找每个变量名,并把 {name} 替换为 name 键的值。

变量名

F-string 变量名被当作简单的字符串标识符。它们不能包含点、方括号或特殊字符——只能有字母数字和下划线。

python
# Template
Hello, {name}!
Your topic is: {topic}

# Input
{
  "name": "Ashley",
  "topic": "LangSmith"
}

# Output
Hello, Ashley!
Your topic is: LangSmith

如果你的输入有像 {"user": {"name": "Ashley"} 这样的嵌套对象,你不能在 f-string 格式中用 {user.name} 访问嵌套值。这个点会被当作变量名的一部分(字面上寻找一个叫 "user.name" 的键),而非路径分隔符。对于嵌套访问,请改用 mustache 格式。

字面花括号

有时你需要在输出中包含实际的花括号(例如在 JSON 例子或代码片段中)。要做到这一点,把花括号翻倍:

python
# Template
Use double braces for literals: {{not_a_variable}}
But single braces for variables: {variable}

# Input
{
  "variable": "value"
}

# Output
Use double braces for literals: {not_a_variable}
But single braces for variables: value

模板解析器把 { 识别为一个转义花括号,而非变量占位符。只有单花括号 {...} 被当作变量。

限制

LangSmith 的 f-string 实现被限定以保持模板简单且可预测。以下特性不受支持:

  • 用于嵌套访问的点记法: 不能用 {user.name} 访问嵌套对象。整个字符串 "user.name" 会被当作单个变量名。
  • 格式说明符: 不能用 {price:.2f} 做数字格式化,也不能用 {rate:.1%} 做百分比。
  • 表达式: 不能用 {x + y}、{len(items)} 或 {value if condition else default}。
  • 函数调用: 不能用 {str.upper()} 或其他方法调用。
  • 循环或条件: 无控制流结构。
  • 数组索引: 不能用 {items[0]} 访问数组元素。

对于这些高级特性中的任何一个,请改用 mustache 格式。

Mustache 语法

Mustache 是一种"无逻辑"的模板语言,意味着它不允许任意代码执行,但确实通过节提供结构化控制流。它被称为"无逻辑"是因为你写不了复杂表达式——取而代之,你通过组织数据来控制渲染什么。

Mustache 为复杂数据结构和动态渲染而设计。它对以下情形不可或缺:

  • 评估器: 处理线程历史和会话上下文。
  • 少样本提示: 遍历示例列表。
  • 嵌套数据: 访问深度嵌套的对象和数组。
  • 条件内容: 基于数据是否存在展示不同文本。

双花括号语法 {variable} 把它与 f-string 区分开。

基本变量

和 f-string 一样,mustache 用它们的值替换变量:

mustache
{{!-- Template --}}
Hello, {{name}}! Welcome to {{company}}.

{{!-- Input --}}
{
  "name": "Ashley",
  "company": "LangChain"
}

{{!-- Output --}}
Hello, Ashley! Welcome to LangChain.

NOTE

{!-- ... --} 是一条 mustache 注释,不会出现在输出中。参阅注释一节。

嵌套对象访问

你可以用点记法遍历嵌套对象:

mustache
{{!-- Template --}}
User: {{user.name}}
Email: {{user.profile.email}}

{{!-- Input --}}
{
  "user": {
    "name": "Billy",
    "profile": {
      "email": "billy@example.com"
    }
  }
}

{{!-- Output --}}
User: Billy
Email: billy@example.com

模板引擎沿你的数据结构跟随 user → profile → email 这条路径。每个点代表一层嵌套。

真实世界的数据常常是嵌套的(例如:API 响应、数据库记录等)。Mustache 让你自然地处理这些数据而无需先把它扁平化。

节

节是 mustache 的核心特性。一个节以 {#name} 开始,以 {/name} 结束。里面发生什么取决于值:

  • 数组: 为每个元素重复内容。
  • 对象: 以那个对象为上下文渲染一次。
  • 真值: 渲染一次。
  • 假值(false、null、undefined、空数组): 不渲染。

在下面的例子中,节 {#items} 遍历 items 数组。对每次迭代,节内的变量(如 {name} 和 {price})针对当前数组元素解析:

mustache
{{!-- Template --}}
Shopping List:
{{#items}}
  - {{name}}: ${{price}}
{{/items}}

{{!-- Input --}}
{
  "items": [
    {"name": "Apple", "price": "1.50"},
    {"name": "Banana", "price": "0.75"},
    {"name": "Orange", "price": "2.00"}
  ]
}

{{!-- Output --}}
Shopping List:
  - Apple: $1.50
  - Banana: $0.75
  - Orange: $2.00

节消除了手动构造重复文本的需要。在评估器中,你会用节来遍历会话消息或少样本示例。

对于深度嵌套的层次数据,你可以嵌套多个节来处理带多层数组和对象的复杂结构:

mustache
{{!-- Template --}}
{{#company}}
Company: {{name}}
{{#departments}}
  Department: {{dept_name}}
  {{#employees}}
    - {{employee_name}} ({{role}})
  {{/employees}}
{{/departments}}
{{/company}}

{{!-- Input --}}
{
  "company": {
    "name": "TechCorp",
    "departments": [
      {
        "dept_name": "Engineering",
        "employees": [
          {"employee_name": "Ashley", "role": "Senior Engineer"},
          {"employee_name": "Billy", "role": "Engineer"}
        ]
      },
      {
        "dept_name": "Sales",
        "employees": [
          {"employee_name": "Carol", "role": "Sales Manager"}
        ]
      }
    ]
  }
}

{{!-- Output --}}
Company: TechCorp
  Department: Engineering
    - Ashley (Senior Engineer)
    - Billy (Engineer)
  Department: Sales
    - Carol (Sales Manager)

TIP

你可以创建任意深的结构,但为了可读性,考虑在模板化之前把很深的结构扁平化。这种做法对嵌套类别、带元数据的会话线程,或任何层次数据表示都很有用。

嵌套循环

你可以嵌套节来处理多层数据结构:

mustache
{{!-- Template --}}
{{#categories}}
Category: {{name}}
{{#products}}
  - {{title}} ({{price}})
{{/products}}
{{/categories}}

{{!-- Input --}}
{
  "categories": [
    {
      "name": "Fruits",
      "products": [
        {"title": "Apple", "price": "$1.50"},
        {"title": "Banana", "price": "$0.75"}
      ]
    },
    {
      "name": "Vegetables",
      "products": [
        {"title": "Carrot", "price": "$0.50"},
        {"title": "Lettuce", "price": "$1.25"}
      ]
    }
  ]
}

{{!-- Output --}}
Category: Fruits
  - Apple ($1.50)
  - Banana ($0.75)
Category: Vegetables
  - Carrot ($0.50)
  - Lettuce ($1.25)

外层节 {#categories} 把上下文设为每个类别对象。在该上下文中,{name} 指类别名,内层节 {#products} 遍历该类别的产品。

当你的数据有层次关系时用嵌套循环——类别与产品、部门与员工,或带多轮交流的会话线程。

按索引取数组元素

有时你需要某个特定元素而非循环。用带数字索引的点记法:

mustache
{{!-- Template --}}
First item: {{items.0}}
Second item: {{items.1}}
Last item: {{items.2}}

{{!-- Input --}}
{
  "items": ["Apple", "Banana", "Orange"]
}

{{!-- Output --}}
First item: Apple
Second item: Banana
Last item: Orange

你在写模板时必须知道那个索引。

评估器常常需要会话线程里的第一条用户消息或最后一条 AI 响应。用 {all_messages.0} 取第一条消息,或在你的数据里预先算出最后一条消息。

条件

你可以把节用作条件。它们只在值存在、非空且不为 false 时渲染:

mustache
{{!-- Template --}}
{{#user}}
Welcome back, {{name}}!
{{/user}}

{{!-- Input (user exists) --}}
{
  "user": {
    "name": "Ashley"
  }
}

{{!-- Output --}}
Welcome back, Ashley!

{{!-- Input (no user) --}}
{}

{{!-- Output --}}
(empty - section doesn't render)

节 {#user} 检查 user 是否存在且为真。若是,它以 user 为上下文渲染里面的内容(所以 {name} 会在 user 里查找 name)。

只在用户数据可用时展示诸如"欢迎回来"这样的可选内容,或只在存在错误时展示错误消息。

反节

反节只在一个值不存在、为 false、null、undefined 或空数组时渲染。反节常用于处理空状态,例如缺失的数据或空列表。

在下面的例子中:

  • {#results} 遍历每个结果并为每项渲染一行。
  • {^results} 只在 results 数组为空或缺失时渲染。
  • 反节在没有结果可展示时提供一个清晰的回退。
mustache
{{!-- Template --}}
Search results for "{{query}}":

{{#results}}
  - {{title}} ({{year}})
{{/results}}

{{^results}}
No results found. Try a different search term.
{{/results}}

{{!-- Input (with results)--}}
{
  "query": "matrix",
  "results": [
    {"title": "The Matrix", "year": 1999},
    {"title": "The Matrix Reloaded", "year": 2003}
  ]
}

{{!-- Output --}}
Search results for "matrix":

  - The Matrix (1999)
  - The Matrix Reloaded (2003)

{{!-- Input (no results) --}}
{
    "query": "asdlkjasd",
    "results": []
}

{{!-- Output --}}
Search results for "asdlkjasd":

No results found. Try a different search term.

你也可以组合常规节和反节来创建 if/else 逻辑,在变量缺失时提供默认值。

常规节 {#username} 只在 username 存在时渲染。反节 {^username} 只在它不存在时渲染。合起来,它们创建一个 if/else 分支。当用户数据可选时、或当未提供自定义指令而需展示默认指令时,这对个性化提示很有用:

mustache
{{!-- Template --}}
{{#username}}
Hello, {{username}}!
{{/username}}
{{^username}}
Hello, Guest!
{{/username}}

{{!-- Input (with username) --}}
{"username": "Ashley"}
{{!-- Output: Hello, Ashley! --}}

{{!-- Input (no username) --}}
{}
{{!-- Output: Hello, Guest! --}}

这个模式延伸到布尔标志,让你基于数据条件改变输出格式化:

mustache
{{!-- Template --}}
Status: {{status}}
{{#is_urgent}}
⚠️ URGENT - Immediate attention required!
{{/is_urgent}}
{{^is_urgent}}
Standard priority
{{/is_urgent}}

{{!-- Input --}}
{
  "status": "Open",
  "is_urgent": true
}

{{!-- Output --}}
Status: Open
⚠️ URGENT - Immediate attention required!

在你的数据中使用布尔标志来控制哪些内容块渲染。这能把格式化逻辑从你的应用代码移到模板里。这种做法对突出重要信息、依据上下文调整语气(正式对随意),或为不同用户类型展示不同指令都很有用。

注释

注释在不影响输出的情况下为你的模板写文档。用 {! comment } 或 {!-- comment --}:

mustache
{{!-- Template --}}
Hello, {{name}}!
{{! This is a comment and won't appear in output }}
Welcome to our service.

{{!-- Input --}}
{
  "name": "Ashley"
}

{{!-- Output --}}
Hello, Ashley!
Welcome to our service.

用注释来解释复杂的节、记录预期的数据结构,或注明为什么存在某些逻辑。这帮助协作者理解你的模板。

用于评估器和线程的特殊变量

在构建评估器或处理会话式 AI 时,LangSmith 自动提供以有用方式组织会话数据的特殊变量。这些变量只在评估器上下文中可用,不在常规 Playground 提示中。

评估器需要整体地分析会话——查看跨多条消息的模式、比较第一个问题与最终答案,或检查 AI 对追问的响应有多好。这些变量让你无需手动操作数据就能轻松访问会话结构。

线程消息变量

LangSmith 提供会话的四个预组织视图:三个针对一个线程,一个针对一条轨迹。

mustache
{{!-- Access all messages in the thread --}}
{{#all_messages}}
{{role}}: {{content}}
{{/all_messages}}

{{!-- Access human-AI message pairs --}}
{{#human_ai_pairs}}
Human: {{human}}
AI: {{ai}}
{{/human_ai_pairs}}

{{!-- Access first human and last AI message --}}
{{#first_human_last_ai}}
Original question: {{first_human}}
Final answer: {{last_ai}}
{{/first_human_last_ai}}

{{!-- Access specific message by index --}}
First message: {{all_messages.0}}
Second message: {{all_messages.1}}

{{!-- Access the trajectory of the session --}}
{{trajectory}}
  • all_messages:按时间顺序的每条消息,带 role(user/assistant/system)和 content 字段。用它展示完整的会话流。
  • human_ai_pairs:被分成问答对的每条消息。每对有 human(用户消息)和 ai(助手响应)。在评估响应质量时用它。
  • first_human_last_ai:仅初始问题(first_human)和最终答案(last_ai)。在检查 AI 是否最终回答了原始问题、忽略中间会话时用它。
  • trajectory:会话中的每条消息作为一个扁平、去重的列表,包括工具调用和工具结果。每条消息有一个 human、ai、system 或 tool 的 role,以及一个持有字符串或内容块列表(如 text、reasoning、tool_call)的 content 字段。用它评估 agent 所走的路径。

NOTE

trajectory 与线程变量互斥。一个提示要么用 trajectory,要么用 all_messages、human_ai_pairs 和 first_human_last_ai。关于这条规则如何被强制执行、以及如何在线程评估器中使用 trajectory,见评估轨迹。

带线程上下文的例子

下面的例子是一个使用线程上下文的实用评估器提示:

mustache
{{!-- Template --}}
Evaluate this conversation:

{{#all_messages}}
{{role}}: {{content}}
{{/all_messages}}

Was the AI helpful? Rate from 1-5.

{{!-- Input (provided by LangSmith) --}}
{
  "all_messages": [
    {"role": "user", "content": "What's the weather?"},
    {"role": "assistant", "content": "I don't have access to weather data."},
    {"role": "user", "content": "Can you tell me a joke instead?"},
    {"role": "assistant", "content": "Why did the chicken cross the road?"}
  ]
}

{{!-- Output --}}
Evaluate this conversation:

user: What's the weather?
assistant: I don't have access to weather data.
user: Can you tell me a joke instead?
assistant: Why did the chicken cross the road?

Was the AI helpful? Rate from 1-5.

该模板用 mustache 节 {#all_messages} 来遍历会话数组。对每次迭代,节把上下文设为那条消息对象,所以 {role} 和 {content} 访问当前消息的属性。循环自动按顺序遍历所有四条消息,把每条显示为 "role: content"。这给评估器 LLM 完整的会话历史以评估有用性。

当你在 LangSmith 中创建一个评估器时,选择你想包含哪些线程变量。LangSmith 会自动从被评估的会话填充它们。

带轨迹上下文的例子

下面的例子是一个使用轨迹上下文的实用评估器提示:

mustache
{{!-- Template --}}
Evaluate the path this agent took:

<trajectory>
{{trajectory}}
</trajectory>

Did the agent call the right tools to answer the question? Rate from 1-5.

{{!-- Input (provided by LangSmith) --}}
{
  "trajectory": [
    {
      "content": [{"type": "text", "text": "Is my GitHub CLI authenticated?"}],
      "role": "human",
      "id": "01a04b29-ab54-763b-89ba-1f3dd2266c54"
    },
    {
      "content": [
        {
          "type": "tool_call",
          "id": "call_wQO8IHBPu6HyXoZ1Q3UqvxIs",
          "name": "execute",
          "args": {"command": "gh auth status", "timeout": 30}
        }
      ],
      "role": "ai"
    },
    {
      "content": "Logged in to github.com account octocat",
      "role": "tool",
      "tool_call_id": "call_wQO8IHBPu6HyXoZ1Q3UqvxIs"
    },
    {
      "content": [{"type": "text", "text": "Yes, you are logged in as octocat."}],
      "role": "ai"
    }
  ]
}

与线程变量不同,trajectory 解析为从每条追踪内的模型和工具调用构建的轨迹,所以评估器能更细地给 agent 所走的路径打分。直接引用变量为 {trajectory},或用 mustache 节 {#trajectory}{role}{/trajectory} 遍历消息以控制评审者收到什么。

少样本示例

少样本提示通过示例教 LLM。你提供若干展示该任务的输入-输出对,然后要求它对新输入执行同样的任务。

少样本示例帮助 LLM 理解:

  • 格式预期(例如,"用 JSON 响应"或"用这种语气")
  • 边缘情形(例如,如何处理含糊的输入)
  • 任务细微差别(例如,"正面"和"非常正面"情绪之间的区别)

它对分类、格式化和风格化任务尤其有用,在这些任务上展示比讲述更清楚。

少样本占位符

在 LangSmith 中,在你希望示例出现的地方使用 {few_shot_examples} 占位符:

mustache
{{!-- Template --}}
You are a sentiment classifier.

{{few_shot_examples}}

Now classify this text:
Text: {{text}}
Sentiment:

当你在 LangSmith UI(在评估器或 Prompt Hub 中)启用少样本示例时,你单独配置示例格式。LangSmith 会自动把你放置 {few_shot_examples} 占位符的任何地方注入那些格式化好的示例。这让你的提示模板保持干净,并让你独立管理示例。

带已配置示例的示例输出:

You are a sentiment classifier.

Text: I love this!
Sentiment: positive
Text: This is terrible.
Sentiment: negative
Text: It's okay.
Sentiment: neutral

Now classify this text:
Text: This is amazing!
Sentiment:

在 LangSmith UI 中配置你的少样本示例,以匹配你为实际任务使用的格式。这种一致性帮助 LLM 正确地泛化。占位符方法把提示结构从示例数据分离,让两者都更易维护。

格式之间的转换

F-string 到 mustache 对基本变量总是可行。格式说明符会被转换,但格式化会被移除。

Mustache 到 f-string 只对基本变量可行。Mustache 特性如点记法、节、条件和注释在 f-string 中没有等价物,无法被转换:

  • 点记法: {user.name} F-string 会把 "user.name" 当作单个变量名而非嵌套访问。
  • 节/循环: {#items}...{/items} 在 f-string 中没有等价物。
  • 条件: {#value}...{/value} 在 f-string 中没有等价物。
  • 反节: {^value}...{/value} 在 f-string 中没有等价物。
  • 注释: {! comment } 在 f-string 中没有等价物。

如果你试图转换一个带这些特性的 mustache 模板,LangSmith 要么拒绝转换,要么只转换简单部分,破坏模板的功能。转换后务必预览。

其他资源


BytesRouter 是社区翻译站点,所有译文仅供参考,一切以官方英文原文为准。