AI基础入门(应用开发篇)——LangChain:核心抽象

作者:大模型教程日期:2025/11/29

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI

一、前提

  • LangChain 是一个 AI 应用开发的生态,包括了开发框架、社区生态和扩展生态。其中,最重要的,也是构成整个生态基础的就是开发框架。
  • 开发框架为我们提供了构建大模型应用的基础抽象和 LangChain 表达式语言,其中,LangChain 表达式语言是为了提高代码的表达性,要想理解 LangChain,关键点就是理解其中的基础抽象。这一讲,我们就来讨论一下 LangChain 的基础抽象。

二、LangChain 提供的最核心的三个抽象

2.1、ChatModel

  • ChatModel:整个框架的核心,根据输入的内容生成输出。
  • 如果你去查看 LangChain 的文档,估计第一个让人困惑的问题一定就是为什么 LangChain 中既有 LLM,也有 ChatModel?
  • 它俩的关系其实类似于之前我们说的补全接口和聊天补全接口的关系,LLM 对应的是文本到文本的生成,而 ChatModel 则是对应着由 ChatGPT 带来的聊天模式。
  • 大部分情况下,推荐使用 ChatModel,即便对于非聊天应用也是如此,如同聊天补全接口几乎可以替代补全接口,ChatModel 几乎可以完全替代 LLM。所以,我们后面的讨论也集中在 ChatModel 上。
  • 我们来看一个例子,它的主要作用就是把一段文字由英文翻译成中文:
1from langchain_core.messages import HumanMessage, SystemMessage  
2from langchain_openai import ChatOpenAI  
3  
4os.environ["OPENAI_API_KEY"] = "你的 API Key"  
5os.environ["OPENAI_API_BASE"] = "你的 API Base"  
6  
7messages = [  
8    SystemMessage(content="Translate the following from English into Chinese:"),  
9    HumanMessage(content="Welcome to LLM application development!"),  
10]  
11  
12model = ChatOpenAI(model="gpt-4o-mini")  
13result = model.invoke(messages)  
14print(result)
15
  • 在这段代码里,我们创建了一个 ChatModel,也就是这里的 ChatOpenAI,它负责集成 OpenAI 的模型。在创建这个 ChatModel 的同时,我们指定了使用的具体模型,这里我们用到的是 GPT-4o-mini。
  • 正如我们上一讲所说,具体的实现是由社区生态提供的,所以,我们要想使用 ChatOpenAI 模型,需要安装 langchain-openai 这个包。有许多服务提供商会提供多个基础抽象的实现,比如,OpenAI 除了 ChatModel 之外,还提供了 Embedding 模型,所有与 OpenAI 相关的内容都会统一放到 langchain-openai这个包里,LangChain 社区将它们统一称为供应商(Provider) ,这里的 OpenAI 就是一个供应商。
  • 接下来,就是把消息传给模型。还记得我们在 OpenAI API 提到的消息吗?每条消息都包含角色和内容两个部分,SystemMessage 表示消息的角色是系统,HumanMessage 表示消息的角色是人,对应到 OpenAI API 的底层实现,角色就是用户。然后,我们通过 model.invoke 把消息传给了模型,接下来只需等待返回结果。
  • 下面是一次执行的结果,我们前面讲过 OpenAI API 的应答,在这里都可以对应上,我就不过多解释了。
1content='欢迎来到大型语言模型应用开发!' additional_kwargs={'refusal': None} response_metadata={'token_usage': {'completion_tokens': 8, 'prompt_tokens': 26, 'total_tokens': 34, 'completion_tokens_details': {'reasoning_tokens': 0}}, 'model_name': 'gpt-4o-mini-2024-07-18', 'system_fingerprint': 'fp_483d39d857', 'finish_reason': 'stop', 'logprobs': None} id='run-12d4417e-811b-467a-a92f-3deec9106db6-0' usage_metadata={'input_tokens': 26, 'output_tokens': 8, 'total_tokens': 34}
2
3
  • 尝试运行这段代码,你会发现,“等待”是执行中最让人难熬的部分,因为我们采用的同步方式执行代码,所以,必须等到所有的内容完全产生之后,我们才能得到响应。你可能想到我要说什么了,没错,我们需要流式响应。我们调整一下代码:
1from langchain_core.messages import HumanMessage, SystemMessage  
2from langchain_openai import ChatOpenAI  
3  
4messages = [  
5    SystemMessage(content="Translate the following from English into Chinese:"),  
6    HumanMessage(content="Welcome to LLM application development!"),  
7]  
8  
9model = ChatOpenAI(model="gpt-4o-mini")  
10stream = model.stream(messages)  
11for response in stream:  
12    print(response.content, end="|")
13
  • 同前面的代码相比,这段代码仅有的变化就是用流处理代替了同步调用,这里调用的函数是 stream,这个函数的返回值是迭代器(Iterator),我们可以用 for 循环来一个一个处理返回的内容。这里我只处理返回的内容部分,为了让结果看得更清楚,我给结果加上了一个分割符,这就是 end="|" 处理的效果。
  • 下面就是这段代码一次执行的结果,分割线之间的内容就是一个消息块中的内容:
1|欢迎|来到|大型|语言|模型|应用|开发|!||  
  • 之前我们说过,所有的 LangChain 应用代码核心就是构建一条链。在这里,单独的一个模型也是一条链,只不过这条链上只有一个组件,它就是 ChatModel。前面的两个例子演示的调用方法其实也是链的调用方法。在后面的例子里,我会把重点放在链的组装上,返回结果如何处理在这两个例子里已经做了相应的演示。
  • 除了同步调用和流式处理,链还提供了其它的调用方式,比如,批处理和异步调用等。这些调用方式都是在同步调用和流式处理的基础上做了封装,简化代码的编写,你可以在需要时查看相关的文档。

2.2、PromptTemplate

  • PromptTemplate:负责处理输入,有效拆分了开发者提示词和用户提示词。
  • LangChain 把这种预置提示词的方法提炼了出来,引入了一个叫提示词模板(PromptTemplate)的概念。下面是一个例子,这段代码的功效和前面的例子完全一样,只是我用了提示词模板:
1from langchain_core.prompts import ChatPromptTemplate  
2from langchain_openai import ChatOpenAI  
3  
4prompt_template = ChatPromptTemplate.from_messages(  
5    [  
6        ("system", "Translate the following from English into Chinese:"),  
7        ("user", "{text}")  
8    ]  
9)  
10  
11model = ChatOpenAI(model="gpt-4o-mini")  
12  
13chain = prompt_template | model  
14result = chain.invoke({"text":"Welcome to LLM application development!"})  
15print(result)
16
17
  • 除了使用 ChatPromptTemplate 这个类型之外,提示词模板的部分你会觉得非常眼熟,这和前面例子里面的消息内容几乎一模一样,仅有的差别是在用户消息里面,我们没有采用一个固定的输入,而是引入了一个占位符 text。熟悉各种模板语言的话,通过 {} 定义占位符的方式你一定不陌生,这个位置就是留给用户填写的内容。
  • 现在我们有了两个组件(PromptTemplate 和 ChatModel),我们可以通过 LCEL 把它们组成一条链:
1chain = prompt_template | model  
  • 在 LCEL 中,组件声明的先后顺序就是处理逻辑的先后顺序。在这个处理过程中,先是提示词模板把输入参数处理成发给模型的消息,所以,这里把提示词模板写在前面,模型写在后面。
  • 有了链之后,就可以调用这条链了。相比于直接传递消息,这次我们在调用传递的是一个变量名及其对应的值。PromptTemplate 内部会先做一个替换,用这里的值替换掉模板中的占位符。如果你想知道替换出来的消息到底长什么样,可以像下面这样查看一下:
1messages = prompt_template.invoke({"text":"Welcome to LLM application development!"})  
2print(messages)
3
  • 引入了 PromptTemplate 之后,开发者写的提示词和用户的消息就完全分开了。开发者可以不断地调整提示词以便达到更好的效果,而这一切对用户完全屏蔽掉了。此外,还有一个好处,就是好的提示词模板是可以共享出来的,我们甚至可以把别人写好的提示词用在自己的代码里。我们在上一讲说过的提示词社区就是这样诞生的。

2.3、OutputParser

  • PromptTemplate 处理的是输入,与之对应的是 OutputParser,从名字就可以看出,它是负责处理输出的。在前面的例子里,我们看到的输出都是一个对象,在正常情况下,我们还需要编写代码从这个输出对象中解析出自己所需的信息,比如,想要获得大模型生成的内容,我们要这么写:
1content = result.content  
  • OutputParser 就是把输出结果的解析过程单独拿了出来。LangChain 里提供了一些常用的解析器,比如,把输出结果拿出来就对应着 StrOutputParser。下面是一个例子:
1from langchain_core.prompts import ChatPromptTemplate  
2from langchain_core.output_parsers import StrOutputParser  
3from langchain_openai import ChatOpenAI  
4  
5prompt_template = ChatPromptTemplate.from_messages(  
6    [  
7        ("system", "Translate the following from English into Chinese:"),  
8        ("user", "{text}")  
9    ]  
10)  
11  
12model = ChatOpenAI(model="gpt-4o-mini")  
13parser = StrOutputParser()  
14  
15chain = prompt_template | model | parser  
16result = chain.invoke({"text":"Welcome to LLM application development!"})  
17print(result)
18
  • 这个例子接续了上一个例子的代码,唯一的差别是这里创建了 StrOutputParser,因为它处理的是模型的输出结果,所以,它的声明应该是在模型之后的。正如 StrOutputParser 名字所示,它把输出结果解析成了一个字符串,chain.invoke 在之前的例子里是直接返回一个对象,而因为有了 StrOutputParser,它返回的结果就成了一个字符串:
1欢迎来到大语言模型应用开发!  
  • 当然,输出解析远不止把内容提取出来。LangChain 还提供了许多不同的输出格式解析器,比如:JSON、CSV、分割符、枚举等等。但你可能会有一个疑问,我该怎么让大模型返回这些格式呢?LangChain 已经为我们做好了准备。
  • 下面我们来看一个例子,我们让大模型帮我们列出一些著名作者的作品,用 JSON 格式返回:
1
2from langchain_core.output_parsers import JsonOutputParser  
3from langchain_core.prompts import PromptTemplate  
4from langchain_openai import ChatOpenAI  
5from pydantic import BaseModel, Field  
6  
7class Work(BaseModel):  
8    title: str = Field(description="Title of the work")  
9    description: str = Field(description="Description of the work")  
10  
11  
12parser = JsonOutputParser(pydantic_object=Work)  
13  
14prompt = PromptTemplate(  
15    template="列举3部{author}的作品。\n{format_instructions}",  
16    input_variables=["author"],  
17    partial_variables={"format_instructions": parser.get_format_instructions()},  
18)  
19  
20model = ChatOpenAI(model="gpt-4o-mini")  
21  
22chain = prompt | model | parser  
23result = chain.invoke({"author": "老舍"})  
24print(result)
25
26
  • 在这个例子里,我们首先声明了返回的格式,也就是这里的作品(Work),其中包含了标题(title)和描述(description)两个字段。然后,声明了一个 JsonOutputParser,告诉它根据 Work 这个对象解析结果。
  • 关键的部分来了,在声明提示词模板时,除了正常的提示词部分,我们还额外加上了格式指令(format_instructions),它就是对大模型回复内容的约束。然后,我们在partial_variables 里初始化了格式指令这个变量,给它赋值为 parser.get_format_instructions()。
  • 是的,LangChain 已经替我们写好了提示词。许多输出解析器都提供了格式指令,我们只要在配置提示词的时候,把它们添加到其中就可以了。当然,如果你愿意深究,完全也可以调用一下模板的 invoke 看看生成的提示词到底是什么样。
  • 顺便说一下,这里的 partial_variables 相当于初始化一次的变量,我们可以理解为,它把模板里的一部分内容填写好,生成了一个新的模板,后面使用的就是这个新的模板。相应地,input_variables 是来自用户的输入,所以,每次都有不同的内容。
  • 下面是执行这段代码的一次输出,我让它回答了老舍有哪些作品:
1[{'title': '骆驼祥子', 'description': '讲述了一个人力车夫的悲惨生活和梦想,反映了旧社会的残酷和人性的复杂。'}, {'title': '四世同堂', 'description': '描绘了一个大家族在抗日战争时期的生活和挣扎,展现了中国传统文化与现代冲突的深刻主题。'}, {'title': '茶馆', 'description': '通过一个茶馆的兴衰反映了社会变迁,揭示了人性、社会和历史的多重层面。'}]  
  • 到这里,我们讨论了 LangChain 中最核心的三个抽象:ChatModel、PromptTemplate 和 OutputParser。经过这一讲的讲解,你已经可以编写一些简单的大模型应用了,只要把提示词模板的内容替换成你要完成的工作。当然,LangChain 提供的抽象远不止这些。在接下来的内容中,我会结合具体的应用,给你讲解遇到的各种抽象。

学习资源推荐

如果你想更深入地学习大模型,以下是一些非常有价值的学习资源,这些资源将帮助你从不同角度学习大模型,提升你的实践能力。

本文较长,建议点赞收藏。更多AI大模型应用开发学习视频及资料,在智泊AI


AI基础入门(应用开发篇)——LangChain:核心抽象》 是转载文章,点击查看原文


相关推荐


web开发,在线%药店管理%系统,基于Idea,html,css,jQuery,java,ssm,mysql。
合作小小程序员小小店2025/11/26

经验心得 开发在线药店管理系统Demo时,以Idea为工具,用SSM框架搭建后端架构。前端用HTML构建药品入库、销售台账等模块页面,CSS实现分类展示布局,jQuery处理库存预警弹窗与表单校验。后端通过Spring MVC接收请求,MyBatis 优化药品表、库存表的关联查询,Spring管理事务确保售药数据一致性。MySQL设计时重点考虑药品批次与有效期索引,提升过期预警效率。发中曾遇多用户同时售药的数据冲突问题,通过 SSM的事务隔离机制解决。此次实践掌握了 SSM框架的协同开发模式,


Jetpack Compose 实战:复刻 Material 3 圆形波浪进度条
雨白2025/11/24

效果 要实现的效果是 Material 3 的 CircularWavyProgressIndicator。简单来说,就是一个带波浪的圆形进度条。 圆形波浪进度指示器 实现步骤 绘制轨道和平滑波浪 首先我们将轨道和“碾平”的波浪绘制出来。 对于普通圆弧,我们通常会使用 DrawScope.drawArc()。但我们需要绘制波浪,后续需要对每个点进行偏移,所以必须使用 Path() 来进行每个点的绘制。 @Composable fun CircularWavyProgressIndicatorSt


鸿蒙ets实现强制蜂窝网络
波儿菜2025/11/23

在用户同时开启 wifi/cellular 时,期望强行使用 cellular 访问网络,这是个比较常规的诉求。 鸿蒙提供了大量的 ets 网络基础库,本来以为能简单实现这个能力,却有些令人不解的坑。 作为基建来说,规避 ets 而直接使用 C++ 可能才是最优解。 获取蜂窝网络 IP 第一个坑就是connection.getAllNets()接口在 wifi/cellular 同时开启时并不会返回 cellular 的NetHandle,仅开启 cellular 才能拿到其NetHandle。


计算机网络重要知识点
Eric_Makabaka2025/11/21

内容来源于飞天闪客,讲的非常通俗易懂。 网络是怎么传输的? https://www.bilibili.com/video/BV1tseyzCEoF?spm_id_from=333.788.videopod.sections&vd_source=c815609efed4d3ffbba6f23ca86d94ae 集线器(物理层) 两台电脑之间想要通信,可以直接通过一条网线进行连接。但是随着网线的增加,每台电脑的线太过混乱,不好管理。 所以就有了集线器这样的设备,把各自的网线都插到这


Docker 安装配置
ITVV2025/11/19

卸载旧版本(如有) sudo apt remove docker docker-engine docker.io containerd runc 安装依赖包 sudo apt update sudo apt install -y \ ca-certificates \ curl \ gnupg \ lsb-release 添加 Docker 官方 GPG 密钥 sudo mkdir -p /etc/apt/keyrings curl -fsSL htt


Lua 的标准库
hubenchang05152025/11/18

#Lua 的标准库 #变量 _G - Lua 的全局环境,包含所有全局变量(包括 _G 自身);Lua 本身并不使用这个变量,改变它的值不会有任何作用 _VERSION - Lua 的版本,例如 "Lua 5.4" #基础函数 assert - 断言 collectgarbage - 垃圾收集 dofile - 执行文件中的 Lua 代码 error - 主动抛出错误,终止当前代码的执行 getmetatable - 获取元表 ipairs - 遍历数组 load - 加载一个代码块 l


SeqXGPT:Sentence-Level AI-Generated Text Detection —— 把大模型的“波形”变成测谎仪
only-code2025/11/17

1. 论文基本信息 标题:  SeqXGPT: Sentence-Level AI-Generated Text Detection 作者:  Pengyu Wang, Linyang Li, Ke Ren, Botian Jiang, Dong Zhang, Xipeng Qiu 年份:  2023 机构:  Fudan University, Shanghai Key Laboratory of Intelligent Information Processing 领域关键


Python 的内置函数 open
IMPYLH2025/11/16

Python 内建函数列表 > Python 的内置函数 open Python 的内置函数 open() 是用于打开文件的重要函数,它提供了与文件系统交互的基本接口。该函数返回一个文件对象(file object),可用于读取、写入或追加文件内容。 函数签名 open(file, mode='r', buffering=-1, encoding=None, errors=None, newline=None, closefd=True, opener=None) 主要参数说明 f


word表格操作疑难杂症处理
weixin_438338512025/11/14

1. 从excel 复制一个表格粘贴到word中,表格超出word的宽度 第一种方式:点表格左上角的按钮全选表格, 表格工具---自动调整---根据窗口调整表格 或者 根据内容调整表格。 第二种方式:设置 页边距 和 纸张大小,默认A4纸,可能大小就是不够 第三种方式: 粘贴表格对象 复制表格后,在word中不要直接粘贴,而是在word中空白处 右键 ,选择最后一个图标“选择性粘贴”,选择 wps表格对象---确定, 这样就是一模一样的粘贴过来了,但是word中无法直接编辑该


HarmonyOS Web组件深度解析:构建高性能JavaScript交互的实践与创新
万少-2025/11/13

HarmonyOS Web组件深度解析:构建高性能JavaScript交互的实践与创新 引言 在万物互联的时代,HarmonyOS作为分布式操作系统,其应用生态的构建离不开Web技术的深度融合。Web网页组件(Web组件)作为连接Web生态与原生应用的关键桥梁,其JavaScript交互能力直接决定了应用的体验边界。传统的WebView交互往往局限于简单的URL加载和基础脚本执行,但在HarmonyOS的分布式架构下,我们需要重新思考JavaScript交互的深度与广度。 本文将深入探讨Harm

首页编辑器站点地图

本站内容在 CC BY-SA 4.0 协议下发布

Copyright © 2025 聚合阅读