Skip to main content
本页面描述了在 Playground提示中心评估器 中支持的提示模板格式。提示模板允许您创建带有动态占位符的可复用提示,这些占位符在运行时会被填充。
有关提示工程和提示模板的概述,请参阅概念页面。
LangSmith 支持两种提示模板格式,适用于不同复杂程度的场景:
格式语法最适用于
f-string{variable}具有基本变量替换的简单提示
mustache{{variable}}包含循环、条件、嵌套数据或评估器的复杂提示
F-string 语法 适用于直接明了的提示。Mustache 提供了处理复杂数据结构和逻辑的功能,这对评估器和高级用例很有帮助。 您可以在 UI 中切换格式。LangSmith 会在可能的情况下自动转换您的模板,但某些 mustache 功能(如循环和条件)无法转换为 f-string 格式。
使用 Playground 测试本页面上的示例。在 Playground 的提示设置 菜单下切换 提示格式

F-string 语法

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

基本变量

变量会被输入数据中的对应值替换。变量名必须完全匹配(区分大小写):
# 模板
Hello, {name}! Welcome to {company}.

# 输入
{
  "name": "Ashley",
  "company": "LangChain"
}

# 输出
Hello, Ashley! Welcome to LangChain.
当模板运行时,LangSmith 会在输入对象中查找每个变量名,并将 {name} 替换为 name 键的值。

变量名

F-string 变量名被视为简单的字符串标识符。它们不能包含点、括号或特殊字符——只能包含字母数字字符和下划线。
# 模板
Hello, {name}!
Your topic is: {topic}

# 输入
{
  "name": "Ashley",
  "topic": "LangSmith"
}

# 输出
Hello, Ashley!
Your topic is: LangSmith
如果您的输入包含嵌套对象,如 {"user": {"name": "Ashley"}},您不能在 f-string 格式中使用 {user.name} 访问嵌套值。点会被视为变量名的一部分(字面上查找名为 "user.name" 的键),而不是路径分隔符。要访问嵌套数据,请改用 mustache 格式

字面花括号

有时您需要在输出中包含实际的花括号(例如,在 JSON 示例或代码片段中)。为此,请将花括号加倍
# 模板
Use double braces for literals: {{not_a_variable}}
But single braces for variables: {variable}

# 输入
{
  "variable": "value"
}

# 输出
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 会将变量替换为其值:
{{!-- 模板 --}}
Hello, {{name}}! Welcome to {{company}}.

{{!-- 输入 --}}
{
  "name": "Ashley",
  "company": "LangChain"
}

{{!-- 输出 --}}
Hello, Ashley! Welcome to LangChain.
{{!-- ... --}} 是 mustache 注释,不会出现在输出中。请参阅注释部分。

嵌套对象访问

您可以使用点表示法遍历嵌套对象:
{{!-- 模板 --}}
User: {{user.name}}
Email: {{user.profile.email}}

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

{{!-- 输出 --}}
User: Billy
Email: billy@example.com
模板引擎会沿着 userprofileemail 的路径遍历您的数据结构。每个点代表一层嵌套。 现实世界的数据通常是嵌套的(例如:API 响应、数据库记录等)。Mustache 让您可以自然地处理这些数据,而无需先将其扁平化。

节是 mustache 的核心功能。一个节以 {{#name}} 开始,以 {{/name}} 结束。内部发生的情况取决于值:
  • 数组: 为每个元素重复内容。
  • 对象: 以该对象作为上下文渲染一次。
  • 真值: 渲染一次。
  • 假值(false、null、undefined、空数组): 不渲染。
在下面的示例中,节 {{#items}} 遍历 items 数组。对于每次迭代,节内的变量(如 {{name}}{{price}})会根据当前数组元素进行解析:
{{!-- 模板 --}}
Shopping List:
{{#items}}
  - {{name}}: ${{price}}
{{/items}}

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

{{!-- 输出 --}}
Shopping List:
  - Apple: $1.50
  - Banana: $0.75
  - Orange: $2.00
节消除了手动构建重复文本的需要。在评估器中,您将使用节来遍历对话消息或少样本示例 对于深度嵌套的分层数据,您可以嵌套多个节来处理具有多层数组和对象的复杂结构:
{{!-- 模板 --}}
{{#company}}
Company: {{name}}
{{#departments}}
  Department: {{dept_name}}
  {{#employees}}
    - {{employee_name}} ({{role}})
  {{/employees}}
{{/departments}}
{{/company}}

{{!-- 输入 --}}
{
  "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"}
        ]
      }
    ]
  }
}

{{!-- 输出 --}}
Company: TechCorp
  Department: Engineering
    - Ashley (Senior Engineer)
    - Billy (Engineer)
  Department: Sales
    - Carol (Sales Manager)
您可以根据需要创建任意深度的结构,但为了可读性,建议在模板化之前将非常深的结构扁平化。这种方法对于嵌套类别、带有元数据的对话线程或任何分层数据表示都很有用。

嵌套循环

您可以嵌套节来处理多层数据结构:
{{!-- 模板 --}}
{{#categories}}
Category: {{name}}
{{#products}}
  - {{title}} ({{price}})
{{/products}}
{{/categories}}

{{!-- 输入 --}}
{
  "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"}
      ]
    }
  ]
}

{{!-- 输出 --}}
Category: Fruits
  - Apple ($1.50)
  - Banana ($0.75)
Category: Vegetables
  - Carrot ($0.50)
  - Lettuce ($1.25)
外部节 {{#categories}} 将上下文设置为每个类别对象。在该上下文中,{{name}} 指的是类别名称,内部节 {{#products}} 遍历该类别的产品。 当您的数据具有分层关系时——例如带有产品的类别、带有员工的部门或包含多次交换的对话线程——请使用嵌套循环。

通过索引访问数组元素

有时您需要特定元素而不是循环。请使用带数字索引的点表示法:
{{!-- 模板 --}}
First item: {{items.0}}
Second item: {{items.1}}
Last item: {{items.2}}

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

{{!-- 输出 --}}
First item: Apple
Second item: Banana
Last item: Orange
编写模板时必须知道索引。 评估器通常需要对话线程中的第一条用户消息或最后一条 AI 响应。使用 {{all_messages.0}} 获取第一条消息,或在数据中预先计算最后一条消息。

条件

您可以将节用作条件。它们仅在值存在、非空且不为 false 时渲染:
{{!-- 模板 --}}
{{#user}}
Welcome back, {{name}}!
{{/user}}

{{!-- 输入(用户存在) --}}
{
  "user": {
    "name": "Ashley"
  }
}

{{!-- 输出 --}}
Welcome back, Ashley!

{{!-- 输入(无用户) --}}
{}

{{!-- 输出 --}}
(空 - 节不渲染)
{{#user}} 检查 user 是否存在且为真值。如果是,则以 user 作为上下文渲染其内部内容(因此 {{name}} 会在 user 内部查找 name)。 仅在用户数据可用时显示可选内容(如“欢迎回来”消息),或仅在存在错误时显示错误消息。

反向节

反向节仅在值不存在、为 false、null、undefined 或空数组时渲染。反向节通常用于处理空状态,例如缺失数据或空列表。 在以下示例中:
  • {{#results}} 遍历每个结果并为每个项目渲染一行。
  • {{^results}} 仅在 results 数组为空或缺失时渲染。
  • 当没有结果显示时,反向节提供了清晰的回退。
{{!-- 模板 --}}
Search results for "{{query}}":

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

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

{{!-- 输入(有结果)--}}
{
  "query": "matrix",
  "results": [
    {"title": "The Matrix", "year": 1999},
    {"title": "The Matrix Reloaded", "year": 2003}
  ]
}

{{!-- 输出 --}}
Search results for "matrix":

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

{{!-- 输入(无结果) --}}
{
    "query": "asdlkjasd",
    "results": []
}

{{!-- 输出 --}}
Search results for "asdlkjasd":

No results found. Try a different search term.
您还可以组合常规节和反向节来创建 if/else 逻辑,在变量缺失时提供默认值。 常规节 {{#username}} 仅在 username 存在时渲染。反向节 {{^username}} 仅在 username 不存在时渲染。它们共同构成了一个 if/else 分支。当用户数据是可选的,或者在未提供自定义指令时显示默认指令时,这对于个性化提示很有用:
{{!-- 模板 --}}
{{#username}}
Hello, {{username}}!
{{/username}}
{{^username}}
Hello, Guest!
{{/username}}

{{!-- 输入(有用户名) --}}
{"username": "Ashley"}
{{!-- 输出: Hello, Ashley! --}}

{{!-- 输入(无用户名) --}}
{}
{{!-- 输出: Hello, Guest! --}}
此模式可扩展到布尔标志,允许您根据数据条件更改输出格式:
{{!-- 模板 --}}
Status: {{status}}
{{#is_urgent}}
⚠️ URGENT - Immediate attention required!
{{/is_urgent}}
{{^is_urgent}}
Standard priority
{{/is_urgent}}

{{!-- 输入 --}}
{
  "status": "Open",
  "is_urgent": true
}

{{!-- 输出 --}}
Status: Open
⚠️ URGENT - Immediate attention required!
在数据中使用布尔标志来控制哪些内容块被渲染。这将格式化逻辑从应用程序代码中移出,放入模板中。这种方法对于突出重要信息、根据上下文调整语气(正式与非正式)或为不同用户类型显示不同指令很有用。

注释

注释用于记录您的模板,而不会影响输出。使用 {{! comment }}{{!-- comment --}}
{{!-- 模板 --}}
Hello, {{name}}!
{{! 这是注释,不会出现在输出中 }}
Welcome to our service.

{{!-- 输入 --}}
{
  "name": "Ashley"
}

{{!-- 输出 --}}
Hello, Ashley!
Welcome to our service.
使用注释来解释复杂的节、记录预期的数据结构或说明某些逻辑存在的原因。这有助于协作者理解您的模板。

评估器和线程的特殊变量

在构建评估器或处理对话式 AI 时,LangSmith 会自动提供特殊变量,以有用的方式组织对话数据。这些变量仅在评估器上下文中可用,在常规 Playground 提示中不可用。 评估器需要全面分析对话——查看多条消息中的模式、将第一个问题与最终答案进行比较,或检查 AI 对后续问题的响应效果。这些变量使得无需手动数据操作即可轻松访问对话结构。

线程消息变量

LangSmith 提供了对话线程的三个预结构化视图:
{{!-- 访问线程中的所有消息 --}}
{{#all_messages}}
{{role}}: {{content}}
{{/all_messages}}

{{!-- 访问人机消息对 --}}
{{#human_ai_pairs}}
Human: {{human}}
AI: {{ai}}
{{/human_ai_pairs}}

{{!-- 访问第一条人类消息和最后一条 AI 消息 --}}
{{#first_human_last_ai}}
Original question: {{first_human}}
Final answer: {{last_ai}}
{{/first_human_last_ai}}

{{!-- 通过索引访问特定消息 --}}
First message: {{all_messages.0}}
Second message: {{all_messages.1}}
  • all_messages:按时间顺序排列的所有消息,包含 role(user/assistant/system)和 content 字段。使用此变量显示完整的对话流程。
  • human_ai_pairs:将消息分组为问答对。每对包含 human(用户消息)和 ai(助手响应)。在评估响应质量时使用此变量。
  • first_human_last_ai:仅包含初始问题(first_human)和最终答案(last_ai)。使用此变量检查 AI 最终是否回答了原始问题,忽略中间对话。

使用线程上下文的示例

以下示例是一个使用线程上下文的实用评估器提示:
{{!-- 模板 --}}
Evaluate this conversation:

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

Was the AI helpful? Rate from 1-5.

{{!-- 输入(由 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?"}
  ]
}

{{!-- 输出 --}}
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 会自动从正在评估的对话中填充它们。

少样本示例

少样本提示通过示例来教导 LLM。您提供几个演示任务的输入-输出对,然后要求它在新的输入上执行相同的任务。 少样本示例帮助 LLM 理解:
  • 格式期望(例如,“以 JSON 格式响应”或“使用这种语气”)
  • 边缘情况(例如,如何处理模糊输入)
  • 任务细微差别(例如,“积极”和“非常积极”情感之间的区别)
它对于分类、格式化和风格任务特别有用,在这些任务中,展示比说明更清晰。

少样本占位符

在 LangSmith 中,在您希望示例出现的位置使用 {{few_shot_examples}} 占位符:
{{!-- 模板 --}}
You are a sentiment classifier.

{{few_shot_examples}}

Now classify this text:
Text: {{text}}
Sentiment:
当您在 LangSmith UI 中启用少样本示例(在评估器或提示中心中)时,您可以单独配置示例格式。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 可能会拒绝转换,或者只转换简单部分,从而破坏模板的功能。转换后请务必预览。

附加资源