【智能体开发】用LangChain组织提示词、模型与结果解析:构建可独立测试的处理流程

发布时间:2026/10/10 9:20:47

【智能体开发】用LangChain组织提示词、模型与结果解析:构建可独立测试的处理流程 用LangChain组织提示词、模型与结果解析构建可独立测试的处理流程一、你遇到的问题假设你在做一个“课程反馈分析”功能用户提交一段课程评价文本系统需要从中提取出评分1-5分、情感倾向和关键点列表并交给下游的报表模块使用。最直接的做法是写一个函数拼好提示词调用模型拿到字符串再用正则或json.loads解析。这个做法在第一次跑通时没问题但接下来你会遇到一连串麻烦模型输出的 JSON 偶尔多一个逗号json.loads直接抛异常整个流程断掉想换一个模型做对比测试发现提示词里硬编码了某个模型的特殊格式想单独测试“解析逻辑是否正确”却发现它和模型调用绑死在同一个函数里不连真实 API 就测不了同事想复用你的提示词模板你只能把一大段字符串复制过去。这些问题的根源是提示词、模型调用、结果解析被揉成了一团。LangChain 提供的ChatPromptTemplate、模型接口和输出解析器本质上是把这三者拆成可独立替换、可独立测试的组件。本文要做的就是把它们组合成一条清晰的链并给出能实际验证的测试方法。完成后你将得到一个可复现的 Python 程序一份带三类验收场景的测试表以及一套判断“解析是否正确”的明确标准。二、前置条件与适用环境适用环境Python 3.10LangChain 生态的 Python 包。操作系统不限Windows/macOS/Linux 均可命令以 Bash 风格给出Windows 用户可在 Git Bash 或 WSL 中执行。你需要具备的入门知识Python 基础语法、pip安装依赖、环境变量设置。不需要 LangChain 经验本文会解释用到的每个核心概念。你需要准备的一个模型服务的 API Key本文以 OpenAI 兼容接口为例其他提供商的接入方式在代码中留有替换位置一个隔离的目录不要在已有项目中直接运行约 15 分钟。本文使用的模型与接口选择LangChain 的init_chat_model支持统一方式接入多个提供商。本文选择openai作为示例提供商因为它的接口最通用。如果你使用 Ollama 本地模型或 DeepSeek 等只需修改模型标识链的其余部分不变。这一点会在代码中说明。三、为什么要把三件事拆开一条 LangChain 链的骨架是这样的prompt | model | parser这三个组件各自承担明确职责提示词PromptTemplate / ChatPromptTemplate负责把输入变量渲染成模型能理解的格式。ChatPromptTemplate支持系统消息、用户消息、AI 消息的多角色结构比单字符串的PromptTemplate更适合需要约束模型行为的场景。模型ChatModel负责接收消息列表并返回模型输出。LangChain 的模型接口是统一的无论底层是 OpenAI、Anthropic 还是本地 Ollamainvoke的调用方式一致。输出解析器OutputParser负责把模型返回的字符串或消息对象转成结构化数据。PydanticOutputParser允许你用一个 Pydantic 模型描述期望的输出结构并自动生成“格式指令”注入提示词引导模型按 schema 输出。拆开之后你可以单独测试解析器给它一段固定的 JSON 字符串看它是否正确转成 Pydantic 对象也可以单独测试提示词给它变量看渲染出的消息列表是否符合预期。模型调用成为唯一需要真实网络的部分其余逻辑都可以在离线状态下验证。需要说明的是LangChain 较新版本推荐用with_structured_output配合 Pydantic 模型来获取结构化输出这种方式在支持工具调用的模型上更可靠。本文选择“提示词注入格式指令 PydanticOutputParser”的经典路线原因是它在不支持工具调用的模型上同样可用且解析逻辑完全独立于模型便于做离线测试。两种方式并不互斥你可以根据模型能力选择。四、完整实现文件清单文件用途config.py从环境变量读取模型标识和 API 配置schemas.py定义输出数据的 Pydantic 模型parser_test.py用固定测试数据验证解析器main.py组装链并运行完整流程.env可选存放 API Key不提交到版本控制4.1 定义输出 schema# schemas.pyfromtypingimportLiteralfrompydanticimportBaseModel,FieldclassCourseFeedback(BaseModel):从课程评价文本中提取的结构化反馈。rating:intField(description课程评分1到5的整数)sentiment:Literal[positive,neutral,negative]Field(description情感倾向)key_points:list[str]Field(description评价中提到的关键点每个点用1到3个词概括)Literal类型约束了情感倾向只能取三个值。Field的description会被PydanticOutputParser写进格式指令告诉模型每个字段的含义。4.2 构建提示词模板# prompts.pyfromlangchain_core.promptsimportChatPromptTemplate SYSTEM_TEMPLATE你是一个课程反馈分析助手。 从用户提供的课程评价中提取评分、情感倾向和关键点。 严格按照提供的JSON格式输出不要添加任何额外说明。HUMAN_TEMPLATE课程评价如下 {feedback_text} {format_instructions}defbuild_prompt(format_instructions:str)-ChatPromptTemplate:returnChatPromptTemplate.from_messages([(system,SYSTEM_TEMPLATE),(human,HUMAN_TEMPLATE),]).partial(format_instructionsformat_instructions)这里有两个关键选择。第一用ChatPromptTemplate而不是PromptTemplate因为系统消息可以对模型行为形成更稳定的约束。第二用.partial()把格式指令预填进去这样调用链时只需要传feedback_text一个变量。格式指令来自解析器不是手写的。4.3 组装链# main.pyimportosfromlangchain.chat_modelsimportinit_chat_modelfromlangchain_core.output_parsersimportPydanticOutputParserfromschemasimportCourseFeedbackfrompromptsimportbuild_promptdefbuild_chain(model_id:str):parserPydanticOutputParser(pydantic_objectCourseFeedback)promptbuild_prompt(parser.get_format_instructions())modelinit_chat_model(modelmodel_id,temperature0)returnprompt|model|parserparser.get_format_instructions()返回一段文本描述了模型应该输出的 JSON 结构。temperature0让输出尽可能稳定减少格式波动。init_chat_model会根据模型标识自动推断提供商。如果你用 OpenAI模型标识类似gpt-4o-mini如果用 DeepSeek标识以deepseek开头会被推断为 DeepSeek 提供商如果用 Ollama需要显式指定model_providerollama。4.4 环境配置# 在隔离目录中执行python-mvenv venvsourcevenv/bin/activate# Windows: venv\Scripts\activatepipinstalllangchain langchain-openai pydantic python-dotenv# 设置 API Key不要写入代码文件exportOPENAI_API_KEY你的keyinit_chat_model会自动读取OPENAI_API_KEY环境变量。如果你用其他提供商对应的环境变量名不同例如 DeepSeek 可能需要DEEPSEEK_API_KEY查阅该提供商的 LangChain 集成文档确认。五、如何验证解析是否正确解析器是整个流程里最需要独立测试的部分。模型输出不可控但解析逻辑是确定性的给同样的字符串必须得到同样的结果。5.1 解析器独立测试# parser_test.pyfromlangchain_core.output_parsersimportPydanticOutputParserfromlangchain_core.exceptionsimportOutputParserExceptionfromschemasimportCourseFeedbackdeftest_parser_normal():parserPydanticOutputParser(pydantic_objectCourseFeedback)raw{rating: 5, sentiment: positive, key_points: [内容扎实, 节奏好]}resultparser.parse(raw)assertisinstance(result,CourseFeedback)assertresult.rating5assertresult.key_points[内容扎实,节奏好]print(正常场景通过)deftest_parser_invalid_rating():parserPydanticOutputParser(pydantic_objectCourseFeedback)raw{rating: 9, sentiment: positive, key_points: [还行]}try:parser.parse(raw)print(边界场景失败评分9不应通过)exceptException:print(边界场景通过超出范围的评分被拒绝)deftest_parser_missing_field():parserPydanticOutputParser(pydantic_objectCourseFeedback)raw{rating: 4, key_points: [不错]}try:parser.parse(raw)print(失败场景失败缺少sentiment字段不应通过)exceptException:print(失败场景通过缺失字段被拒绝)if__name____main__:test_parser_normal()test_parser_invalid_rating()test_parser_missing_field()运行方式python parser_test.py预期输出正常场景通过 边界场景通过超出范围的评分被拒绝 失败场景通过缺失字段被拒绝关于边界场景的一个技术说明Pydantic 默认不会拒绝超出范围的整数除非你在Field中加了约束。上面的test_parser_invalid_rating实际上会失败评分 9 会被接受除非把schemas.py中的rating字段改为rating:intField(description课程评分1到5的整数,ge1,le5)ge和le是 Pydantic 的数值约束加上后评分超出 1-5 范围会抛出验证错误。这个细节恰恰说明了独立测试解析器的价值如果你不单独测就不会发现 schema 缺少约束。5.2 完整链的验收场景下表给出三类验收场景。正常场景需要真实 API Key边界场景和失败场景可以在不调用模型的情况下通过直接测试解析器来验证。场景类型测试目的输入预期结果判定方法正常验证完整链能产出结构化对象一段包含明确评分和情感的评价返回CourseFeedback实例字段齐全isinstance(result, CourseFeedback)为 True边界验证评分约束是否生效JSON 中rating为 0 或 6抛出验证异常捕获ValidationError或OutputParserException失败验证缺失字段是否被拒绝JSON 中缺少sentiment抛出验证异常捕获ValidationError或OutputParserException对于正常场景完整链的调用方式frommainimportbuild_chainimportos chainbuild_chain(gpt-4o-mini)resultchain.invoke({feedback_text:这门课讲得很清楚节奏也舒服就是作业稍微多了点。给4分吧。})print(type(result))# class schemas.CourseFeedbackprint(result.rating)# 4print(result.sentiment)# positiveprint(result.key_points)# 关键点列表具体措辞因模型而异模型输出不要求逐字匹配。key_points的内容因模型而异验收标准是字段存在、类型正确、评分在合理范围、关键点非空。不要用固定字符串做断言。5.3 常见故障定位故障一OutputParserException提示“Failed to parse”。原因通常是模型在 JSON 前后加了说明文字或者输出了不完整的 JSON。定位方法先绕过解析器直接打印模型原始输出fromlangchain_core.runnablesimportRunnableLambdafrommainimportbuild_chain chainbuild_chain(gpt-4o-mini)raw_chainchain[:-1]|RunnableLambda(lambdamsg:msg.content)rawraw_chain.invoke({feedback_text:...})print(repr(raw))看到原始输出后就知道是格式问题还是 schema 问题。格式问题可以尝试用OutputFixingParser包装原解析器让模型自动修复schema 问题则需要调整提示词或字段描述。故障二init_chat_model报“model_provider not found”。原因是你用的模型标识没有对应的集成包。解决安装对应包如langchain-deepseek或显式传model_provider参数。故障三评分约束不生效。如 5.1 所述Pydantic 默认不做范围检查。确认schemas.py中rating字段是否带有ge1, le5。六、适用边界与未覆盖的部分本文的链是同步、单轮、无状态的。以下情况不在本文范围内需要额外设计多轮对话需要维护消息历史ChatPromptTemplate的MessagesPlaceholder可以承接历史消息流式输出PydanticOutputParser是聚合式解析不支持流式。如果需要流式考虑使用with_structured_output配合支持流式的模型解析失败自动重试可以用RetryWithErrorOutputParser它会带着原始指令和错误信息让模型重新输出生产级并发与限流需要额外的调度和错误恢复逻辑。本文选择的最小闭环是让读者掌握“提示词—模型—解析器”三段式结构的搭建方法并用离线测试验证解析逻辑的确定性。把模型调用隔离在最小范围内是整个设计最核心的工程决策。验证状态已完成的核验解析器的独立测试代码逻辑经静态检查测试用例覆盖正常、边界、失败三类场景提示词构建和链的组装方式对照了 LangChain 官方文档中ChatPromptTemplate、PydanticOutputParser和init_chat_model的用法说明Pydantic 字段约束的说明基于 Pydantic 的标准行为ge/le参数用于数值范围限制。未实际执行的验证完整链调用真实模型的部分未执行因为本文写作环境没有可用的 API Key。正常场景的预期输出是基于 LangChain 文档中类似示例的推断不是实测结果不同提供商DeepSeek、Ollama 等的init_chat_model兼容性未逐一验证。如果你使用非 OpenAI 提供商建议先用parser_test.py确认解析逻辑再接入模型。参考资料LangChain 官方文档Prompt Templates 快速参考核验日期2026-10-09LangChain 官方文档Custom Output Parsers核验日期2026-10-09LangChain 官方文档Output Parsers 类型表v0.1核验日期2026-10-09LangChain API 文档init_chat_model核验日期2026-10-09KodeKloud 教程Pydantic Output Parser 完整示例核验日期2026-10-09
延伸阅读

更多相关文章

2026/10/10 9:20:47

代码报错、公式卡壳、同辈碾压?计算机人内耗自救指南

深夜十一点半,实验室只剩我一个人。屏幕上的 VS Code 开着,红波浪线密密麻麻,编译器报错跳到第 37 行,我改了一次、两次、三次,还是同样的结果。隔壁工位那个早早就跑通实验的同学,朋友圈刚晒完晚饭&#x…

2026/10/10 9:20:47

48元批发一个“医生“之后:AI广告合规的责任链断点与修复路径

【摘要】央视调查显示,周费48元即可批量生成AI医生带货视频,北京首例AI虚拟人虚假宣传案罚款仅5000元。全文结合5起公开处罚案例、7部现行规则与1项强制性国标,拆解AI广告生成、发布、监管全链路的3处责任断点,给出可落地的修复路…

2026/10/10 10:31:16

SocketTool网络调试工具:TCP/UDP模式选型与高频踩坑避坑指南

简介:这是一套面向C#网络编程开发者的Socket调试工具,压缩包内含完整C#源代码,覆盖服务端与客户端建立连接、监听端口、收发数据及异常处理等环节,适合学习网络通信原理或进行联调测验。包内共610个文件、3.71MB,以C#源…

2026/10/10 10:31:16

Python socket网络编程实践:从TCP通信链路到训练避坑指南

简介:这份练习答案适用于国家开放大学(原中央广播电视大学)网络编程技术课程实践技能训练1,针对简易购物车页面设计与实现给出完整前端工程包。整个作品围绕HTML、CSS与JavaScript三项核心技能展开,HTML负责商品列表、…

2026/10/10 10:31:16

Freaky Font 个性字体实战指南:选型、排版与避坑技巧

1. 项目概述:Freaky Font 能做什么字体这东西,很多人觉得不就是打字的工具吗?选来选去无非宋体、黑体、微软雅黑。但实际上一款“不正常”的字体,能直接改变读者对内容的感知。Freaky Font 表面上说的是那些夸张、变形、带手绘感的…

2026/10/10 10:31:16

Windows跨盘合并分区实操:跨区卷与第三方无损合并详解

我手上遇到过不少类似的需求:有人想给剪辑工作站挂一块大仓库盘,有人想把老机械盘和新固态合在一起用,还有人纯粹是嫌电脑里分区太乱、盘符太多,看着就烦。前阵子帮一个开工作室的朋友处理剪辑素材存储,他有两块硬盘&a…

2026/10/10 10:31:16

运动粘度仪原理与选型指南:从恒温控制到全自动低温测试方案

1. 运动粘度仪是什么:同一套技术体系的三个侧面说起运动粘度仪,刚接触的朋友很容易被一串名字绕晕——运动粘度仪、全自动运动粘度测定仪、自动低温乌氏粘度测定仪,听着像三台完全不同的设备,其实它们是同一套技术体系在不同需求下…

2026/10/10 10:26:15

电脑硬件真实性能诊断的5种专业方法

1. 为什么“看配置”这件事,90%的人从第一步就错了很多人一打开电脑就想立刻知道“这台机器到底行不行”,结果点开“此电脑”右键属性,看到“Intel Core i5-8250U,8GB内存”就以为搞定了。我带过不少刚入门的学员,他们…

2026/10/10 7:31:36

Jev+Agent接管浏览器:browser-use实战与jev-ultrafast性能优化

1. 从“Jev”说起:为什么我要把Agent接进浏览器“Jev”这个词最近在圈子里出现的频率越来越高,很多人第一次听到会以为是某个新模型的名字,其实它更像是一种思路——把Jev模型的能力当作底座,通过Agent的方式去接管浏览器&#xf…

2026/10/9 20:15:56

多智能体集群实战:DeepAgents编排、MCP与A2A协议及Skills体系

1. 从"单兵作战"到"集群协同":多智能体编排到底在解决什么问题如果你最近在折腾 Agent 相关的东西,大概率会有一种感觉:单个 Agent 能做的事情,其实很快就摸到天花板了。你给它一个提示词,挂几个工…

2026/10/8 6:05:44

无源低通滤波器设计实战:从RC到LC,手把手教你避开那些坑

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/10 0:04:53

从逻辑门到计算机:数字电路核心原理与全加器搭建实战

如果你拆过一台旧电脑的主板,盯着那些黑乎乎的小芯片看上一会儿,可能会冒出同一个疑问:这堆引脚密集的元件,到底是怎么“变”出那么复杂的应用的?答案并不在某个神秘的部件里,而是在所有芯片内部都在反复使…

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

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

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