尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

LangChain 从入门到实战(03):别再用字符串拼提示词——多消息、few-shot 与结构化输出

LangChain 从入门到实战(03):别再用字符串拼提示词——多消息、few-shot 与结构化输出 LangChain 从入门到实战03别再用字符串拼提示词——多消息、few-shot 与结构化输出上一篇我们用三个最小件跑通了第一次真实调用也埋了根线from_template生成的是单条用户消息。这一篇把这根线拆开——ChatPromptTemplate真正能上生产的三种写法多角色消息system/human、few-shot 少样本示例、绑定结构化输出JSON。让提示词从「一段写死的字符串」变成「一个可被管理、复用、进生产的组件」。老规矩本篇代码都能直接跑并附在每段后的「跑起来你会看到」。一、单条消息的局限你需要「系统」这个角色上一篇的from_template只能生成一条用户消息。但真实生产里一段合格的提示词往往是「先立规矩 再提问」system 消息设定模型的身份、语气、边界「你是资深 Java 后端架构师只回答与代码相关的问题」human 消息用户真正的问题。from_messages就是干这个的它能按顺序放多个角色fromlangchain_core.promptsimportChatPromptTemplate ckptChatPromptTemplate.from_messages([(system,你是资深{role}工程师。回答要精炼不超过3条。),(human,{question}),])chain(ckpt|llm|parser)# llm、parser 沿用第02篇print(chain.invoke({role:Java 后端,question:Transactional 失效的三种场景}))跑起来你会看到先有身份设定再答方向不会跑偏。把「立规矩的 system」和「用户输入 human」分开管是生产提示词的第一条分水岭。二、few-shot给模型「照着写」的范本有时光靠 system 描述一件事不够模型还是不知道你要的格式。最有效的办法是给几个「输入 → 正确输出」的样例让模型照着写——few-shot少样本示例。fromlangchain_core.promptsimportFewShotChatMessagePromptTemplate,ChatPromptTemplate examples[{question:11 等于几,answer:2},{question:2*3 等于几,answer:6},]fewFewShotChatMessagePromptTemplate(example_promptChatPromptTemplate.from_messages([(human,{question}),(ai,{answer}),]),examplesexamples,)finalChatPromptTemplate.from_messages([(system,你是一个只回数字的算术助手。),few,(human,{question}),])resultfinal.invoke({question:4*5 等于几})print(result)跑起来你会看到最后一条 human 是用户提问前面带着两组示例做「锚定」。few-shot 的价值是「用节奏带动模型对齐格式」它比千言万语更管用——模型直接抄格式几乎没有发挥空间。三、结构化输出让链直接吐出 JSON不进生产的关键一步前面两步都是「输入侧」。要到生产输出侧必须结构化。用JsonOutputParser模型就直接返回一个合规 JSONfromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportJsonOutputParser parser_jsonJsonOutputParser()promptChatPromptTemplate.from_messages([(system,你是货币换算助手。),(human,把金额 {amount} usd 转成人民币四舍五入到元。\n{format_instructions}),])# 把 JSON 格式约束注入成模板变量 {format_instructions}promptprompt.partial(format_instructionsparser_json.get_format_instructions())chainprompt|llm|parser_json resultchain.invoke({amount:12.5})print(result)# 直接就是 dict例{amount_cny: 90}这里的两个关键点①partial必须在模板里留{format_instructions}这个占位符get_format_instructions()生成的「请按下面 JSON 结构返回」约束才注得进去②invoke传入的键要和模板里的变量名严格对齐这里是amount多传、少传或拼错都会报 KeyError。JsonOutputParser内部已经帮你做了json.loads所以你拿到的直接是 Pythondict不再是需要re去抠的一堆字符串——这在 Java 侧相当于你在服务里直接拿到MapString, Object而不是自己去 parse 文本。对照 Java 视角这个输出「强类型化」的过程就是String→Map再 → 「Pydantic Model」的演进。想再进一步用PydanticOutputParser能直接锚定到一个class上去——而v0.3 更主流也更少踩坑的写法是llm.with_structured_output(PydanticModel)一行就把「让模型按 schema 输出 反序列化成对象」两步合并了我们第 05 篇会专门展开。四、工程化对照Java 视角模板即配置from_messages把提示词和业务代码分离像 Java 把 SQL / 文案外置到资源文件改文案不用动代码。few-shot 即「样例驱动开发」调试模型行为本质是「加样例」而不是「改逻辑」跟对着测试用例改实现一个思路。结构化输出即「对账」JsonOutputParser保证下游是强类型少一层「文本→对象」的反序列化少一类 parser 崩溃。小结能力解决的问题白话from_messages多角色提示词只能「一条」把「规矩」和「提问」分开few-shot少样本模型不知道你要什么格式给 2~3 个例子让它「照抄格式」JsonOutputParser输出是一坨没法处理的文本直接反射成 JSON / dict下一篇预告这一篇我们把提示词打磨成组件下一关是「模型」——第04篇《模型适配一套代码接所有 Provider》——把 API Key、base_url、模型名这些「会变的东西」做成可配置让 LangChain 链能在一个项目里同时换 OpenAI、Zhipu、DeepSeek 多个供应商而业务代码零改动。
返回列表