LangChain入门:Prompt模板与结构化输出详解

发布时间:2026/9/10 11:42:00

LangChain入门:Prompt模板与结构化输出详解 从手写提示词到结构化数据一文搞定LangChain核心输出解析 引言在开发大模型应用时我们常常面临两个核心问题如何高效地组织和管理提示词Prompt—— 避免代码中到处拼接字符串如何让模型返回程序可直接使用的结构化数据—— 而不是自然语言段落LangChain 提供了完善的解决方案PromptTemplate系列管理输入OutputParser系列处理输出。本文将带你从零开始掌握这两大模块并完成多个实战案例。一、Prompt 基础与模板1.1 什么是 PromptPrompt就是给模型的指令。简单示例python请用中文介绍一下LangChain。但在实际项目中Prompt 往往包含角色设定、任务描述、输入数据和约束条件python system 你是一名资深技术顾问擅长用通俗语言解释复杂概念。 human 请向非技术人员介绍LangChain字数控制在200字以内。如果每次都在代码中拼接会产生大量重复和易错代码。Prompt 模板将固定部分与变量分离提高复用性和可维护性。1.2 PromptTemplate纯文本模板适用于不需要区分系统/用户角色的简单文本任务。python from langchain_core.prompts import PromptTemplate template PromptTemplate.from_template( 请为产品{product_name}写一句广告语突出{feature}。 ) prompt template.invoke({product_name: 智能手环, feature: 超长续航}) print(prompt) # 输出请为产品智能手环写一句广告语突出超长续航。1.3 ChatPromptTemplate聊天消息模板推荐使用因为它可以构建结构化的消息列表SystemMessage / HumanMessage / AIMessage更符合现代对话模型的输入习惯。python from langchain_core.prompts import ChatPromptTemplate chat_template ChatPromptTemplate.from_messages([ (system, 你是一位{role}回答要简洁专业。), (human, {question}) ]) prompt_value chat_template.invoke({ role: AI产品经理, question: 什么是RAG }) # 内部会生成 [SystemMessage, HumanMessage]模板类型输出形式适用场景PromptTemplate纯字符串简单文本生成无角色区分ChatPromptTemplate消息列表聊天、Agent、多轮对话二、Prompt 编写最佳实践掌握以下四个原则就能写出高质量的 Prompt明确角色—— 让模型以特定身份思考明确任务—— 说清楚要做什么明确约束—— 限制输出格式、字数、风格给出输入字段—— 让模型清楚每个变量的含义三、实战案例Prompt 篇案例1商品文案生成器根据商品信息自动生成电商文案。代码01_product_copywriter.pypython from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model get_deepSeek_model() template ChatPromptTemplate.from_messages([ (system, 你是一名资深电商文案写手擅长用吸引人的语言描述产品。), (human, 请为以下商品撰写一段电商文案150字以内包含标题和卖点。 商品名称{name} 核心卖点{feature} 适用人群{target} ) ]) prompt template.invoke({ name: 智能保温杯, feature: 24小时保温智能测温健康提醒, target: 注重健康的办公族 }) response model.invoke(prompt) print(response.content)案例2学习计划生成器根据学习目标生成分阶段计划。代码02_study_plan.pypython from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model get_deepSeek_model() template ChatPromptTemplate.from_messages([ (system, 你是一位资深学习规划师。), (human, 为以下学习目标制定一份为期{days}天的学习计划。 目标{goal} 当前水平{level} 每日可用时间{hours}小时 请按阶段列出每日任务并给出学习建议。 ) ]) prompt template.invoke({ goal: 从零开始学习Python数据分析, days: 30, level: 零基础, hours: 2 }) response model.invoke(prompt) print(response.content)案例3客服回复生成器模拟根据用户问题和订单信息生成回复。代码03_customer_reply.pypython from langchain_core.prompts import ChatPromptTemplate from utils.model_factory import get_deepSeek_model model get_deepSeek_model() template ChatPromptTemplate.from_messages([ (system, 你是一名专业客服回复要礼貌且解决问题。), (human, 用户问题{question} 订单状态{status} 物流信息{logistics} 请生成一段客服回复给出明确解决方案。 ) ]) prompt template.invoke({ question: 我的快递显示签收但我没收到, status: 已签收, logistics: 2025-01-15 10:00 已由门卫代收 }) response model.invoke(prompt) print(response.content)四、MessagesPlaceholder插入多轮对话历史在构建聊天应用时经常需要将历史消息插入到模板中。MessagesPlaceholder专门用于此。python from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder prompt ChatPromptTemplate.from_messages([ (system, 你是一个乐于助人的AI助手。), MessagesPlaceholder(history, optionalTrue, n_messages4), # 最多保留4条 (human, {question}) ]) history [ (human, 我叫小明), (ai, 你好小明有什么可以帮你), (human, 我喜欢Python), (ai, Python是很好的语言) ] prompt_value prompt.invoke({ history: history, question: 我刚才说了什么 }) # 实际只会插入最近4条历史消息如果超过参数说明variable_name输入变量名optional是否必须传入默认Falsen_messages最多保留最近几条消息五、结构化输出让程序读懂模型结果模型返回的自然语言虽然易读但程序难以直接处理。我们需要让模型输出JSON或其他结构化格式。5.1 StrOutputParser简单的字符串提取如果只想要纯文本内容StrOutputParser可以将AIMessage转为普通字符串并支持管道组合。python from langchain_core.output_parsers import StrOutputParser from langchain_core.prompts import ChatPromptTemplate model get_deepSeek_model() parser StrOutputParser() chain ChatPromptTemplate.from_template(翻译成中文{text}) | model | parser result chain.invoke({text: LangChain is awesome!}) print(result) # 直接打印字符串为什么不用response.content在管道|中每个组件必须是Runnable而.content是属性不是 Runnable。StrOutputParser正是为了合规接入管道。5.2 Pydantic 定义输出结构使用Pydantic声明期望的字段及类型让模型按此格式返回。python from pydantic import BaseModel, Field from typing import Literal class ResumeInfo(BaseModel): name: str Field(description候选人姓名) years_of_experience: int Field(description工作年限) skills: list[str] Field(description掌握的技术技能) target_position: str Field(description目标岗位)5.3 PydanticOutputParser手动解析该解析器会根据 Pydantic 模型生成格式说明get_format_instructions()并嵌入 Prompt最后将模型输出解析成对象。案例简历信息抽取 (02_resume_extractor.py)python from langchain_core.output_parsers import PydanticOutputParser from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model model get_deepSeek_model() class ResumeInfo(BaseModel): name: str Field(description姓名) years_of_experience: int Field(description工作年限) skills: list[str] Field(description掌握的技术技能) target_position: str Field(description目标岗位) parser PydanticOutputParser(pydantic_objectResumeInfo) format_instructions parser.get_format_instructions() template ChatPromptTemplate.from_messages([ (system, 你是一名招聘分析助手。\n{format_instructions}), (human, {resume_content}) ]) resume_text 我叫张三工作10年擅长Python、LangChain、FastAPI想找智能体开发岗位。 prompt template.invoke({ format_instructions: format_instructions, resume_content: resume_text }) response model.invoke(prompt) result parser.invoke(response) print(result.name) # 张三 print(result.years_of_experience) # 10 print(result.skills) # [Python, LangChain, FastAPI] print(result.target_position) # 智能体开发5.4 with_structured_output更简洁的方式如果模型服务支持如 OpenAI、DeepSeek 的 JSON 模式可以直接在模型上绑定输出结构。python structured_model model.with_structured_output(ResumeInfo, methodjson_mode) result structured_model.invoke(从简历中提取信息...) # 返回的 result 就是 ResumeInfo 实例注意使用 DeepSeek 时需指定methodjson_mode否则会报错。案例商品评论分析 (03_review_analyzer.py)python from typing import Literal from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model class ReviewAnalysis(BaseModel): sentiment: Literal[正面, 负面, 中性] Field(description情感倾向) keywords: list[str] Field(description关键词) summary: str Field(description评论总结) needs_reply: bool Field(description是否需要商家回复) model get_deepSeek_model() structured_model model.with_structured_output(ReviewAnalysis, methodjson_mode) template ChatPromptTemplate.from_messages([ (system, 你是评论分析专家严格按JSON格式输出。), (human, 分析评论{review}) ]) prompt template.invoke({ review: 鼠标手感不错也很安静但是用了两周滚轮就有异响。 }) result structured_model.invoke(prompt) print(result.sentiment) # 负面 print(result.keywords) # [手感, 安静, 滚轮异响] print(result.summary) # 用户认可手感但反映滚轮质量问题 print(result.needs_reply)# True案例工单分类 (04_ticket_classifier.py)python from typing import Literal from langchain_core.output_parsers import PydanticOutputParser from langchain_core.prompts import ChatPromptTemplate from pydantic import BaseModel, Field from utils.model_factory import get_deepSeek_model class TicketResult(BaseModel): category: Literal[订单, 物流, 退款, 产品, 其他] Field(description工单分类) priority: Literal[低, 中, 高] Field(description优先级) reason: str Field(description分类原因) parser PydanticOutputParser(pydantic_objectTicketResult) format_instructions parser.get_format_instructions() template ChatPromptTemplate.from_messages([ (system, 客服工单分类助手。\n{format_instructions}), (human, {question}) ]) prompt template.invoke({ format_instructions: format_instructions, question: 订单显示已签收但我没收到商品请处理。 }) response model.invoke(prompt) result parser.invoke(response) print(result.category) # 物流 print(result.priority) # 高 if result.priority 高: print(立即转人工)六、处理解析错误模型输出不稳定时可能返回不符合结构的内容。应捕获OutputParserException或通用异常。python from langchain_core.exceptions import OutputParserException try: result parser.parse(response.content) except OutputParserException as e: print(解析失败原始输出, response.content) print(错误信息, e) # 可进行重试、日志记录或人工干预七、结构化方式对比方式优点缺点适用场景StrOutputParser简单、管道兼容仅返回字符串摘要、翻译、问答PydanticOutputParser清晰、可自定义需手动拼接格式说明需要精细控制解析过程with_structured_output代码简洁依赖模型服务支持现代大模型OpenAI/DeepSeek等建议先掌握PydanticOutputParser理解原理实际项目优先使用with_structured_output。八、工具函数封装减少重复代码为了让案例更干净我们将模型初始化抽到utils/model_factory.pypython # utils/model_factory.py from langchain_openai import ChatOpenAI import os def get_deepSeek_model(temperature0): return ChatOpenAI( modeldeepseek-chat, api_keyos.getenv(DEEPSEEK_API_KEY), base_urlhttps://api.deepseek.com/v1, temperaturetemperature )这样每个案例只需导入get_deepSeek_model即可。九、常见问题解答Q1Prompt 越长越好吗不是。应清晰简洁避免过多无关要求否则模型可能顾此失彼。Q2模型为什么不完全按指令输出大模型是概率性生成不能保证100%服从。若输出格式关键需配合结构化输出和程序校验。Q3PromptTemplatevsChatPromptTemplate如果模型支持多角色消息System/Human优先用ChatPromptTemplate本课程所有案例均使用它。Q4为什么temperature0对于信息抽取、分类等确定性任务温度设为0可获得最稳定输出。Q5with_structured_output没看到 JSON 字符串因为 LangChain 内部已将 JSON 自动解析为 Pydantic 对象你拿到的直接就是模型实例。 总结通过本文你学会了使用PromptTemplate/ChatPromptTemplate管理提示词编写高质量 Prompt 的四个原则三个业务案例文案、计划、客服实战MessagesPlaceholder处理聊天历史三种输出解析器StrOutputParser、PydanticOutputParser、with_structured_output结构化输出案例简历抽取、评论分析、工单分类处理解析错误和异常掌握这些技能你就能构建出既易于维护又能与业务系统无缝对接的 LLM 应用。
延伸阅读

更多相关文章

2026/9/10 11:37:44

NLP核心任务与工业实践:从基础到高阶应用

1. 自然语言处理的核心任务全景自然语言处理(NLP)作为AI领域最具挑战性的分支之一,其核心任务体系已经形成了清晰的脉络。在我过去五年的工业界实践中,这些任务从基础到高阶大致可以分为三类:文本理解、文本生成和跨模…

2026/9/9 20:21:12

3步掌握开源清理工具:让你的显卡驱动重获新生

3步掌握开源清理工具:让你的显卡驱动重获新生 【免费下载链接】display-drivers-uninstaller Display Driver Uninstaller (DDU) a driver removal utility / cleaner utility 项目地址: https://gitcode.com/gh_mirrors/di/display-drivers-uninstaller 显卡…

2026/9/8 18:39:08

3分钟免费解锁Wand专业版:终极游戏修改增强指南

3分钟免费解锁Wand专业版:终极游戏修改增强指南 【免费下载链接】Wand-Enhancer Advanced UX and interoperability extension for Wand (WeMod) app 项目地址: https://gitcode.com/GitHub_Trending/we/Wand-Enhancer 还在为Wand(原WeMod&#x…

2026/9/10 11:37:29

C++数据库连接池设计与性能优化实践

1. 为什么需要数据库连接池? 在C后端开发中,数据库操作是系统性能的关键瓶颈之一。每次建立数据库连接都需要完成TCP三次握手、认证、权限检查等系列操作,实测MySQL创建单个连接的平均耗时在50-200ms之间。在高并发场景下,频繁创建…

2026/9/10 11:37:29

Android打包流程详解:从编译到签名优化

1. Android打包流程概述作为一名Android开发者,每天都要经历数十次打包过程。但你真的了解这个看似简单的操作背后发生了什么吗?从点击"Build"按钮到生成最终的APK/AAB文件,Android Studio完成了一系列复杂的编译、转换和优化工作。…

2026/9/10 11:37:29

mpv 配置指南:4 步诊断法搞定卡顿、字幕与低功耗播放

mpv 配置指南:4 步诊断法搞定卡顿、字幕与低功耗播放 【免费下载链接】mpv 🎥 Command line media player 项目地址: https://gitcode.com/GitHub_Trending/mp/mpv mpv 配置讲究"先诊断后开方":多数翻车不是因为参数抄得不对…

2026/9/9 13:11:35

超人会飞不算本事:系统稳定依赖清晰规则与边界设计

开头先不绕弯子。“#斯坦李吐槽dc 所以超人是无缘无故会飞的嘛哈哈哈哈哈哈哈锤哥真是技术人才啊!#雷神 #复联”这类调侃式短标题,第一波冲击力在于它把两个宇宙的角色塞进同一个吐槽箱里,但细想一下就能发现,它真正碰到的根本不是…

2026/9/10 11:16:38

超人VS蜘蛛侠:拆解超级IP的影响力与传播方法论

把“蜘蛛侠 vs 超人”放在 CSDN 上聊,可能很多人第一反应是走错片场了。但如果把这两个角色看成“两个持续运营了 80 多年的文化产品”,你会发现,这场比较本质上是两个不同 IP 策略的长期结果对比:超人赢在定义了整个超级英雄题材…

2026/9/9 16:31:09

基于CNN的调制信号识别:MATLAB实现时频图分类实战

简介:本资源是一套面向通信工程与信号处理方向学习者、研究者的深度学习实践方案,聚焦调制信号自动检测与识别这一典型无线通信任务,解决传统方法依赖人工特征、低信噪比下性能下降等痛点。压缩包共12个文件(10.73MB)&…

2026/9/10 0:00:55

目录对比去重实战:用哈希算法精准清理重复文件

我电脑里现在还有一块换了三次机的“数据墓地”硬盘,里面存着2016年以前所有旧笔记本的完整备份。平时不觉得有什么,直到前阵子想把它整理归档,发现同一个安装包、同一批照片、同一份论文草稿,在几个不同的备份目录里反复出现。更…

2026/9/10 0:00:55

Leaflet离线地图完整Demo合集:内网部署与坐标纠偏实战

简介:这是一份面向Web GIS开发者的LeafLet离线地图示例合集,帮助开发者快速掌握离线地图从搭建到交互的完整流程。压缩包共723个文件,大小14.06MB,以319个js脚本、175个html页面和29个css样式文件为主体,配合png/svg图…

2026/9/10 0:00:55

MATLAB读取Rinex 3.02观测文件:多系统GNSS数据解析实战

简介:基于MATLAB开发的Rinex3.02版观测文件(o文件)读取代码包,面向卫星定位导航方向的学习者与研究人员,用于解决新版观测文件的数据解析、历元提取与时间转换问题。压缩包共4个文件,包含两个m脚本、一个19…

2026/9/7 16:23:03

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/7 22:46:00

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/9 10:21:54

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码