【AI】Langchain(一)

前言

我们以我们的国产模型deepseek为例,进行langchain的练习

一:环境配置

(1)安装包

复制代码
pip install -U langchain langchain-core langchain-deepseek

(2)配置环境变量

环境变量DEEPSEEK_API_KEY 虽然可以不用配置,但是暴露在代码中还是不太好

进行填写环境变量

(3)这里调用的是远程模型,不是本地模型

二:链的理解与使用

(1)定义模型

python 复制代码
from langchain_deepseek import ChatDeepSeek

model = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0
)

1.from langchain_deepseek import ChatDeepSeek:表示从langchain_deepseek 这个包里面调用ChatDeepSeek这个类

2.model="deepseek-chat"表示你要选择哪个模型

(2)定义消息

python 复制代码
from langchain_core.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage(content="请帮我把英文翻译成中文"),
    HumanMessage(content="hi")
]

SystemMessage(系统命令,给模型限制):它通常作为消息序列里的第一条消息,用来规定 AI 后面整体的行为。

HumanMessage:对模型所说的话

(3)调用模型

python 复制代码
result = model.invoke(messages)

1.invoke(...) 就是执行这个组件的方法

2.你把 messages 传进去,本质上就是拿这些消息去问模型。

(4)结果
result:返回类型其实是一个 AIMessage。

也就是说:

你发出去的是 HumanMessage / SystemMessage

模型回给你的是 AIMessage

这就形成了完整闭环:

人类消息 → 模型处理 → AI 消息

所以:下面的代码就是一个简单的可调用的

python 复制代码
from langchain_deepseek import ChatDeepSeek
from langchain_core.messages import HumanMessage, SystemMessage

# 1. 定义模型
model = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0
)

# 2. 定义消息

messages = [
    SystemMessage(content="请帮我把英文翻译成中文"),
    HumanMessage(content="hi")
]

# 3. 调用模型
result = model.invoke(messages)

# 4. 输出结果
print(result.content)

(2)链式结构体现

对于前面的代码,本质上就是:
输入消息 → 模型处理 → 返回结果

输出解释器

模型返回给你的 result,其实不是你最想直接拿来用的终态数据。它里面除了正文,还有别的信息。

但很多时候你根本不关心这么多。

你可能只想要:

一段纯文本

一个 JSON

一个固定结构的数据

怎么办?

这时候就需要一个专门的"收尾处理者":输出解释器

最终代码:

python 复制代码
from langchain_deepseek import ChatDeepSeek
from langchain_core.messages import HumanMessage, SystemMessage
from langchain_core.output_parsers import StrOutputParser


# 1. 定义模型
model = ChatDeepSeek(
    model="deepseek-chat",
    temperature=0
)

# 2. 定义消息

messages = [
    SystemMessage(content="请把用户输入的英文翻译成中文"),
    HumanMessage(content="My name is Xiaoming.")
]

# 3. 调用模型
result = model.invoke(messages)

# 定义输出解释器
parser = StrOutputParser()

# 4. 输出结果
#print(result.content)
# print(result)

#将结果给放进输出解释器
final_result = parser.invoke(result)
# 输出最终结果
print(final_result)

结果:

前面的普通调用还不算链,因为只是手动调用模型。

LangChain 先引入输出解析器,让模型组件和解析器组件都出现。

模型负责生成结果,解析器负责把结果整理成指定格式。

但此时仍然是手动逐个 invoke,所以还不是真正的链式调用。

真正的链怎么定义?

前面我们已经有两个组件了:

1.model:模型组件

2.parser:输出解析器组件

之前我们还是手动的在调:

python 复制代码
result = model.invoke(messages)
final_result = parser.invoke(result)

使用链的调用:

python 复制代码
chain = model | parser

这里的意思是调用完model的结果后面然后给parser

LangChain 的链式结构,本质是把多个组件按顺序串联起来。

定义链时可以使用管道符 |,例如 chain = model | parser。

它表示先执行 model,再把输出交给 parser。

执行时不再分别调用每个组件,而是直接调用 chain.invoke(messages)。

链会按照从前到后的顺序自动完成整条处理流程。

三:返回值和 invoke()

首先我们要解决俩问题

为什么模型和解析器都能用 invoke()?

模型返回的 result 到底是什么,里面有哪些信息?

1.为什么都能 invoke()?

LangChain 里,很多东西都被抽象成"组件",既然都是组件,就尽量用统一方式去执行。

python 复制代码
model.invoke(...)
parser.invoke(...)

LangChain 不是一堆零散 API,而是一套"统一接口 + 可拼装组件"的设计

2.result 到底是什么?

result 的类型不是普通字符串,而是 AIMessage。

为什么不是字符串?

因为模型返回的,不只是"回答正文"。

如果直接只给你一段字符串 ,那太简陋了。

真实调用里,往往还会带很多附加信息,比如:

回答内容
本次请求消耗了多少 token
模型版本
请求 id
其他响应原数据

所以框架把它包装成一个对象,而不是直接给你个 "你好"

3.AIMessage 可以怎么理解?

前面已经见过两种消息:

HumanMessage:人发给模型的
SystemMessage:系统给模型定规则的

那现在模型回给你的,就叫:

AIMessage

4.AIMessage 里最重要的字段:content

它表示:

AI 返回的正文内容。

比如翻译例子里,你真正想看的就是:

python 复制代码
result.content

这就是"你好"或者"我的名字是小明"这种最终文本。

为什么前面又要引入解析器?

因为如果你每次都自己去:

result.content

那说明你还是在手动扒对象。

后面引入 StrOutputParser(),本质上就是:

让我别再手动管 AIMessage 这些包装,

我只想拿最后的干净字符串。

所以解析器其实是在做整理。

python 复制代码
messages
  ↓
model.invoke(messages)
  ↓
得到 AIMessage
  ├── content                 -> 真正正文
  ├── response_metadata       -> 响应本身的信息
  └── usage / token 等信息    -> 资源消耗信息
  ↓
parser.invoke(result)
  ↓
拿到最终想要的纯字符串/标准格式

LangChain 快速上手的核心,不是单纯调用一次大模型,而是理解它的链式开发思想。

最开始可以按照普通流程来调用模型:先定义模型,再定义消息,然后通过 invoke 调用模型并拿到结果。

模型返回的不是普通字符串,而是 AIMessage 对象,其中 content 表示真正的回答内容。

如果只想得到干净的字符串结果,可以引入 StrOutputParser 作为输出解析器。

当模型组件和解析器组件都定义好之后,就可以用管道符把它们串起来,例如 chain = model | parser。

这样就把原本手动逐步调用的流程,变成了一个自动串联的链式执行流程。

最终只需要执行 chain.invoke(messages),链就会自动按照从前到后的顺序完成整条处理过程。

四:Runnable与LCEL

1.什么是Runnable?

它是LangChain 中"可运行组件"的统一抽象接口。

也就是说,只要一个对象实现了 Runnable 这套标准接口,那么它就可以被 LangChain 当作"一个可以执行的组件"来使用。

比如:
1.模型可以是 Runnable
2.输出解析器可以是 Runnable

所以你才会看到:

为什么调用模型用 invoke(),调用解析器也用 invoke(),调用链还是 invoke()。

因为它们在 LangChain 看来,本质上都是"可运行对象"。

2.Runnable有什么意义?

只要实现了 Runnable ,组件就拥有一致的调用方式,Runnable 的本质,是给 LangChain 的组件定义了一套统一执行规范。

3.为什么 Runnable 很重要?

3.1. 原生接入大模型时的问题

如果你直接使用各家模型自己的 SDK 或 API,那么你会遇到一个现实问题:

模型切换很麻烦。

因为不同模型平台的:

1,请求参数格式不同

2.返回结果结构不同

3.调用方式不同

比如你接 OpenAI,要适配 OpenAI 的接口;

你接 Gemini,要重新适配 Gemini;

你接 DeepSeek,又要再适配一套。

这就像什么?

就像你买了 3 种不同品牌的充电器,每个接口都不一样。

你每换一个手机,就得换一整套线。

3.2.LangChain 是怎么解决的?

LangChain 的思路是:
把不同模型都包装成符合 Runnable 标准的对象

这样一来,你调用它们时,方式就统一了。

python 复制代码
result = model.invoke("你好")

你换模型时,很多时候只需要:

改模型定义

不改后续调用逻辑

也就是说,变的是模型实例,不变的是使用方式

这就是抽象层的价值。

它把底层差异藏起来,把上层调用统一起来。

4,什么是 LCEL?

LCEL全称:LangChain Expression Language

可以理解成:

LangChain 用来"把多个 Runnable 组织起来"的表达方式

也就是说,Runnable 解决的是:

"组件怎么统一执行"

LCEL 解决的是:

"多个组件怎么按顺序连起来执行"

所以 LCEL 更像一种 编排方案

5.链(Chain)到底是什么?

通过链式方式构造出来的 chain,本质上并不是一个"特殊黑盒",它其实也是一个 Runnable 对象。

也就是:可运行序列

模型是 Runnable

解析器是 Runnable

链是由多个 Runnable 组合出来的新 Runnable

所以链本身当然也能继续 invoke()。

这就像搭积木:

单块积木能用

多块拼起来还是一个新的整体

这个整体还能继续被拿来使用

这就是 LCEL 的核心思想。

6.LCEL 为什么能实现链式调用?

前一个 Runnable 的输出,会自动作为后一个 Runnable 的输入。

python 复制代码
chain = model | parser

执行时发生的事情,可以理解成:

1.model.invoke(input) 先执行

2.得到模型输出结果

3.这个输出结果自动传给 parser

4.parser 再继续处理

最终得到整个链的输出

原来你可能得自己写:

python 复制代码
result1 = model.invoke(input)
result2 = parser.invoke(result1)

现在 LCEL 让你可以直接写成:

python 复制代码
chain = model | parser
result = chain.invoke(input)

这就是它作为"编排方案"的价值:
既解决了顺序组织问题,也解决了执行衔接问题

7.为什么链的顺序不能乱?

因为前一个组件的输出类型,必须能被后一个组件接收。

8.定义链的三种方式

方式 1:管道符 |

这是最常用、最推荐的方式。

python 复制代码
chain = model | parser

优点是直观,一眼就能看出执行顺序。

方式 2:显式构造 RunnableSequence

python 复制代码
from langchain_core.runnables import RunnableSequence

chain = RunnableSequence(first=model, last=parser)

这种写法更偏底层,适合你想明确知道链本质是什么的时候。

方式 3:使用 pipe()

php 复制代码
chain = model.pipe(parser)

这和 | 本质上也是同一种思想,只是换了写法。

在 LangChain 中,Runnable 是最核心的底层抽象之一。它为各种组件定义了一套统一的标准接口,因此无论是大模型、输出解析器,还是由多个组件组合而成的链,都可以通过一致的方式调用,例如 invoke()。
这种统一抽象的好处在于,它屏蔽了不同模型和组件之间的底层差异,使开发者能够以一致的方式使用它们,从而降低模型切换和系统扩展的成本。
在 Runnable 的基础上,LangChain 又提供了 LCEL(LangChain Expression Language)来完成组件编排。LCEL 可以把多个 Runnable 按顺序连接起来,形成一个新的 Runnable 对象,通常表现为 RunnableSequence。链式调用的本质,就是前一个组件的输出自动作为后一个组件的输入,从而实现从前到后的流水线执行。
因此可以说:Runnable 解决的是"组件如何统一执行",而 LCEL 解决的是"多个组件如何组合执行"。这也是 LangChain 能够高效组织模型、解析器和其他能力组件的关键所在。

相关推荐
mCell2 小时前
为什么我不建议初学者一上来就用框架学 Agent
javascript·langchain·agent
中科天工2 小时前
中科天工智能包装技术是什么?
大数据·人工智能
醉卧考场君莫笑2 小时前
NLP(词性标注,jieba库实现)
人工智能·自然语言处理
RE.nior2 小时前
2026 年 4 月 AI 视频生成模型实测:Wan 2.7、PixVerse V6、Sora 2、Seedance 2.0 谁能打
人工智能·aigc·音视频
xiangzhihong82 小时前
2026年十大最佳AI视频生成器推荐
人工智能
科技小花2 小时前
2026年数据治理出海:当“全球化运营”遭遇“数据治理壁垒”,谁能提供答案?
网络·人工智能·数据治理·全球化·出海
无忧智库2 小时前
能源集团“十五五“数据资产入表与数据价值化运营管理体系:一次真正意义上的资产重构(WORD)
人工智能
Bruce_Liuxiaowei2 小时前
让AI帮你“看懂”文件:批量重命名、会议纪要、视频翻译全攻略
人工智能·ai·音视频·智能体·workbuddy
啦啦啦_99992 小时前
机器学习大纲
人工智能·机器学习