LangChain 初探:模型调用、链式编排与运行机制

一:Langchain快速上手

首先我们需要理解链式结构:

bash 复制代码
输入 → 组件1 → 组件2 → 组件3 → 输出

并且我们还需要明白一个前提:

LangChain 不是单纯帮你调接口,而是把 AI 开发流程拆成一个个"组件",
再把组件串起来。

1.正常调用大模型

bash 复制代码
1. 接入并定义大模型
2. 定义消息
3. 调用大模型
4. 输出结果

首先我们需要的就是配置环境,具体的配置环境我就不多bb了~

然后就是写代码调用模型~ 作参考~~

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

# 1. 定义模型
model = ChatDeepSeek(model="deepseek-chat")
#这里其实可以天很多其他参数的
比如 temperature
max_tokens
Token

# 2. 定义消息列表
messages = [
    SystemMessage(content="你是一个C++学习助手,请用简洁中文回答。"),
    HumanMessage(content="一加一等于几")
]

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

# 4. 输出结果
print(result)#测试用
print("--------------")
print(result.content)

这个apikey是配置到了win的环境变量里面了

返回结果(整理过后)

bash 复制代码
//真正的大模型回答内容。
content='根据数学定义,1 + 1 = 2。'
//额外参数,表示模型可以回答。如果你问一些违规的内容,可能会拒绝-》"refusal":"我无法帮助完成该请求"
additional_kwargs={
    'refusal': None
}
//模型返回的元数据
// 1.token使用量
// 2.提供商
// 3.模型

response_metadata={
    'token_usage': {
        'completion_tokens': 12,
        'prompt_tokens': 23,
        'total_tokens': 35,
        ...
    },
    'model_provider': 'deepseek',
    'model_name': 'deepseek-v4-flash',
    'system_fingerprint': 'fp_8b330d02d0_prod0820_fp8_kvcache_20260402',
    'id': 'e0388115-b15d-4f1e-b073-28762491cd9f',
    'finish_reason': 'stop',
    'logprobs': None
}


//LangChain本次运行ID
id='lc_run--019e8d0a-c9ea-73a2-b4e7-221959f108b5-0'
//本次没有调用工具所以就是空
tool_calls=[]
//没有错误的工具调用
invalid_tool_calls=[]

//统计费用
usage_metadata={
    'input_tokens': 23,
    'output_tokens': 12,
    'total_tokens': 35,
    ...
}

这个返回结果是:AIMessage

result 返回的是一个对象

2.esponse_metadata 和 usage_metadata 区别

  1. response_metadata

它更关注这次响应本身的信息,比如:

bash 复制代码
请求 ID
模型版本
服务商返回的原始信息
结束原因
调试信息

它常用于:

bash 复制代码
调试
日志记录
问题排查
  1. usage_metadata

它更关注资源消耗,比如:

输入用了多少 token
输出用了多少 token
总共用了多少 token

它常用于:

成本统计
预算控制
接口调用监控

你可以理解为:

response_metadata:这次请求的身份证
usage_metadata:这次请求的消费账单

3.输出解释器

把模型返回的复杂对象,解析成我们想要的格式。 ~

使用方法:

python 复制代码
from langchain_core.output_parsers import StrOutputParser
。
。
。
。
parser = StrOutputParser()
final_result = parser.invoke(result)
print(final_result)

exmaple:

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

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

# 2. 定义消息 列表
messages = [
    SystemMessage(content="你是一个C++学习助手,请用简洁中文回答。"),
    HumanMessage(content="一加一等于几?")
]

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

fina_result = parser.invoke(result)
# 4. 输出结果
print(fina_result)
print("--------------")
print(result.content)

二:链式结构

前面的都是手动执行

链式结构是把组件串起来:chain = model | parser

这个 | 很关键。它是管道符。

可以理解成:前一个组件的输出,自动作为后一个组件的输入。

1.链式调用大模型

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

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

# 2. 定义消息 列表
messages = [
    SystemMessage(content="你是一个C++学习助手,请用简洁中文回答。"),
    HumanMessage(content="一加一等于几?")
]

parser = StrOutputParser()

chain = model | parser

result = chain.invoke(messages)

print(result)

运行结果

python 复制代码
一加一等于二。

2.三种构建链的方式

第一种:管道符 |

这是最常用的写法。

python 复制代码
chain = model | parser

第二种:RunnableSequence

手动创建:

python 复制代码
from langchain_core.runnables import RunnableSequence

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

第三种:pipe 方法

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

三:LangChain 底层:Runnable 和 LCEL

1.Runnable

Runnable 可以理解成 LangChain 里面的一个 标准接口

perl 复制代码
ChatDeepSeek 继承 BaseChatDeepSeek
BaseChatDeepSeek 继承 Runnable 接口
powershell 复制代码
model.invoke(...)
parser.invoke(...)
chain.invoke(...)

对象虽然功能不同,但它们都遵守同一套调用规范

不管你是模型、解析器、Prompt、还是链,只要你是 Runnable,就可以用统一方式运行

LangChain 解决了 原生大模型切换困难 的问题

Runnable 接口

方法 作用
invoke() 单次调用,一个输入对应一个输出
batch() 批处理,多个输入一起处理
stream() 流式输出,一个字/词/token 慢慢返回
ainvoke() 异步调用
astream() 异步流式输出

2.LCEL -LangChain Expression Language

LangChain 表达式语言

LCEL让各个组件进行管道输出

python 复制代码
chain = prompt | model | parser
result = chain.invoke({"topic": "C++ RAII"})

前一个组件的输出,自动作为后一个组件的输入

底层:

chain :

看起来好像只是把两个对象用 | 连起来,但底层其实生成了一个新的对象:

powershell 复制代码
RunnableSequence 

可运行序列
chain = model | parser
理解成:
chain = RunnableSequence(first=model, last=parser)

林外:chain 自己也是一个 Runnable

四:进阶使用Langchain的接口

init_chat_model()

这个函数是 ChatDeepSeek()的进阶替代。

代码:

python 复制代码
from langchain.chat_models import init_chat_model
from langchain_core.messages import SystemMessage, HumanMessage
from langchain_core.output_parsers import StrOutputParser

# 1. 定义模型
deepseek_model  = init_chat_model(model="deepseek-chat",model_provider="deepseek")
#model = ChatDeepSeek(model="deepseek-chat")

messages = [
    SystemMessage(content = "你是一个数学老师"),
    HumanMessage(content="5的负数")
]

parser = StrOutputParser()

chain = deepseek_model|parser

result = chain.invoke(messages)

print(result)

它的目的就是:

用一套写法初始化不同厂商的聊天模型

参数:

参数 作用
temperature 控制回答随机性
max_tokens 控制最大输出长度
timeout 控制请求超时时间
max_retries 控制失败重试次数
api_key 指定 API Key
base_url 指定请求地址

五:可配置模型写法

意思就是在init_chat_model里面不要填模型名称,在下面代码进行配置

invoke() 两个重要参数

参数 作用
input 输入内容,比如字符串或消息列表
config 本次调用的配置信息

config 可以理解成:

对本次 Runnable 调用进行补充配置

所以:config 给可配置模型补上 model 和 provider

代码:

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

# 1. 定义模型
deepseek_model  = init_chat_model(temperature=0.3)
#model = ChatDeepSeek(model="deepseek-chat")

messages = [
    SystemMessage(content = "你是一个数学老师"),
    HumanMessage(content="5的负数")
]

parser = StrOutputParser()

chain = deepseek_model|parser

result = chain.invoke(  messages,
                        config={
                                "configurable": 
                                {
                                    "model": "deepseek-chat",
                                    "model_provider": "deepseek"
                                }
                                }
)

print(result)

config其他参数:

字段 作用
configurable 配置模型运行时可变参数
run_id 本次运行的唯一标识
run_name 本次运行的名称
metadata 附加元数据
un_id、run_name、metadata 更多用于:
powershell 复制代码
日志追踪
链路观测
调试分析
LangSmith 追踪

六:带默认参数的可配置模型

初始化时已经有默认模型,但调用时想临时改参数。

我们需要知道的一个前提就是:

LangChain 默认不会让你随便在运行时修改已有属性。

也就是你在init_chat_model定义的参数,在后面就绝对不能修改!!!

configurable_fields 和 config_prefix

这个其实就是让标记 init_chat_model 里面的参数,告诉我们哪些可以修改

字面意思就是给那些上锁的门解锁

configurable_fields:声明哪些字段允许运行时修改

config_prefix:给配置项加前缀

老师还加了一个参数:

上代码:

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

# 1. 定义模型
deepseek_model  = init_chat_model(model="deepseek-chat",
                                model_provider="deepseek",
                                temperature=0.3,
                                configurable_fields=("max_tokens",),
                           config_prefix="first"
##########################                                )
#多次调用
configurable_fields=("model", "model_provider", "max_tokens"),
config_prefix="first"
#########################                           
#model = ChatDeepSeek(model="deepseek-chat")

messages = [
    SystemMessage(content = "你是一个语文老师"),
    HumanMessage(content="小猫在晒太阳 扩写100字")
]

parser = StrOutputParser()

chain = deepseek_model|parser

result = chain.invoke(  messages,
                        config={
                                "configurable": 
                                {
                                    "first_max_tokens": 10
                                }
                                }
)

print(result)

注意:

("max_tokens",),后面的逗号不能少。

如果你想让所有字段都能被运行时修改,可以设置成类似:

configurable_fields="any"

意思是:

所有可配置字段都允许运行时修改。

不过真实项目里我不建议一上来就这么干。

七:本地模型

前提是你的电脑下载了ollama

代码:

python 复制代码
from langchain_ollama import ChatOllama

model = ChatOllama(
    model="deepseek-r1:1.5b",
    base_url="http://127.0.0.1:11434"
)

result = model.invoke("你是谁?")

print(result.content)

这里的:127.0.0.1

表示本机地址,也就是 localhost。

11434

是 Ollama 默认服务端口。

远程模型和本地模型的对比

对比项 远程模型 本地模型
例子 OpenAI、DeepSeek API Ollama + DeepSeek R1
是否需要 API Key 通常需要 通常不需要
是否依赖网络 需要 本地运行时不一定需要
模型能力 通常更强 取决于本地模型大小
隐私性 数据发到远程服务 数据留在本机
速度 受网络和服务影响 受本机配置影响
成本 可能按 token 计费 主要消耗本机算力
相关推荐
z200509301 小时前
【linux学习】Linux 软硬链接深度解析:从 inode 到目录硬链接的那些坑
前端·chrome
competes1 小时前
数据查询方式最左匹配原则
java·大数据·前端·人工智能·windows
光影少年1 小时前
react中的Context 为什么会导致性能问题?
前端·javascript·react.js
ZC跨境爬虫1 小时前
跟着 MDN 学CSS day_48:深入CSS多列布局——像报纸一样组织内容
前端·css·学习
Just Jump2 小时前
企业级AI角色扮演对话系统
langchain·ai对话系统·skill技能热加载·角色扮演
易知微EasyV数据可视化2 小时前
Web+游戏引擎模式:设计的跨界协同最优解 | 数字孪生实战训练营·设计篇
前端·经验分享·游戏引擎·数字孪生·空间智能
羊羊小栈2 小时前
农业病害知识管理系统(基于前后端Web开发)
前端·人工智能·毕业设计·大作业