96SEO 2026-04-22 16:50 0
作为一名后端开发者,你可NengYi经迫不及待地想在自己的NestJS项目中接入像LangChain这样强大的框架了。说实话,直接把字符串硬编码在代码里发给大模型,虽然刚开始觉得挺爽,但一旦项目复杂起来维护起来简直就是一场灾难。这时候,Prompt Template就成了你的救命稻草。今天咱们就抛开那些枯燥的官方文档,用一种geng接地气的方式,深入聊聊在NestJS环境下到底该怎么优雅地玩转LangChain的Prompt模板。

想象一下你正在开发一个智Neng客服系统。Ru果每次用户提问,你dou要手写一段“请你作为一个客服人员,回答用户关于...的问题”,这不仅累,而且极易出错。Prompt Template本质上就是一种“填空题”的逻辑。它把那些固定的指令封装起来只留出几个“坑”让你在运行时动态填入。这不仅让代码整洁了不少,还Neng复用逻辑,何乐而不为呢?
在LangChain的世界里Zui核心的两种模板形式莫过于 PromptTemplate 和 ChatPromptTemplate。虽然它们名字听起来hen像,但用法和适用场景却有着天壤之别。咱们一个一个来拆解。
登场的是 PromptTemplate。这是Zui基础的形式,它主要用于生成纯文本字符串。当你不需要区分消息角色,只是单纯想给LLM发送一段指令时它就是你的首选。
在NestJS的服务层中,我们通常会这样引入它:
import { PromptTemplate } from '@langchain/core/prompts';
async demonstrateBasicUsage: Promise {
// 1. 定义模板字符串,用花括号 {variable} 标记变量位置
const templateString = '请针对{topic}这个领域,给我写一篇关于{type}的简短介绍。';
// 2. 实例化模板对象,并告知它有哪些变量需要填充
const promptTemplate = new PromptTemplate({
template: templateString,
inputVariables: ,
});
// 3. 使用 format 方法填充变量,生成Zui终的提示词
// 注意:在NestJS中,format 方法是同步的,不需要 await
const finalPrompt = promptTemplate.format({
topic: '量子力学',
type: '科普向'
});
console.log;
// 输出: 生成的提示词: 请针对量子力学这个领域,给我写一篇关于科普向的简短介绍。
}
kan到这里你可Neng会问,每次dou要 new 一个实例,还要手动列 inputVariables,是不是有点太繁琐了?别急,LangChain也提供了一个geng便捷的静态方法 .fromTemplate,它Neng自动帮你识别模板里的变量名,省去了不少敲键盘的功夫。
const quickTemplate = PromptTemplate.fromTemplate(
'请简要评价{product}在{aspect}方面的表现。'
);
const promptValue = quickTemplate.format;
进阶篇:ChatPromptTemplate 的角色扮演
现在的LLM大多是基于Chat模型的,它们geng习惯处理“对话”结构,而不是一大段纯文本。这时候,ChatPromptTemplate 就该闪亮登场了。它允许我们定义不同角色的消息,比如 System、Human和 AI。
在NestJS中,构建一个多角色的对话模板非常直观。我们Ke以使用 fromMessages 方法,传入一个元组数组,每个元组定义了角色和内容。
import {
ChatPromptTemplate,
SystemMessagePromptTemplate,
HumanMessagePromptTemplate
} from '@langchain/core/prompts';
async createChatPrompt {
// 使用 fromMessages 静态方法构建
const chatTemplate = ChatPromptTemplate.fromMessages(,
]);
// 调用 invoke 方法,注意这里是异步的!
// invoke 返回的是一个 ChatPromptValue 对象,里面包含了格式化后的消息数组
const result = await chatTemplate.invoke({
name: '阿强',
question: 'React Hooks 的依赖项数组到底该怎么填?'
});
console.log;
}
这里有个细节需要特别注意:invoke 是异步方法,必须使用 await。Ru果你直接打印 result,可Neng会kan到一个 Promise 对象而不是你想要的结果。另外result.messages 就是我们Zui终传给大模型的 BaseMessage 数组,里面包含了 SystemMessage 和 HumanMessage 实例。
在实际开发中,我发现hen多同学对 ChatPromptTemplate 的几个调用方法容易混淆。其实它们的主要区别在于返回值类型和是否异步:
.invoke: 异步。返回 ChatPromptValue 对象。这是Zui标准的 LangChain Runnable 接口调用方式,适合直接链式传递给 LLM。
.formatMessages: 异步。直接返回 BaseMessage 数组。Ru果你只需要消息列表而不需要包装对象,用这个hen方便。
.format: 同步。返回纯文本字符串。它会将所有消息拼接成一个字符串,通常用于调试或者不需要消息结构的场景。
// 演示三种方式的区别
const template = ChatPromptTemplate.fromMessages(,
]);
// 1. invoke
const val1 = await template.invoke;
// 2. formatMessages
const val2 = await template.formatMessages;
// 3. format
const val3 = template.format;
高级技巧:部分变量填充
有时候,我们会有这样的需求:一个模板里有五个变量,但其中三个是固定的,只有两个是每次请求dou不一样的。Ru果每次dou要把这三个固定的变量传一遍,那代码冗余度就太高了。
LangChain 提供了 partial 功Neng,专门解决这个问题。我们Ke以预先填充一部分变量,生成一个新的“半成品”模板。
在创建模板时就Ke以通过 partialVariables 参数指定预填充的值。
const partialTemplate = new PromptTemplate({
template: '请评价{product}的优缺点,重点关注{aspect1}和{aspect2}。',
inputVariables: , // 只需要声明剩余未填充的变量
partialVariables: {
aspect1: '电池续航' // 预先固定这个值
}
});
// 使用时只需传 product 和 aspect2
const promptA = partialTemplate.format({
product: '某品牌手机',
aspect2: '屏幕显示'
});
方式二:链式调用 .partial
Ru果你Yi经有一个完整的模板对象,也Ke以直接调用 .partial 方法。这在动态配置场景下非常有用。
const baseTemplate = PromptTemplate.fromTemplate(
'请分析{target}在{season}的表现,主要kan{metric}。'
);
// 动态生成一个只关注“春季”和“销售额”的模板
const seasonalTemplate = await baseTemplate.partial({
season: '春季',
metric: '销售额'
});
// 后续调用只需传入 target
const promptB = seasonalTemplate.format;
动态消息列表:MessagesPlaceholder
在构建聊天机器人时我们经常需要把用户的“历史聊天记录”塞给模型,让它Neng记住上下文。但是历史记录的长度是不确定的,这时候普通的模板变量就不够用了。
这时候,MessagesPlaceholder 就派上用场了。它就像一个特殊的占位符,告诉模板:“嘿,这里到时候我会塞给你一整个消息列表,你别管有多少条,全部放进去就行。”
import { MessagesPlaceholder } from '@langchain/core/prompts';
async createHistoryPrompt {
const historyTemplate = ChatPromptTemplate.fromMessages(,
// 👇 这里放一个占位符,变量名是 'chat_history'
new MessagesPlaceholder,
]);
const result = await historyTemplate.invoke({
name: '小智',
// 这里传入一个包含历史消息的数组
chat_history: ,
input: "我刚才说我叫什么?"
});
console.log;
}
这种结构非常灵活,因为它允许你在 System 指令和当前用户输入之间,插入任意长度的对话历史。这是实现具备记忆功NengAI应用的关键一步。
少样本提示除了上述的结构化技巧,LangChain 还支持“少样本提示”。简单来说就是通过给模型kan几个例子,让它学会怎么回答。这在处理复杂任务时效果奇佳。
虽然这部分逻辑稍微复杂一点,通常涉及到 ExampleSelector,但其核心思想依然是模板化。你Ke以把“例子”kan作是一种特殊的变量填充。每个例子通常是一个字典,键对应输入变量,值对应具体的输入和输出。
比如你想让模型学会Zuo“情感分析”,你Ke以构建一个包含正面、负面例子的模板。虽然这里不展开具体的代码实现,但理解了“用例子来教模型”这个逻辑,配合前面提到的 PromptTemplate,你就Neng组合出非常强大的提示词策略。
在NestJS中使用LangChain的Prompt模板,其实就是在Zuo“结构化”的工作。把混乱的自然语言指令,变成代码中可维护、可复用的对象。
Zui后再强调几个开发中容易踩的坑:
异步与同步的混淆在NestJS里invoke 和 formatMessages 是异步的,千万别忘了 await,否则你拿到的只是一个 Promise 对象,直接传给 LLM 会报错。
变量名匹配模板里的 {variable} 必须与 inputVariables 数组或者调用时传入的对象键名完全一致,少一个字母dou不行。
消息类型的选择Ru果你是在Zuo聊天机器人,优先使用 ChatPromptTemplate;Ru果只是简单的文本补全,用 PromptTemplate 就够了。别把简单的事情复杂化。
掌握了这些,你就Neng在NestJS中构建出既灵活又强大的AI应用了。别光kan,赶紧去你的项目里试试吧!
作为专业的SEO优化服务提供商,我们致力于通过科学、系统的搜索引擎优化策略,帮助企业在百度、Google等搜索引擎中获得更高的排名和流量。我们的服务涵盖网站结构优化、内容优化、技术SEO和链接建设等多个维度。
| 服务项目 | 基础套餐 | 标准套餐 | 高级定制 |
|---|---|---|---|
| 关键词优化数量 | 10-20个核心词 | 30-50个核心词+长尾词 | 80-150个全方位覆盖 |
| 内容优化 | 基础页面优化 | 全站内容优化+每月5篇原创 | 个性化内容策略+每月15篇原创 |
| 技术SEO | 基本技术检查 | 全面技术优化+移动适配 | 深度技术重构+性能优化 |
| 外链建设 | 每月5-10条 | 每月20-30条高质量外链 | 每月50+条多渠道外链 |
| 数据报告 | 月度基础报告 | 双周详细报告+分析 | 每周深度报告+策略调整 |
| 效果保障 | 3-6个月见效 | 2-4个月见效 | 1-3个月快速见效 |
我们的SEO优化服务遵循科学严谨的流程,确保每一步都基于数据分析和行业最佳实践:
全面检测网站技术问题、内容质量、竞争对手情况,制定个性化优化方案。
基于用户搜索意图和商业目标,制定全面的关键词矩阵和布局策略。
解决网站技术问题,优化网站结构,提升页面速度和移动端体验。
创作高质量原创内容,优化现有页面,建立内容更新机制。
获取高质量外部链接,建立品牌在线影响力,提升网站权威度。
持续监控排名、流量和转化数据,根据效果调整优化策略。
基于我们服务的客户数据统计,平均优化效果如下:
我们坚信,真正的SEO优化不仅仅是追求排名,而是通过提供优质内容、优化用户体验、建立网站权威,最终实现可持续的业务增长。我们的目标是与客户建立长期合作关系,共同成长。
Demand feedback