本页介绍 提示词模板 在 Playground, 提示词中心和 评估器中支持的提示词模板格式。提示词模板允许您创建可重用的提示词,这些提示词具有在运行时填充的动态占位符。
LangSmith 支持两种提示词模板格式,适用于不同复杂程度的场景:
| 格式 | 语法 | 适用于 |
|---|---|---|
| **f-string** | {variable} | 简单提示词,基本变量替换 |
| **mustache** | {{variable}} | 复杂提示词,包含循环、条件语句、嵌套数据或评估器 |
F-string 语法 非常适合简单直接的提示词。 Mustache 提供处理复杂数据结构和逻辑的功能,对评估器和高级用例很有帮助。
您可以在 UI中切换格式。LangSmith 会在可能的情况下自动 转换您的模板 ,但某些 Mustache 功能(如循环和条件语句)无法转换为 F-string 格式。
F-string 语法
F-string 模板使用 Python 风格格式,单花括号 {variable}。LangSmith 使用 简化子集 Python 的 f-string 语法:仅支持基本变量替换,不支持 Python 表达式和格式化选项的全部功能。当您有扁平数据结构且只需将值插入提示词时,F-string 是理想选择。
基本变量
变量将替换为输入数据中的相应值。变量名称必须完全匹配(区分大小写):
# Template
Hello, {name}! Welcome to {company}.
# Input
{
"name": "Ashley",
"company": "LangChain"
}
# Output
Hello, Ashley! Welcome to LangChain.
模板运行时,LangSmith 会在输入对象中查找每个变量名称并替换 {name} 为 name key.
变量名称
F-string 变量名称被视为简单的字符串标识符。它们不能包含点、括号或特殊字符,只能包含字母、数字和下划线。
# Template
Hello, {name}!
Your topic is: {topic}
# Input
{
"name": "Ashley",
"topic": "LangSmith"
}
# Output
Hello, Ashley!
Your topic is: LangSmith
如果您的输入包含嵌套对象(如 {"user": {"name": "Ashley"}}),则 **不能** 使用以下方式访问嵌套值 {user.name} 在 f-string 格式中。点将被视为变量名的一部分(字面意思是查找名为 "user.name"的键),而不是路径分隔符。对于嵌套访问,请使用 mustache 格式 instead.
字面量花括号
有时您需要在输出中包含实际的花括号(例如,在 JSON 示例或代码片段中)。为此,请 **双写花括号**:
# 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%}进行百分比格式化。 - Expressions: 不能使用
{x + y},{len(items)}, or{value if condition else default}. - 函数调用: 不能使用
{str.upper()}或其他方法调用。 - 循环或条件语句: 不支持控制流结构。
- 数组索引: 不能使用
{items[0]}来访问数组元素。
对于以上任何高级功能,请 **改用 mustache 格式**.
Mustache 语法
Mustache 是一种"无逻辑"的模板语言,这意味着它不允许任意代码执行,但通过 sections 提供结构化的控制流。它被称为"无逻辑"是因为您不能编写复杂的表达式——相反,您需要结构化数据来控制渲染内容。
Mustache 专为复杂数据结构和动态渲染而设计。它对于以下场景是必需的:
- Evaluators: 处理线程历史和对话上下文。
- Few-shot 提示: 遍历示例列表。
- 嵌套数据: 访问深度嵌套的对象和数组。
- 条件内容: 根据数据存在情况显示不同文本。
双花括号语法 {{variable}} 将其与 f-strings 区分开来。
基本变量
与 f-strings 一样,mustache 用变量的值替换变量:
{{!-- Template --}}
Hello, {{name}}! Welcome to {{company}}.
{{!-- Input --}}
{
"name": "Ashley",
"company": "LangChain"
}
{{!-- Output --}}
Hello, Ashley! Welcome to LangChain.
嵌套对象访问
您可以使用点表示法遍历嵌套对象:
{{!-- 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}}结尾。内部发生什么取决于该值:
- Array: 为每个元素重复内容。
- Object: 使用该对象作为上下文渲染一次。
- 真值: 渲染一次。
- 假值(false、null、undefined、空数组): 不渲染。
在以下示例中,区块 {{#items}} 遍历 items 数组。对于每次迭代,区块内的变量(如 {{name}} 和 {{price}})会根据当前数组元素进行解析:
{{!-- 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
区块消除了手动构建重复文本的需要。在求值器中,你可以使用区块来遍历对话消息或 少样本示例.
对于深层嵌套的层次数据,你可以嵌套多个区块来处理具有多层数组和对象的复杂结构:
{{!-- 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)
嵌套循环
你可以嵌套区块来处理多级数据结构:
{{!-- 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}} 遍历该类别的产品。
当你的数据具有层次关系时使用嵌套循环——带产品的类别、带员工的部门或具有多个交流的对话线程。
通过索引访问数组元素
有时你需要一个特定的元素而不是循环。使用点号表示法和数字索引:
{{!-- 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:
{{!-- 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}} 在 name 中查找 user).
仅在用户数据可用时显示可选内容(如"欢迎回来"消息),或仅在存在错误时显示错误消息。
反转区块
反转部分仅在值不存在、为 false、null、undefined 或空数组时渲染。反转部分常用于处理空状态,例如数据缺失或空列表。
在以下示例中:
- -
{{#results}}遍历每个结果并为每个条目渲染一行。 - -
{{^results}}仅在 results 数组为空或缺失时渲染。 - - 当没有结果要显示时,反转部分提供了一个清晰的回退方案。
{{!-- 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.
You can also combine regular and inverted sections to create if/else logic, providing default values when variables are missing.
常规部分 {{#username}} 仅在以下情况下渲染 username 存在时。反转部分 {{^username}} renders only if it doesn't. Together, they create an if/else branch. This is useful for personalizing prompts when user data is optional or showing default instructions when custom ones aren't provided:
{{!-- Template --}}
{{#username}}
Hello, {{username}}!
{{/username}}
{{^username}}
Hello, Guest!
{{/username}}
{{!-- Input (with username) --}}
{"username": "Ashley"}
{{!-- Output: Hello, Ashley! --}}
{{!-- Input (no username) --}}
{}
{{!-- Output: Hello, Guest! --}}
此模式可扩展到布尔标志,允许您根据数据条件更改输出格式:
{{!-- 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 }} or {{!-- comment --}}:
{{!-- 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 提供三种预结构化的对话 线程:
{{!-- 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}}
- - **
all_messages**视图:按时间顺序排列的每条消息,带有role(user/assistant/system) andcontent字段。使用此视图显示完整的对话流程。 - - **
human_ai_pairs**:消息分组为问答对。每对包含human(用户消息)和ai(助手回复)。在评估回复质量时使用此视图。 - - **
first_human_last_ai**:仅包含初始问题(first_human)和最终答案(last_ai)。使用此视图检查 AI 最终是否回答了原始问题,忽略中间对话。
使用线程上下文的示例
以下示例是一个使用线程上下文的实际评估器提示:
{{!-- 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 会自动从正在评估的对话中填充这些变量。
小样本示例
小样本提示通过示例来教导 LLM。您提供几个展示任务的输入-输出对,然后让它在新输入上执行相同的任务。
小样本示例 帮助 LLM 理解:
- 格式期望 (例如,"用 JSON 响应"或"使用此语气")
- 边缘情况 (例如,如何处理歧义输入)
- 任务细微差别 (例如,"积极"与"非常积极"情感之间的区别)
这对于分类、格式化和文体任务特别有用,在这些任务中,展示比讲述更清晰。
少样本占位符
在 LangSmith 中,使用 {{few_shot_examples}} 占位符来指定示例出现的位置:
{{!-- 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-strings 中没有等价物,无法转换:
- 点号表示法:
{{user.name}}F-strings 会将"user.name"视为单个变量名,而非嵌套访问。 - Sections/loops:
{{#items}}...{{/items}}F-strings 中无等价功能。 - Conditionals:
{{#value}}...{{/value}}F-strings 中无等价功能。 - 反转区段:
{{^value}}...{{/value}}F-strings 中无等价功能。 - Comments:
{{! comment }}F-strings 中无等价功能。
如果您尝试转换包含这些功能的 Mustache 模板,LangSmith 将拒绝转换或仅转换简单部分,从而破坏模板的功能。转换后请务必预览。
其他资源
- - **LangSmith 提示工程概念**:关于有效提示策略的高级指导。
- - **Mustache 手册**:包含所有功能的完整 Mustache 规范。
- - **Python F-string 文档**:官方 Python F-string 语法(注意:LangSmith 使用的是简化的子集)。