LangChain新手入门指南03
文章目录前言一、提示词模板Prompts告别手动拼接Prompt1.1 为什么需要提示词模板1.2 入门必学的4种模板1.2.1 基础字符串模板PromptTemplate1.2.2 聊天提示模板ChatPromptTemplate1.2.3 消息占位符MessagesPlaceholder1.2.4 少样本提示模板FewShotPromptTemplate1.3 新手提示词最佳实践二、输出解析器Output Parsers让大模型输出结构化数据2.1 为什么需要输出解析器2.2 入门必学的4种解析器2.2.1 最基础StrOutputParser2.2.2 JSON解析JsonOutputParser2.2.3 带校验PydanticOutputParser2.2.4 生产推荐with_structured_output2.3 输出解析器选型速查表三、Chains链式调用搭积木一样构建AI工作流3.1 什么是Chain3.2 核心基础Runnable统一接口3.3 LCEL表达式语言用管道符拼积木3.4 常用Runnable组合器3.4.1 RunnableParallel并行分叉3.4.2 RunnablePassthrough输入透传3.4.3 RunnableLambda自定义逻辑3.4.4 RunnableWithMessageHistory带记忆的对话四、入门总结核心知识点梳理前言很多刚接触大模型应用开发的同学都会频繁听到LangChain这个框架但刚上手时很容易被各种模板、解析器、链式概念绕晕。本文完全从零基础视角出发拆解LangChain最核心的三大基础组件提示词模板、输出解析器、Chains链式调用全程附可运行的极简代码示例看完就能上手搭建自己的第一个大模型应用。一、提示词模板Prompts告别手动拼接Prompt1.1 为什么需要提示词模板在大模型开发中我们几乎不会写死固定的Prompt而是需要根据用户输入动态生成内容。如果每次都手动拼接字符串不仅代码冗余重复还很容易出现格式错误。提示词模板的核心思想就是把Prompt的固定部分和可变部分分离通过「模板变量」的方式动态生成最终的提示词自带三大优势复用性强一次定义模板传入不同参数就能生成不同Prompt便于维护所有提示词统一管理修改和迭代更方便优化友好独立的模板方便做A/B测试适配提示词工程优化1.2 入门必学的4种模板1.2.1 基础字符串模板PromptTemplate这是最简单的提示词模板适用于纯文本生成的简单场景相当于带占位符的字符串模板。fromlangchain_core.promptsimportPromptTemplate# 方式1快速创建推荐新手用promptPromptTemplate.from_template(讲一个关于{topic}的{adjective}故事)# 方式2构造方法创建显式声明变量promptPromptTemplate(template讲一个关于{topic}的{adjective}故事,input_variables[topic,adjective])# 传入变量生成最终Promptformatted_promptprompt.invoke({topic:人工智能,adjective:有趣的})print(formatted_prompt)# 输出text讲一个关于人工智能的有趣的故事进阶技巧部分变量预填充如果模板里有部分变量是固定值可以提前填充减少后续调用的传参# 运行时动态固定变量promptPromptTemplate.from_template(讲一个关于{topic}的{adjective}故事)fixed_promptprompt.partial(adjective有趣的)# 后续只需要传topic即可print(fixed_prompt.invoke({topic:编程}))1.2.2 聊天提示模板ChatPromptTemplate纯字符串模板只适合单轮文本生成而多轮对话场景中大模型需要接收带角色的消息列表系统提示、用户消息、AI回复这时候就需要用ChatPromptTemplate。LangChain支持三种核心角色system系统消息用来设定AI的角色、行为规则human用户输入的消息aiAI的回复消息fromlangchain_core.promptsimportChatPromptTemplate# 用元组形式构造带变量时最简洁chat_promptChatPromptTemplate.from_messages([(system,你是一个专业的{role}。),(human,请回答关于{topic}的问题。),(human,{question})])# 生成带角色的消息列表messageschat_prompt.invoke({role:Python编程助手,topic:Python装饰器,question:什么是装饰器?})1.2.3 消息占位符MessagesPlaceholder做带记忆的对话系统时我们需要把历史对话动态插入到Prompt中MessagesPlaceholder就是专门用来预留「历史消息插槽」的工具。fromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain_core.messagesimportAIMessage,HumanMessage# 模板里预留history插槽promptChatPromptTemplate.from_messages([(system,你是AI助手),MessagesPlaceholder(variable_namehistory),# 历史对话占位(human,{input})])# 调用时传入历史消息列表messagesprompt.invoke({history:[HumanMessage(content什么是Python?),AIMessage(contentPython是一种通用编程语言。),],input:它有什么特点?})1.2.4 少样本提示模板FewShotPromptTemplate如果想让模型严格按照指定格式输出只靠文字指令效果不稳定这时候可以给模型几个示例也就是「少样本学习」。FewShotPromptTemplate可以自动把示例拼接到Prompt里。fromlangchain_core.promptsimportFewShotPromptTemplate,PromptTemplate# 1. 准备示例数据examples[{input:高兴,output:开心},{input:难过,output:悲伤},{input:生气,output:愤怒}]# 2. 定义单条示例的格式example_formatterPromptTemplate(template输入: {input}\n输出: {output},input_variables[input,output])# 3. 创建少样本模板few_shot_promptFewShotPromptTemplate(examplesexamples,example_promptexample_formatter,prefix以下是一些同义词转换的例子:,suffix\n输入: {input}\n输出:,input_variables[input])# 生成最终Promptprint(few_shot_prompt.invoke({input:兴奋}))1.3 新手提示词最佳实践指令清晰明确不要只写「请翻译」要写「将以下文本从中文翻译成英文保留专业术语」设定角色身份用system消息给AI设定专业角色输出质量会显著提升明确约束条件比如「回答不超过100字」「只回答Python相关问题」提供参考示例格式要求严格的场景优先用少样本模板引导模型二、输出解析器Output Parsers让大模型输出结构化数据2.1 为什么需要输出解析器大模型默认返回的是自然语言文本但在实际开发中我们往往需要程序直接处理结果比如提取字段、存入数据库、调用下游接口这就需要模型输出JSON、列表等结构化格式。输出解析器的核心作用就是把大模型的自然语言输出转换成程序可直接使用的结构化数据。实现结构化输出主要有两种思路实现策略原理可靠性适用场景Prompt约束在提示词里要求模型输出指定格式依赖模型能力可能出错通用场景所有模型都支持厂商原生能力调用API的结构化输出参数底层强制约束极高API层面保证格式生产环境需对应厂商支持2.2 入门必学的4种解析器2.2.1 最基础StrOutputParser最简单也最常用的解析器作用就是把大模型返回的AIMessage对象提取成纯字符串几乎所有基础链都会用到。fromlangchain_core.output_parsersimportStrOutputParser parserStrOutputParser()# 典型用法放在链的最后直接拿到文本结果# chain prompt | llm | StrOutputParser()2.2.2 JSON解析JsonOutputParser通过Prompt约束的方式引导模型输出JSON格式再自动解析成Python字典适合通用JSON提取场景。使用步骤用Pydantic定义目标结构 → 创建解析器 → 把格式说明注入Prompt → 解析结果fromlangchain_core.output_parsersimportJsonOutputParserfromlangchain_openaiimportChatOpenAIfrompydanticimportBaseModel,Field llmChatOpenAI(modelgpt-4o-mini,temperature0.0)# 1. 定义目标JSON结构classPrime(BaseModel):prime:list[int]Field(description素数)count:list[int]Field(description小于该素数的素数个数)# 2. 创建解析器json_parserJsonOutputParser(pydantic_objectPrime)# 3. 调用模型把格式说明放进系统提示resllm.invoke([(system,json_parser.get_format_instructions()),(user,任意生成5个1000-100000之间的素数并标出小于该素数的素数个数)])# 4. 解析成Python字典parsed_resjson_parser.invoke(res)2.2.3 带校验PydanticOutputParser和JsonOutputParser不同它解析后返回的是Pydantic对象支持字段级别的类型校验、规则校验适合对数据准确性要求高的场景。fromlangchain_core.output_parsersimportPydanticOutputParserfrompydanticimportBaseModel,Field# 定义带校验规则的数据模型classMovieReview(BaseModel):title:strField(description电影标题)rating:intField(description评分,1-10分,ge1,le10)# 限制数值范围summary:strField(description剧情简介)recommended:boolField(description是否推荐)parserPydanticOutputParser(pydantic_objectMovieReview)# 解析后直接拿到带校验的Pydantic对象字段不合法会直接报错2.2.4 生产推荐with_structured_output这是LangChain的统一封装接口底层自动调用大模型厂商的原生结构化输出能力比Prompt约束可靠得多而且更换模型不需要改业务代码生产环境优先用。fromlangchain_openaiimportChatOpenAIfrompydanticimportBaseModel# 1. 初始化大模型llmChatOpenAI(modelgpt-4o-mini,temperature0.0)# 2. 定义数据结构classCalendarEvent(BaseModel):name:strdate:strparticipants:list[str]# 3. 封装成结构化输出的Runnablestructured_llmllm.with_structured_output(schemaCalendarEvent)# 4. 直接调用返回Pydantic对象resultstructured_llm.invoke(Alice和Bob周五要去参加科技展)2.3 输出解析器选型速查表新手不用纠结直接对着场景选场景推荐方案普通文本生成只拿字符串结果StrOutputParser通用JSON提取不依赖特定厂商JsonOutputParser生产环境要求格式绝对正确with_structured_output()需要字段类型、规则校验PydanticOutputParser三、Chains链式调用搭积木一样构建AI工作流3.1 什么是Chain单独的提示词模板、大模型、输出解析器能力都很有限而实际的AI应用往往需要多个步骤串联接收输入 → 生成Prompt → 调用大模型 → 解析结果 → 后续处理。Chain链的本质就是把多个组件按顺序组合成完整工作流像流水线一样自动执行让复杂的AI应用调用起来像调用一个函数一样简单。3.2 核心基础Runnable统一接口LangChain所有核心组件提示词模板、大模型、解析器、工具、链本身都实现了Runnable接口也就是所有组件都有统一的调用方式这是链式调用的基础。常用的4个核心方法方法作用适用场景invoke()同步单次调用普通单轮请求stream()流式逐块输出打字机效果的对话展示batch()批量处理多个输入批量数据处理ainvoke()异步单次调用高并发异步服务3.3 LCEL表达式语言用管道符拼积木LCELLangChain表达式语言是LangChain的核心语法用管道符|就可以把多个Runnable组件串联起来写法非常简洁。最经典的基础链写法fromlangchain_core.promptsimportChatPromptTemplatefromlangchain_core.output_parsersimportStrOutputParserfromlangchain_openaiimportChatOpenAI# 1. 定义各个组件promptChatPromptTemplate.from_template(请用{tone}风格回答:{question})llmChatOpenAI(modelgpt-4o-mini)parserStrOutputParser()# 2. 用管道符拼成链chainprompt|llm|parser# 3. 直接调用整个链resultchain.invoke({tone:幽默,question:什么是人工智能?})组合后的链本身也是Runnable支持invoke/stream/batch所有方法还可以继续和其他组件组合成更复杂的链。3.4 常用Runnable组合器除了基础的顺序执行LCEL还提供了组合器来实现复杂逻辑新手掌握这4个就够应对绝大多数场景。3.4.1 RunnableParallel并行分叉同一个输入同时传给多个分支执行最后把所有结果合并成一个字典适合多任务并行处理的场景。fromlangchain_core.runnablesimportRunnableLambda# 字典写法会自动转成并行执行parallel_chain{length:RunnableLambda(lambdax:len(x)),uppercase:RunnableLambda(lambdax:x.upper()),word_count:RunnableLambda(lambdax:len(x.split()))}resultparallel_chain.invoke(Hello World LangChain)# 输出{length: 24, uppercase: HELLO WORLD LANGCHAIN, word_count: 3}3.4.2 RunnablePassthrough输入透传作用是把输入原样传递下去最常用的场景是保留原始输入的同时新增其他字段比如RAG场景里同时保留用户问题和检索到的上下文。fromlangchain_core.runnablesimportRunnablePassthrough# 保留原始输入同时新增转换后的字段chain{original:RunnablePassthrough(),uppercase:lambdax:x[text].upper()}resultchain.invoke({text:hello})3.4.3 RunnableLambda自定义逻辑把普通的Python函数包装成Runnable这样自定义的处理逻辑就能直接放进链里实现灵活的自定义操作。fromlangchain_core.runnablesimportRunnableLambda# 自定义函数从URL提取域名defextract_domain(url):returnurl.split(//)[-1].split(/)[0]# 包装成Runnabledomain_extractorRunnableLambda(extract_domain)# 放进链里使用chaindomain_extractor|RunnableLambda(lambdax:fhttp://{x})print(chain.invoke(https://www.example.com/path))3.4.4 RunnableWithMessageHistory带记忆的对话官方封装好的带历史对话的链只需要提供历史存储函数就能快速实现多轮对话记忆功能。fromlangchain_core.runnables.historyimportRunnableWithMessageHistoryfromlangchain_core.chat_historyimportInMemoryChatMessageHistoryfromlangchain_core.promptsimportChatPromptTemplate,MessagesPlaceholderfromlangchain_openaiimportChatOpenAI# 会话存储用session_id区分不同用户store{}defget_session_history(session_id:str):ifsession_idnotinstore:store[session_id]InMemoryChatMessageHistory()returnstore[session_id]# 基础链promptChatPromptTemplate.from_messages([(system,你是AI助手),MessagesPlaceholder(variable_namehistory),(human,{input})])llmChatOpenAI(modelgpt-4o-mini)base_chainprompt|llm# 包装成带历史的链chain_with_historyRunnableWithMessageHistory(base_chain,get_session_history,input_messages_keyinput,history_messages_keyhistory)# 调用时指定session_id自动携带历史对话responsechain_with_history.invoke({input:我叫张三},config{configurable:{session_id:user123}})四、入门总结核心知识点梳理提示词模板解决「动态生成Prompt」的问题基础场景用PromptTemplate对话场景用ChatPromptTemplate带记忆加MessagesPlaceholder需要示例用FewShotPromptTemplate。输出解析器解决「模型输出结构化」的问题普通文本用StrOutputParser生产环境结构化输出优先用with_structured_output。链式调用用LCEL管道符把组件串成工作流所有组件都遵循Runnable接口支持顺序、并行、透传、自定义等多种逻辑。