> ## Documentation Index
> Fetch the complete documentation index at: https://langchain-zh.cn/llms.txt
> Use this file to discover all available pages before exploring further.

# 提示模板格式指南

本页介绍了在 [Playground](/langsmith/prompt-engineering-concepts#playground)、[提示中心](/langsmith/manage-prompts#public-prompt-hub) 和 [评估器](/langsmith/evaluation-concepts#evaluators) 中支持的 [提示模板](/langsmith/prompt-engineering-concepts#prompts-vs-prompt-templates) 格式。提示模板允许您创建带有动态占位符的可重用提示，这些占位符在运行时被填充。

<Tip>
  有关提示工程和提示模板的概述，请参阅 [概念](/langsmith/prompt-engineering-concepts#prompts-vs-prompt-templates) 页面。
</Tip>

LangSmith 支持两种提示模板格式，适用于不同复杂度的场景：

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

[F-string 语法](#f-string-syntax) 适用于简单的提示。[Mustache](#mustache-syntax) 提供了处理复杂数据结构和逻辑的功能，这对评估器和高级用例很有帮助。

您可以在 [UI](https://smith.langchain.com) 中切换格式。LangSmith 会在可能的情况下自动 [转换您的模板](#conversion-between-formats)，但某些 mustache 功能（如循环和条件）无法转换为 f-string 格式。

<Callout icon="test-pipe" color="#4F46E5" iconType="regular">
  使用 [Playground](https://smith.langchain.com/playground) 测试本页的示例。在 Playground 的提示设置 <Icon icon="settings" color="#4F46E5" iconType="solid" /> 菜单下切换 **提示格式**。
</Callout>

## F-string 语法

F-string 模板使用 Python 风格的格式化，使用单花括号 `{variable}`。LangSmith 使用了 Python [f-string 语法](https://realpython.com/python-f-strings/) 的 [简化子集](#limitations)：它只支持基本的变量替换，而不是完整的 Python 表达式和格式化选项。当您拥有扁平的数据结构并且只需要在提示中插入值时，f-string 是理想的选择。

### 基本变量

变量会根据输入数据中的值进行替换。变量名必须完全匹配（区分大小写）：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# 模板
你好，{name}！欢迎来到 {company}。

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

# 输出
你好，Ashley！欢迎来到 LangChain。
```

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

### 变量名

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

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# 模板
你好，{name}！
你的主题是：{topic}

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

# 输出
你好，Ashley！
你的主题是：LangSmith
```

如果您的输入有嵌套对象，例如 `{"user": {"name": "Ashley"}}`，您**不能**在 f-string 格式中使用 `{user.name}` 访问嵌套值。点号将被视为变量名的一部分（字面上查找名为 `"user.name"` 的键），而不是路径分隔符。对于嵌套访问，请改用 [mustache 格式](#mustache-syntax)。

### 字面量花括号

有时您需要在输出中包含实际的花括号（例如，在 JSON 示例或代码片段中）。为此，**请将花括号加倍**：

```python theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
# 模板
使用双花括号表示字面量：{{not_a_variable}}
但单花括号用于变量：{variable}

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

# 输出
使用双花括号表示字面量：{not_a_variable}
但单花括号用于变量：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](https://mustache.github.io/mustache.5.html) 是一种“无逻辑”的模板语言，这意味着它不允许任意代码执行，但确实通过区块提供了结构化的控制流。它被称为“无逻辑”是因为您不能编写复杂的表达式——相反，您需要结构化数据来控制渲染内容。

Mustache 专为复杂的数据结构和动态渲染而设计。它对以下情况至关重要：

* **评估器：** 处理对话历史和上下文。
* **少样本提示：** 遍历示例列表。
* **嵌套数据：** 访问深度嵌套的对象和数组。
* **条件内容：** 根据数据的存在显示不同的文本。

双花括号语法 `{{variable}}` 将其与 f-string 区分开来。

### 基本变量

与 f-string 类似，mustache 用值替换变量：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
你好，{{name}}！欢迎来到 {{company}}。

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

{{!-- 输出 --}}
你好，Ashley！欢迎来到 LangChain。
```

<Note>
  `{{!-- ... --}}` 是 mustache 注释，不会出现在输出中。请参阅 [注释](#comments) 部分。
</Note>

### 嵌套对象访问

您可以使用点表示法遍历嵌套对象：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
用户：{{user.name}}
邮箱：{{user.profile.email}}

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

{{!-- 输出 --}}
用户：Billy
邮箱：billy@example.com
```

模板引擎通过您的数据结构遵循路径 `user` → `profile` → `email`。每个点代表一个嵌套级别。

现实世界的数据通常是嵌套的（例如：API 响应、数据库记录等）。Mustache 允许您自然地处理这些数据，而无需先将其扁平化。

### 区块

区块是 mustache 的核心功能。区块以 `{{#name}}` 开始，以 `{{/name}}` 结束。内部发生的情况取决于值：

* **数组：** 为每个元素重复内容。
* **对象：** 以该对象为上下文渲染一次。
* **真值：** 渲染一次。
* **假值（false、null、undefined、空数组）：** 不渲染。

在以下示例中，区块 `{{#items}}` 遍历 `items` 数组。对于每次迭代，区块内的变量（如 `{{name}}` 和 `{{price}}`）会针对当前数组元素进行解析：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
购物清单：
{{#items}}
  - {{name}}: ${{price}}
{{/items}}

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

{{!-- 输出 --}}
购物清单：
  - Apple: $1.50
  - Banana: $0.75
  - Orange: $2.00
```

区块消除了手动构建重复文本的需要。在评估器中，您将使用区块来遍历对话消息或 [少样本示例](#few-shot-examples)。

对于深度嵌套的分层数据，您可以嵌套多个区块来处理具有多个数组和对象级别的复杂结构：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
{{#company}}
公司：{{name}}
{{#departments}}
  部门：{{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"}
        ]
      }
    ]
  }
}

{{!-- 输出 --}}
公司：TechCorp
  部门：Engineering
    - Ashley (Senior Engineer)
    - Billy (Engineer)
  部门：Sales
    - Carol (Sales Manager)
```

<Tip>
  您可以创建任意深度的结构，但为了可读性，考虑在模板化之前将非常深的结构扁平化。这种方法适用于嵌套类别、带有元数据的对话线程或任何分层数据表示。
</Tip>

### 嵌套循环

您可以嵌套区块来处理多级数据结构：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
{{#categories}}
类别：{{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"}
      ]
    }
  ]
}

{{!-- 输出 --}}
类别：Fruits
  - Apple ($1.50)
  - Banana ($0.75)
类别：Vegetables
  - Carrot ($0.50)
  - Lettuce ($1.25)
```

外部区块 `{{#categories}}` 将上下文设置为每个类别对象。在该上下文中，`{{name}}` 指的是类别名称，而内部区块 `{{#products}}` 则遍历该类别的产品。

当您的数据具有层次关系时，请使用嵌套循环——例如，包含产品的类别、包含员工的部门，或包含多次交流的对话线程。

### 按索引访问数组元素

有时您需要特定的元素而不是循环。使用带数字索引的点表示法：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
第一项：{{items.0}}
第二项：{{items.1}}
最后一项：{{items.2}}

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

{{!-- 输出 --}}
第一项：Apple
第二项：Banana
最后一项：Orange
```

您必须在编写模板时知道索引。

评估器通常需要对话线程中的第一条用户消息或最后一条 AI 响应。使用 `{{all_messages.0}}` 获取第一条消息，或在数据中预先计算最后一条消息。

### 条件

您可以使用区块作为条件。它们仅在值存在、非空且不为 `false` 时渲染：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
{{#user}}
欢迎回来，{{name}}！
{{/user}}

{{!-- 输入（用户存在） --}}
{
  "user": {
    "name": "Ashley"
  }
}

{{!-- 输出 --}}
欢迎回来，Ashley！

{{!-- 输入（无用户） --}}
{}

{{!-- 输出 --}}
（空 - 区块不渲染）
```

区块 `{{#user}}` 检查 `user` 是否存在且为真值。如果是，则渲染内部内容，并以 `user` 为上下文（因此 `{{name}}` 会在 `user` 内部查找 `name`）。

仅在用户数据可用时显示可选内容，例如“欢迎回来”消息，或仅在错误存在时显示错误消息。

### 反向区块

反向区块仅在值不存在、为 false、null、undefined 或空数组时渲染。反向区块通常用于处理空状态，例如缺失数据或空列表。

在以下示例中：

* `{{#results}}` 遍历每个结果，并为每个项目渲染一行。
* `{{^results}}` 仅在结果数组为空或缺失时渲染。
* 反向区块在没有结果可显示时提供了清晰的回退。

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
"{{query}}" 的搜索结果：

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

{{^results}}
未找到结果。请尝试不同的搜索词。
{{/results}}

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

{{!-- 输出 --}}
"matrix" 的搜索结果：

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

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

{{!-- 输出 --}}
"asdlkjasd" 的搜索结果：

未找到结果。请尝试不同的搜索词。
```

您还可以组合常规区块和反向区块来创建 if/else 逻辑，在变量缺失时提供默认值。

常规区块 `{{#username}}` 仅在 `username` 存在时渲染。反向区块 `{{^username}}` 仅在它不存在时渲染。它们共同创建了一个 if/else 分支。这在用户数据可选时个性化提示，或在未提供自定义指令时显示默认指令时非常有用：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
{{#username}}
你好，{{username}}！
{{/username}}
{{^username}}
你好，访客！
{{/username}}

{{!-- 输入（有用户名） --}}
{"username": "Ashley"}
{{!-- 输出：你好，Ashley！ --}}

{{!-- 输入（无用户名） --}}
{}
{{!-- 输出：你好，访客！ --}}
```

这种模式扩展到布尔标志，允许您根据数据条件更改输出格式：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
状态：{{status}}
{{#is_urgent}}
⚠️ 紧急 - 需要立即关注！
{{/is_urgent}}
{{^is_urgent}}
标准优先级
{{/is_urgent}}

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

{{!-- 输出 --}}
状态：Open
⚠️ 紧急 - 需要立即关注！
```

在数据中使用布尔标志来控制哪些内容块渲染。这可以将格式化逻辑保留在应用程序代码之外，而放在模板中。这种方法适用于突出显示重要信息、根据上下文调整语气（正式与非正式），或为不同的用户类型显示不同的指令。

### 注释

注释用于记录您的模板，而不影响输出。使用 `{{! comment }}` 或 `{{!-- comment --}}`：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
你好，{{name}}！
{{! 这是一个注释，不会出现在输出中 }}
欢迎使用我们的服务。

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

{{!-- 输出 --}}
你好，Ashley！
欢迎使用我们的服务。
```

使用注释来解释复杂的区块、记录预期的数据结构或说明某些逻辑存在的原因。这有助于协作者理解您的模板。

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

在构建 [评估器](/langsmith/evaluation-concepts#evaluators) 或处理对话式 AI 时，LangSmith 会自动提供以有用方式结构化对话数据的特殊变量。这些变量**仅在评估器上下文中可用**，而不是在常规的 Playground 提示中。

评估器需要整体分析对话——查看跨多条消息的模式，比较第一个问题和最终答案，或检查 AI 对后续问题的响应效果如何。这些变量使得无需手动操作数据即可轻松访问对话结构。

### 线程消息变量

LangSmith 提供了对话 [线程](/langsmith/evaluation-concepts#threads) 的三种预结构化视图：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 访问线程中的所有消息 --}}
{{#all_messages}}
{{role}}: {{content}}
{{/all_messages}}

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

{{!-- 访问第一条人类消息和最后一条 AI 消息 --}}
{{#first_human_last_ai}}
原始问题：{{first_human}}
最终答案：{{last_ai}}
{{/first_human_last_ai}}

{{!-- 按索引访问特定消息 --}}
第一条消息：{{all_messages.0}}
第二条消息：{{all_messages.1}}
```

* **`all_messages`**：按时间顺序排列的每条消息，包含 `role`（用户/助手/系统）和 `content` 字段。使用此变量显示完整的对话流程。
* **`human_ai_pairs`**：消息按问答对分组。每对包含 `human`（用户消息）和 `ai`（助手响应）。在评估响应质量时使用此变量。
* **`first_human_last_ai`**：仅包含初始问题（`first_human`）和最终答案（`last_ai`）。使用此变量检查 AI 是否最终回答了原始问题，忽略中间的对话。

### 带有线程上下文的示例

以下是一个使用线程上下文的实用评估器提示示例：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
评估此对话：

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

AI 有帮助吗？请从 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?"}
  ]
}

{{!-- 输出 --}}
评估此对话：

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?

AI 有帮助吗？请从 1-5 评分。
```

该模板使用 mustache 区块 `{{#all_messages}}` 遍历对话数组。对于每次迭代，区块将上下文设置为该消息对象，因此 `{{role}}` 和 `{{content}}` 访问当前消息的属性。循环自动按顺序遍历所有四条消息，将每条显示为 `"role: content"`。这为评估器 LLM 提供了完整的对话历史来评估帮助性。

在 LangSmith 中创建评估器时，选择要包含哪些线程变量。LangSmith 将自动从正在评估的对话中填充它们。

## 少样本示例

少样本提示通过示例来教导 LLM。您提供几个展示任务的输入-输出对，然后要求它对新的输入执行相同的任务。

[少样本示例](/langsmith/create-few-shot-evaluators#how-few-shot-examples-work) 帮助 LLM 理解：

* **格式期望**（例如，“用 JSON 响应”或“使用这种语气”）
* **边缘情况**（例如，如何处理模糊输入）
* **任务细微差别**（例如，“积极”和“非常积极”情感之间的区别）

这对于分类、格式化和风格任务特别有用，因为展示比讲述更清晰。

### 少样本占位符

在 LangSmith 中，在您希望示例出现的位置使用 `{{few_shot_examples}}` 占位符：

```mustache theme={"theme":{"light":"catppuccin-latte","dark":"catppuccin-mocha"}}
{{!-- 模板 --}}
你是一个情感分类器。

{{few_shot_examples}}

现在对以下文本进行分类：
文本：{{text}}
情感：
```

当您在 [LangSmith UI](https://smith.langchain.com) 中启用少样本示例（在评估器或提示中心中）时，您需要单独配置示例格式。LangSmith 会自动将那些格式化后的示例注入到您放置 `{{few_shot_examples}}` 占位符的任何位置。这使您的提示模板保持整洁，并允许您独立管理示例。

**配置示例后的输出示例：**

```
你是一个情感分类器。

文本：I love this!
情感：positive
文本：This is terrible.
情感：negative
文本：It's okay.
情感：neutral

现在对以下文本进行分类：
文本：This is amazing!
情感：
```

在 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 将拒绝转换或仅转换简单部分，从而破坏模板的功能。转换后请务必预览。

## 其他资源

* **[LangSmith 提示工程概念](https://docs.langchain.com/langsmith/prompt-engineering-concepts)**：关于有效提示策略的高级指南。
* **[Mustache 手册](https://mustache.github.io/mustache.5.html)**：包含所有功能的完整 mustache 规范。
* **[Python f-string 文档](https://docs.python.org/3/reference/lexical_analysis.html#f-strings)**：官方 Python f-string 语法（注意：LangSmith 使用简化子集）。

***

<div className="source-links">
  <Callout icon="edit">
    [Edit this page on GitHub](https://github.com/langchain-ai/docs/edit/main/src/i18n\zh-CN\langsmith\prompt-template-format.mdx) or [file an issue](https://github.com/langchain-ai/docs/issues/new/choose).
  </Callout>

  <Callout icon="terminal-2">
    [Connect these docs](/use-these-docs) to Claude, VSCode, and more via MCP for real-time answers.
  </Callout>
</div>
