Prompt templates(提示词模板)
语言模型以文本作为输入 - 这个文本通常被称为提示词(prompt)。
在开发过程中,对于提示词通常不能直接硬编码提供给模型使用,而是通过提示词模板进行维护,类似开发过程中遇到的短信模板、邮件模板等等。
到底什么是提示词模板?
提示词模板的核心是「固定逻辑 + 可变参数」:
- 固定部分:包含对任务目标、输出格式、约束条件、角色设定等通用要求的描述(比如 “你是一名前端工程师,需遵循 ES6 规范编写代码”);
- 可变参数:通过占位符(如
{变量名}、{变量名})预留的个性化输入项(比如{功能需求}、{代码语言}); - 使用时仅需替换变量值,即可快速生成符合要求的完整提示词,无需每次从头梳理指令逻辑。
- 一个提示词模板可以包含下面内容:
- 发给大语言模型(LLM)的指令。
- 一组问答示例,以提醒AI以什么格式返回请求。
- 发给语言模型的问题。
举个基础示例(前端代码生成模板):
import { PromptTemplate } from '@langchain/core/prompts';
const cotPromptTemplate = PromptTemplate.fromTemplate(`
角色:你是一名资深前端工程师,熟悉React和TypeScript,遵循组件化开发规范。
任务:根据以下需求编写可复用的{componentType}组件,要求:
1. 使用{codeLanguage}编写,符合ESLint规范;
2. 包含完整的类型定义和注释;
3. 输出格式:先写组件代码,再补充使用示例和注意事项。
需求详情:{functionalRequirements}
`)
const result = await cotPromptTemplate.format({
componentType: 'button',
codeLanguage: 'React',
functionalRequirements: '支持自定义尺寸、颜色,点击触发回调'
})
console.log(result)
使用时只需替换 组件类型(如 “按钮”)、代码语言(如 “TypeScript”)、功能需求(如 “支持自定义尺寸、颜色,点击触发回调”),就能快速生成标准化的组件开发提示词。
模板输出结果:
角色:你是一名资深前端工程师,熟悉React和TypeScript,遵循组件化开发规范。 任务:根据以下需求编写可复用的button组件,要求:
- 使用React编写,符合ESLint规范;
- 包含完整的类型定义和注释;
- 输出格式:先写组件代码,再补充使用示例和注意事项。 需求详情:支持自定义尺寸、颜色,点击触发回调
聊天消息提示词模板(chat prompt template)
聊天消息提示词模板(Chat Prompt Template)是适配 LLM 聊天场景的标准化提示词结构,核心作用是定义角色规则、约束输出风格、衔接上下文,让 LLM 输出符合预期的聊天回复。
一.Chat Prompt Template 核心结构
所有聊天模板都围绕「3 个核心模块」设计,可灵活组合:
| 模块 | 作用 | 示例占位符 |
|---|---|---|
| 系统提示 | 定义 LLM 角色、回复规则、语气风格(核心,决定对话基调) | {system_role} |
| 对话上下文 | 多轮聊天的历史记录(保证连贯性) | {chat_history} |
| 用户当前输入 | 用户最新发送的消息(核心输入) | {user_input} |
| 输出约束(可选) | 限制回复长度、格式、语言等(避免输出失控) | {output_constraint} |
二.通用 & 分场景 Chat Prompt Template
1.基础通用聊天模板(适配大部分场景)
适用于无特殊要求的日常闲聊,兼顾自然度和可控性:
{system_role}
【对话历史】
{chat_history}
【用户当前消息】
{user_input}
{output_constraint}
变量替换示例:
system_role:你是一个友好的聊天伙伴,语气轻松自然,回复简洁(1-3 句话),不使用专业术语,像和朋友聊天一样。chat_history:用户:今天下班吃什么?AI:可以试试楼下的牛肉面,味道超赞~user_input:那家牛肉面会不会很辣?output_constraint:回复控制在 20 字以内,只回答辣度相关问题,不推荐其他食物。
2.专业客服模板(电商 / 售后场景)
强调「问题解决导向 + 标准化话术 + 同理心」:
{system_role}
【核心规则】
1. 优先安抚用户情绪,再解决问题;
2. 未明确的信息(如订单号、商品型号)主动询问,但仅问1个问题/次;
3. 无法解答时,引导联系人工客服,不编造答案。
【历史对话】
{chat_history}
【用户当前咨询】
{user_input}
【输出要求】
- 语气:耐心、专业、有同理心;
- 长度:30-50 字;
- 格式:先回应情绪 → 解答问题 → 确认是否需要进一步帮助。
变量替换示例:
system_role:你是电商售后客服,负责解答商品退换货、物流、价格相关问题。
3. 技术问答模板(适配前端 / LLM 开发场景)
强调「准确性 + 步骤化 + 简洁性」,贴合你的技术背景:
{system_role}
【回答规则】
1. 技术问题优先给出「步骤化解决方案」,再补充注意事项;
2. 涉及代码的,给出可运行的极简示例(不超过 5 行);
3. 仅回答前端/LLM 开发相关问题,其他问题告知无法解答。
【历史对话】
{chat_history}
【用户技术问题】
{user_input}
【输出约束】
- 语言:简洁易懂,避免冗余;
- 格式:分点说明(最多 3 点),代码用 ```js 包裹。
变量替换示例:
system_role:你是资深前端工程师,擅长 Node.js、LangChain、Ollama 相关开发。
4. 多轮对话优化模板(带上下文裁剪)
解决长对话上下文超限问题,仅保留关键历史:
{system_role}
【上下文规则】
- 仅保留和当前问题相关的历史对话(无关内容已裁剪);
- 回复时无需提及「上下文已裁剪」,自然衔接即可。
【关键对话历史】
{chat_history}
【用户当前输入】
{user_input}
【输出要求】
- 回复需基于历史对话,避免重复提问;
- 长度:1-4 句话,语气连贯。
5. 结构化输出模板(需 JSON / 固定格式)
适用于需要机器解析回复的场景(如对接业务系统):
{system_role}
【输出格式强制要求】
必须返回 JSON 格式,包含以下字段:
- role: 固定值 "assistant";
- content: 回复内容(字符串);
- confidence: 回答置信度(0-1,如不确定则为 0.5);
- need_follow: 是否需要追问(true/false)。
【对话历史】
{chat_history}
【用户输入】
{user_input}
【禁止】
不输出任何 JSON 外的内容,包括注释、说明文字。
示例输出:
{
"role": "assistant",
"content": "Node.js 读取本地文件可使用 fs 模块,示例:fs.readFile('test.txt', (err, data) => {console.log(data);})",
"confidence": 0.95,
"need_follow": false
}
三、LangChain 中使用 Chat Prompt Template
结合 LangChain 的 ChatPromptTemplate 类,可快速封装模板并对接 Ollama 模型,示例如下:
import { ChatPromptTemplate } from "@langchain/core/prompts";
import { ChatOllama } from "@langchain/ollama";
// 1. 定义聊天提示词模板(以技术问答为例)
const chatPrompt = ChatPromptTemplate.fromMessages([
// 系统提示(角色 + 规则)
["system", `你是资深前端工程师,擅长 Node.js、LangChain、Ollama 开发。
回答规则:
1. 技术问题优先给出步骤化解决方案;
2. 代码示例不超过 5 行;
3. 回复控制在 50 字以内。`],
// 对话上下文(多轮时自动填充)
["placeholder", "{chat_history}"],
// 用户当前输入
["user", "{user_input}"]
]);
// 2. 初始化 Ollama 模型
const model = new ChatOllama({
model: "qwen3:0.6b",
temperature: 0.2
});
// 3. 组装模板 + 调用模型
async function runChatTemplate() {
// 填充模板变量
const prompt = await chatPrompt.format({
chat_history: "用户:Node.js 怎么读文件?AI:用 fs 模块的 readFile 方法~",
user_input: "readFile 是异步的吗?有没有同步方法?"
});
// 调用模型获取回复
const response = await model.invoke(prompt);
console.log("模型回复:", response);
}
// 运行测试
runChatTemplate();
四、模板设计关键技巧
- 角色明确:系统提示中清晰定义 LLM 的身份(如「前端工程师」「电商客服」),避免回复偏离定位;
- 规则具体:不用模糊表述(如「回答准确」),而是明确约束(如「代码示例不超过 5 行」);
- 上下文可控:多轮对话时裁剪无关历史,避免上下文窗口超限(如 Qwen3:4B 上下文 32K,需控制历史长度);
- 变量解耦:将「角色、历史、输入」拆分为独立变量,便于动态替换和维护。
使用示例选择器
这里我们使用SemanticSimilarityExampleSelector类。该类根据与输入的相似性选择小样本示例。它使用嵌入模型计算输入和小样本示例之间的相似性,然后使用向量数据库执行相似搜索,获取跟输入相似的示例。
提示:这里涉及向量计算、向量数据库,在AI领域这两个主要用于数据相似度搜索,例如:查询相似文章内容、相似的图片、视频等等,这里先简单了解下就行。
.env文件配置
# Ollama 配置
OLLAMA_BASE_URL=http://localhost:11434
OLLAMA_EMBED_MODEL=nomic-embed-text:latest
OLLAMA_THINK_MODEL=deepseek-r1:1.5b
# Chroma 向量数据库配置
CHROMA_URL=http://localhost:8000
CHROMA_COLLECTION_NAME=few-shot-examples
CHROMA_PERSIST_DIR=./chroma-data
import * as dotenv from 'dotenv';
dotenv.config();
import { Document } from '@langchain/core/documents';
import { SemanticSimilarityExampleSelector } from '@langchain/core/example_selectors';
import { Chroma } from '@langchain/community/vectorstores/chroma'; // Chroma 向量存储
import { ChatOllama, OllamaEmbeddings } from '@langchain/ollama'; // 本地嵌入模型
import { PromptTemplate } from '@langchain/core/prompts'; // 可选:用于构建提示词
import { CallbackManager } from '@langchain/core/callbacks/manager';
const embeddings = new OllamaEmbeddings({
model: process.env.OLLAMA_EMBED_MODEL, // 轻量嵌入模型
baseUrl: process.env.OLLAMA_BASE_URL, // Ollama 服务地址
});
// 1. 初始化回调管理器(打印每个步骤的日志)
const callbackManager = CallbackManager.fromHandlers({
// 监听 LLM 生成环节(推理的核心:模型正在生成回答)
handleLLMStart: (params) => {
console.log('\n=== 推理环节:模型开始生成回答 ===');
console.log('输入给模型的 Prompt:', params);
},
// 监听 LLM 生成结束(推理完成,即将返回回答)
handleLLMEnd: (output) => {
console.log('模型原始输出:', output);
console.log('\n=== 推理环节:模型生成结束 ===');
},
});
// 2 准备示例数据(用于筛选的样本,格式:对象数组,含输入/输出等字段)
const examples = [
{
input: '如何在 Node.js 中安装 LangChain?',
output: '执行命令:npm install @langchain/core @langchain/community',
category: '安装问题', // 可选:元数据,用于过滤
},
{
input: 'Chroma 如何持久化数据?',
output: '启动 Chroma 时指定 --path 目录(本地)或挂载 Docker 卷(容器)',
category: 'Chroma 问题',
},
{
input: 'SemanticSimilarityExampleSelector 作用是什么?',
output: '根据查询的语义相似度,从示例集中筛选最相关的样本(用于 Few-Shot)',
category: 'ExampleSelector 问题',
},
{
input: 'Ollama 如何启动服务?',
output: '终端执行命令:ollama serve(默认端口 11434)',
category: 'Ollama 问题',
},
];
// 3. 创建 Chroma 向量存储(存储示例数据的向量)
const vectorStore = await Chroma.fromDocuments(
// 将示例数据转为 Document 类(Chroma 要求输入为 Document 数组)
examples.map(
(example) =>
new Document({
pageContent: JSON.stringify(example), // 存储示例完整信息(JSON 字符串)
metadata: { category: example.category }, // 元数据(用于后续过滤)
})
),
embeddings, // 嵌入模型(自动将示例转为向量)
{
collectionName: process.env.CHROMA_COLLECTION_NAME, // Chroma 集合名称(类似数据库表名) 若 Chroma 已存在同名集合(collectionName),会直接复用,不会重复创建
url: process.env.CHROMA_URL, // Chroma 服务地址
persistDirectory: process.env.CHROMA_PERSIST_DIR, // 本地 Chroma 时可选(指定数据存储路径)
}
);
// 4. 实例化 SemanticSimilarityExampleSelector(核心步骤)
const exampleSelector = new SemanticSimilarityExampleSelector({
vectorStore, // 绑定 Chroma 向量存储(示例数据存在这里)
k: 2, // 最多返回 2 个最相似的示例
inputKeys: ['input'], // 用于计算相似度的「查询字段」(与示例的 input 对应)
});
// 5. 筛选相似示例(核心功能)
const userQuery = 'Chroma 数据怎么持久化到本地?'; // 用户查询
await Promise.all(examples.map((item) => exampleSelector.addExample(item)));
const selectedExamples = await exampleSelector.selectExamples({ input: userQuery });
// 6. 结合 LLM 实现 Few-Shot 回答(完整落地场景)
// 构建提示词模板(包含筛选出的示例)
const promptTemplate = PromptTemplate.fromTemplate(`
参考:{examples}
问题:{question}
`);
// 格式化示例(转为自然语言文本)
const formattedExamples = selectedExamples.map((ex) => `问:${ex.input}\n答:${ex.output}`).join('\n\n');
// 初始化 LLM(使用环境变量配置)
const llm = new ChatOllama({
model: process.env.OLLAMA_THINK_MODEL,
streaming: true,
callbacks: callbackManager,
});
// 执行链(提示词 + LLM)
const chain = promptTemplate.pipe(llm);
const response = await chain.invoke({
examples: formattedExamples,
question: userQuery,
});
console.log('\n=== LLM 最终回答 ===');
console.log(response.content);