尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

LangChain提示词模板进化史-通用模板-FewShot-ChatPromptTemplate

LangChain提示词模板进化史-通用模板-FewShot-ChatPromptTemplate LangChain 提示词模板进化史从字符串拼接到优雅的模板引擎模型调用学会了接下来要解决一个更头疼的问题——提示词管理。你有没有经历过把一大段提示词硬编码在字符串里改一个词就要翻遍整个代码库稍不留神就拼错变量名。LangChain 的提示词模板系统就是来终结这种痛苦的。它把提示词从手写字符串升级为可复用的模板引擎让提示词管理变得优雅、安全、可维护。一、提示词为什么需要模板化先看看没有模板的日子长什么样# 原始写法字符串手拼灾难现场rolePython 高级工程师skill代码审查task找出下面代码的性能瓶颈promptf你是一位{role}擅长{skill}。请帮我{task}。看着还行等项目大了你就知道痛痛点说明散落各处提示词逻辑和业务代码混在一起改一个词要翻几十个文件变量不安全用户输入里有大括号{}直接炸还得手动转义无法复用同一个提示词结构换个场景就得复制粘贴再改难以迭代想对比两版提示词的效果只能改代码、跑一遍、再改回来多轮对话噩梦system / human / ai 角色混在一起字符串拼接像在拆炸弹模板化的本质是把提示词的骨架和填入的数据彻底分开。骨架是模板数据是变量两者各管各的互不干扰。二、PromptTemplate一切模板的起点PromptTemplate是 LangChain 里最基础的模板类。它用{变量名}做占位符支持动态填充2.1 基础用法fromlangchain.promptsimportPromptTemplate# 定义模板骨架templatePromptTemplate.from_template(你是一位{role}请用{style}的风格回答以下问题{question})# 填入数据生成最终提示词prompttemplate.format(role资深律师,style严谨专业,question签订劳动合同需要注意哪些法律风险)print(prompt)# 你是一位资深律师请用严谨专业的风格回答以下问题签订劳动合同需要注意哪些法律风险2.2 两种创建方式fromlangchain.promptsimportPromptTemplate# 方式一from_template推荐日常够用templatePromptTemplate.from_template(请用{language}写一段{task}的代码)# 方式二显式声明 input_variables更严谨支持参数校验templatePromptTemplate(template请用{language}写一段{task}的代码,input_variables[language,task]# 明确声明需要哪些变量)日常用from_template就够了。但如果你的模板变量很多显式声明input_variables可以在传错变量时立刻报错而不是默默生成奇怪的提示词。2.3 部分填充先填一半剩下的后面再说有些变量是全局固定的比如公司名、产品名每次都传一遍太啰嗦。partial允许你先填一部分生成一个半成品模板fromlangchain.promptsimportPromptTemplate templatePromptTemplate.from_template(你是{company}的{role}请回答{question})# 先把 company 固定为阿里巴巴partial_templatetemplate.partial(company阿里巴巴)# 后续只需要填剩下的变量print(partial_template.format(role客服专员,question如何退货))# 你是阿里巴巴的客服专员请回答如何退货实战技巧把 system prompt 里的公司名、术语规范、输出格式要求等固定内容用partial预填充后续调用只需传核心变量代码清爽很多。三、ChatPromptTemplate多轮对话的剧本编辑器聊到多轮对话PromptTemplate就扛不住了——它只能处理一段纯文本而聊天场景需要区分system / human / ai三种角色。ChatPromptTemplate就是为这个而生的。3.1 基础用法给每个角色写台词模板fromlangchain.promptsimportChatPromptTemplate templateChatPromptTemplate.from_messages([(system,你是一位{role}擅长{skill}。请用中文回答。),(human,请帮我{task}),])# 填入变量messagestemplate.format_messages(role数据分析师,skillSQL 优化,task分析这条 SQL 为什么慢SELECT * FROM orders WHERE year2024)print(messages)# [# SystemMessage(content你是一位数据分析师擅长SQL 优化。请用中文回答。),# HumanMessage(content请帮我分析这条 SQL 为什么慢SELECT * FROM orders WHERE year2024)# ]3.2 四种消息构造方式ChatPromptTemplate支持多种写法你可以选最顺手的一种fromlangchain.promptsimportChatPromptTemplatefromlangchain.schemaimportSystemMessage,HumanMessage# 方式一元组简写推荐最简洁templateChatPromptTemplate.from_messages([(system,你是{role}),(human,{question}),])# 方式二Message 对象字段名更直观templateChatPromptTemplate.from_messages([SystemMessage(content你是{role}),HumanMessage(content{question}),])# 方式三带 role 的字典JS 开发者可能更习惯templateChatPromptTemplate.from_messages([{role:system,content:你是{role}},{role:user,content:{question}},])3.3 MessagesPlaceholder给历史消息留个插槽多轮对话的核心需求把之前的对话历史塞进模板。MessagesPlaceholder就是干这个的——它在模板里留一个插槽专门用来插入一组消息fromlangchain.promptsimportChatPromptTemplate,MessagesPlaceholder templateChatPromptTemplate.from_messages([(system,你是一个有用的助手。),MessagesPlaceholder(variable_namehistory),# ← 历史消息插槽(human,{question}),])# 模拟历史对话history[(human,我叫张三),(ai,你好张三有什么可以帮你的),(human,我今年 30 岁),(ai,了解30 岁正是好年纪),]# 填入历史 新问题messagestemplate.format_messages(historyhistory,question我叫什么名字今年多大)print(messages)# 模型会看到完整的对话历史因此能正确回答你叫张三今年30岁这就是 Memory 组件的底层。MessagesPlaceholder是插槽Memory 组件负责往插槽里填历史消息。后面讲 Memory 时你会发现它本质上就是一个自动管理插槽内容的工具。四、FewShotPromptTemplate教模型照猫画虎有时候光靠 system prompt 说不清楚给几个例子效果立竿见影。FewShotPromptTemplate让你把示例也做成模板的一部分4.1 基础用法fromlangchain.promptsimportFewShotPromptTemplate,PromptTemplate# 准备示例examples[{input:今天天气真好,output:正面},{input:服务太差了气死我了,output:负面},{input:还行吧不好不坏,output:中性},]# 定义示例的格式模板example_templatePromptTemplate.from_template(输入{input}\n输出{output})# 组装 FewShot 模板fewshot_templateFewShotPromptTemplate(examplesexamples,example_promptexample_template,prefix请对以下文本做情感分析输出正面、负面或中性。\n\n示例,suffix\n输入{text}\n输出,input_variables[text],)print(fewshot_template.format(text这个产品质量不错推荐购买))输出效果请对以下文本做情感分析输出正面、负面或中性。 示例 输入今天天气真好 输出正面 输入服务太差了气死我了 输出负面 输入还行吧不好不坏 输出中性 输入这个产品质量不错推荐购买 输出4.2 动态选择示例不要让示例自说自话固定示例的问题是不管用户问什么都给同样的示例。更好的做法是根据用户输入动态选择最相关的示例fromlangchain.promptsimportFewShotPromptTemplate,PromptTemplatefromlangchain.prompts.example_selectorimportSemanticSimilarityExampleSelectorfromlangchain_openaiimportOpenAIEmbeddingsfromlangchain_community.vectorstoresimportChroma# 准备示例库examples[{input:这段代码怎么优化性能,output:你可以考虑1. 减少循环嵌套 2. 使用缓存...},{input:这个 SQL 查询太慢了,output:建议1. 添加索引 2. 避免 SELECT * 3. 使用 EXPLAIN 分析...},{input:如何部署到服务器,output:步骤1. 打包应用 2. 配置环境变量 3. 使用 Docker...},{input:Python 里的装饰器怎么用,output:装饰器是一种高阶函数基本语法是...},]# 用向量相似度动态选择最相关的示例example_selectorSemanticSimilarityExampleSelector.from_examples(examplesexamples,embeddingsOpenAIEmbeddings(),vectorstore_clsChroma,k2,# 选最相关的 2 个示例)fewshot_templateFewShotPromptTemplate(example_selectorexample_selector,example_promptPromptTemplate.from_template(问题{input}\n解答{output}),prefix你是一个编程助手。以下是一些参考示例,suffix问题{question}\n解答,input_variables[question],)# 用户问数据库相关自动匹配到 SQL 示例print(fewshot_template.format(question数据库查询优化怎么做))动态示例选择的本质把示例库向量化用户问题来了之后用语义相似度检索最相关的几个示例。这比固定示例效果好得多也是 RAG检索增强生成思想的雏形。五、模板 模型 管道一条龙服务模板本身只是造提示词的工具真正让它发光的是和模型串成链。用 LCEL 的管道符|一行代码把模板、模型、输出解析器串起来fromlangchain.promptsimportChatPromptTemplatefromlangchain_openaiimportChatOpenAIfromlangchain.schema.output_parserimportStrOutputParser# 模板templateChatPromptTemplate.from_messages([(system,你是一个{role}擅长{skill}。),(human,{question}),])# 模型llmChatOpenAI(modelgpt-4o-mini,temperature0.7)# 串成链chaintemplate|llm|StrOutputParser()# 一行调用resultchain.invoke({role:脱口秀演员,skill:程序员段子,question:讲一个关于 Git 的段子,})print(result)管道符的两种调用方式# 方式一invoke一次性调用resultchain.invoke({role:翻译官,skill:中英互译,question:你好世界})# 方式二stream流式输出forchunkinchain.stream({role:诗人,skill:写现代诗,question:写一首关于代码的诗}):print(chunk,end,flushTrue)模板 管道符 可复用的提示词流水线。同一个模板换不同的变量就能产出不同的提示词换不同的模型就能得到不同风格的回复——模板和模型各自独立互不耦合。六、实战三个模板三种场景6.1 场景一代码审查助手fromlangchain.promptsimportChatPromptTemplate review_templateChatPromptTemplate.from_messages([(system,你是一位资深代码审查员审查标准如下 - 命名是否规范 - 是否有潜在的性能问题 - 是否有安全隐患 - 是否有更好的写法 请逐条给出审查意见。),(human,请审查以下{language}代码\n{language}\n{code}\n),])messagesreview_template.format_messages(languagepython,code def f(x): return x*2 )6.2 场景二多语言翻译器带 FewShotfromlangchain.promptsimportFewShotPromptTemplate,PromptTemplate examples[{source:今天天气真好,target:The weather is really nice today},{source:我昨天加班到凌晨,target:I worked overtime until midnight yesterday},]example_templatePromptTemplate.from_template(中文{source}\n英文{target})translate_templateFewShotPromptTemplate(examplesexamples,example_promptexample_template,prefix请将以下中文翻译成地道的美式英语,suffix中文{text}\n英文,input_variables[text],)6.3 场景三带历史记忆的客服机器人fromlangchain.promptsimportChatPromptTemplate,MessagesPlaceholder service_templateChatPromptTemplate.from_messages([(system,你是{company}的客服专员。 回复要求 - 语气亲切、专业 - 不能承诺任何你无法确定的事情 - 遇到投诉先道歉再解决),MessagesPlaceholder(variable_namehistory),(human,{question}),])# 模拟历史history[(human,我的订单什么时候到),(ai,您的订单 #12345 预计明天下午送达请注意查收短信通知。),]messagesservice_template.format_messages(company京东,historyhistory,question能帮我催一下吗)七、总结模板类型适用场景核心能力PromptTemplate纯文本提示词变量填充、部分填充ChatPromptTemplate多轮对话角色分离、MessagesPlaceholder 插槽FewShotPromptTemplate需要示例引导固定示例 动态示例选择MessagesPlaceholder插入历史消息为 Memory 组件预留插槽提示词模板的本质是把写提示词从体力活变成工程活。模板让你可以像管理代码一样管理提示词——版本控制、A/B 测试、组件复用——这些在字符串手拼时代想都不敢想的事情现在都是标配。参考资料LangChain Prompts 官方文档LangChain FewShotPromptTemplate 指南
返回列表