当前位置: 首页 > news >正文

《AI大模型应用开发实战从入门到精通共60篇》010、LangChain之Prompt Templates:模板化你的提示词

010、LangChain之Prompt Templates:模板化你的提示词

上周调一个客服对话系统,发现同样的用户问题,模型回答质量忽高忽低。排查了半天,问题出在提示词上——每次拼接用户输入时,格式不一致,有的带标点,有的没上下文,模型根本不知道自己在扮演什么角色。这种“手写提示词”的痛,做过LLM应用的人应该都懂。

为什么需要模板化

先看一个反面教材。假设你要做一个翻译助手,最原始的写法可能是这样:

prompt=f"请将以下英文翻译成中文:{user_input}"

看起来没问题?但当你需要加入角色设定、输出格式、few-shot示例时,代码会迅速膨胀成面条式拼接:

prompt=f"你是一个专业的翻译助手。请将以下英文翻译成中文。要求:1. 保持原意 2. 符合中文表达习惯。\n英文:{user_input}\n中文:"

这里踩过坑:一旦需求变更,比如要支持多语言、要加入历史对话,你就要在所有调用处改字符串拼接逻辑。更可怕的是,不同开发者的拼接风格不同,有人加换行,有人不加,模型行为完全不可控。

LangChain的PromptTemplate

LangChain的PromptTemplate就是来解决这个问题的。它把提示词拆成“固定部分”和“变量部分”,类似模板引擎的思想。

基础用法

fromlangchain.promptsimportPromptTemplate# 别这样写:直接在字符串里写死格式# prompt = f"翻译:{text}"# 正确姿势:定义模板template="请将以下{source_lang}翻译成{target_lang}:\n{text}\n{target_lang}:"prompt_template=PromptTemplate(input_variables=["source_lang","target_lang","text"],template=template)# 使用时传入变量formatted_prompt=prompt_template.format(source_lang="英文",target_lang="中文",text="Hello, world!")print(formatted_prompt)# 输出:# 请将以下英文翻译成中文:# Hello, world!# 中文:

注意这里有个坑:input_variables必须和模板中的变量名完全一致,少一个或多一个都会报错。我刚开始写的时候经常漏掉,后来养成习惯:先写模板字符串,再对照着写变量列表。

带few-shot的模板

实际项目中,我们经常要给模型看几个例子。用PromptTemplate可以优雅地组织:

template="""你是一个{role}。请根据以下示例回答问题。 示例1: 问题:{example1_question} 回答:{example1_answer} 示例2: 问题:{example2_question} 回答:{example2_answer} 现在请回答: 问题:{question} 回答:"""prompt_template=PromptTemplate(input_variables=["role","example1_question","example1_answer","example2_question","example2_answer","question"],template=template)

这里踩过坑:few-shot示例的数量如果太多,模板会变得非常长。建议把示例做成列表,用循环生成,而不是硬编码在模板里。后面会讲到更高级的FewShotPromptTemplate。

ChatPromptTemplate:对话场景专用

如果你用的是Chat模型(比如GPT-4、Claude),普通的PromptTemplate就不够用了。对话模型需要区分System、Human、AI消息。

fromlangchain.promptsimportChatPromptTemplate,HumanMessagePromptTemplate,SystemMessagePromptTemplate# 别这样写:把所有内容塞进一个HumanMessage# messages = [HumanMessage(content=f"你是一个助手。用户说:{user_input}")]# 正确姿势:分角色定义system_template="你是一个{role},擅长{skill}。请用{style}的风格回答。"human_template="{user_input}"chat_prompt=ChatPromptTemplate.from_messages([SystemMessagePromptTemplate.from_template(system_template),HumanMessagePromptTemplate.from_template(human_template)])# 使用时传入变量messages=chat_prompt.format_messages(role="技术顾问",skill="Python编程",style="简洁专业",user_input="如何优化列表推导式?")

这里有个经验:System消息里放角色设定和全局约束,Human消息里放用户输入。AI消息通常由模型生成,不需要模板化。如果你需要给模型看历史对话,可以加入AIMessagePromptTemplate。

模板中的高级技巧

部分变量(Partial Variables)

有时候你有一些固定不变的变量,比如系统版本号、当前日期。每次都传一遍很烦人:

fromdatetimeimportdatetime template="当前时间:{date}\n用户问题:{question}"prompt_template=PromptTemplate(template=template,input_variables=["question"],partial_variables={"date":datetime.now().strftime("%Y-%m-%d")})# 调用时只需要传questionresult=prompt_template.format(question="今天天气怎么样?")

注意:partial_variables里的变量不能出现在input_variables中,否则会冲突。这个坑我踩过两次才记住。

模板验证(Template Validation)

LangChain默认会检查模板中的变量是否都在input_variables里声明了。但如果你用了from_template方法,它会自动解析变量名:

# 自动解析,不需要手动写input_variablesprompt_template=PromptTemplate.from_template("你好,{name}!今天{weather}。")print(prompt_template.input_variables)# ['name', 'weather']

这个特性很方便,但有个隐患:如果你的模板里不小心写了拼写错误的变量名(比如{nmae}),它不会报错,只是当成普通文本。建议写完模板后手动检查一下。

实战:构建一个可复用的问答模板

假设你要做一个技术问答系统,需要支持多轮对话和上下文记忆。这里给出一个我实际项目中的模板设计:

fromlangchain.promptsimportChatPromptTemplate,MessagesPlaceholder# MessagesPlaceholder用于插入历史消息列表chat_prompt=ChatPromptTemplate.from_messages([("system","你是一个{domain}专家。请基于以下知识库回答用户问题:\n{knowledge_base}"),MessagesPlaceholder(variable_name="history"),("human","{input}")])# 使用时fromlangchain.schemaimportHumanMessage,AIMessage messages=chat_prompt.format_messages(domain="嵌入式开发",knowledge_base="STM32F4系列主频168MHz,有1MB Flash...",history=[HumanMessage(content="什么是DMA?"),AIMessage(content="DMA是直接内存访问...")],input="DMA和中断有什么区别?")

这里踩过坑:MessagesPlaceholdervariable_name必须和传入的变量名一致。而且历史消息必须是BaseMessage对象列表,不能是字符串列表。很多新手在这里翻车。

个人经验建议

  1. 模板和逻辑分离:把模板定义放在单独的配置文件或YAML文件里,不要硬编码在Python代码中。这样产品经理改提示词时,不需要动代码。

  2. 版本控制模板:每次修改模板都记录版本号,因为模型对提示词极其敏感,改一个标点都可能影响输出质量。我习惯在模板开头加注释:# v1.2 2024-03-15 增加了输出格式约束

  3. 测试模板边界:写单元测试验证模板在各种输入下的表现。比如空字符串、超长文本、特殊字符。我遇到过用户输入包含{}导致模板解析失败的情况。

  4. 不要过度模板化:如果模板变量超过10个,说明你的提示词设计可能有问题。考虑拆分成多个子模板,或者用更结构化的方式(比如JSON格式)组织信息。

  5. 留意模板长度:模板本身也会消耗token。把固定部分(比如角色设定、few-shot示例)缓存起来,不要每次都重新计算。LangChain的partial_variables可以帮你做这件事。

最后说一句:PromptTemplate看起来简单,但它是整个LLM应用的基石。模板设计得好,模型表现稳定;模板设计得烂,后面所有优化都是白费力气。花时间把模板打磨好,比调什么超参数都管用。

http://www.jsqmd.com/news/695476/

相关文章:

  • Drawboard PDF免费版被砍后,我的7个工具位怎么分配最合理?(附颜色配置方案)
  • LSTM超参数调优实战:时间序列预测指南
  • 词嵌入技术解析:从Word2Vec到Transformer演进
  • 毕业答辩PPT还在熬夜肝?让百考通AI帮你把时间还给思考
  • 德国蔡司三维扫描仪国内授权经销商综合实力排行:德国蔡司三维扫描仪,德国蔡司三维蓝光扫描仪atos-q,排行一览! - 优质品牌商家
  • 终极MCP服务器:模块化架构与AI应用开发实战指南
  • 手把手教你用这5个脚本,榨干甲骨文免费服务器的网速潜力
  • 基于进化计算的多智能体协作框架:从原理到实践
  • 手把手搭建第一个企业级AI Agent:从零配置LangChain环境
  • 算法训练营第十三天|454.四数相加||
  • 8款古籍刻本书法字体分享,让你的新中式设计更有书卷气
  • LangChain框架解析:从RAG到智能代理的AI应用构建实战
  • Win10中文用户名导致Anaconda安装失败?保姆级修复与配置全流程(含软链接创建)
  • AI 应用安全加固:Scenario 自动化红队测试开源方案
  • 2026年q2不锈钢焊接加工厂:不锈钢折弯加工厂,不锈钢柜体加工厂,不锈钢橱柜定制加工,优选指南! - 优质品牌商家
  • 从QPushButton到QAction:一文掌握Qt中‘可切换’控件的完整使用手册(setCheckable/setChecked详解)
  • 从振荡波形到Python脚本:一次完整的运放偏置电流测量与数据分析实战
  • 轻量级容器Microverse:边缘计算与嵌入式AI的极简部署方案
  • 告别配置噩梦:用Vcpkg一键安装OpenCV 4.4.0到VS2019 C++项目
  • CSS如何处理CSS颜色模式不兼容_通过fallback定义标准颜色值
  • 基本类型和引用类型的比较
  • 从Xilinx Zynq迁移到复旦微FMQL:手把手教你搞定PS端千兆网口(含设备树避坑指南)
  • 加码 AI 安全研发:微软引入 Anthropic Claude Mythos 模型强化代码风控
  • 面试鸭全栈项目实战:React+Node.js+MongoDB构建面试刷题平台
  • Mac Mouse Fix终极指南:让普通鼠标在macOS上焕发新生
  • 电商图的提示词模板,拿去直接用
  • mysql如何安全地删除数据库账号_使用DROP USER命令清理
  • 【Matlab代码】基于元模型优化算法的主从博弈多虚拟电厂动态定价和能量管理
  • 【案例】江苏大摩半导体 × 无锡哲讯智能|SAP全链路数字化管理,赋能半导体设备企业国产化高质量发展
  • 如何在英国生物银行研究平台上快速完成基因组数据分析:5个高效秘诀