一:Langchain快速上手
首先我们需要理解链式结构:
输入 → 组件1 → 组件2 → 组件3 → 输出并且我们还需要明白一个前提:
LangChain 不是单纯帮你调接口,而是把 AI 开发流程拆成一个个“组件”,
再把组件串起来。
1.正常调用大模型
1. 接入并定义大模型2. 定义消息3. 调用大模型4. 输出结果首先我们需要的就是配置环境,具体的配置环境我就不多bb了~
然后就是写代码调用模型~作参考~~
fromlangchain_deepseekimportChatDeepSeekfromlangchain_core.messagesimportSystemMessage,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的环境变量里面了
返回结果(整理过后)
//真正的大模型回答内容。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本次运行IDid='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 区别
- response_metadata
它更关注这次响应本身的信息,比如:
请求 ID 模型版本 服务商返回的原始信息 结束原因 调试信息它常用于:
调试 日志记录 问题排查- usage_metadata
它更关注资源消耗,比如:
输入用了多少 token
输出用了多少 token
总共用了多少 token
它常用于:
成本统计
预算控制
接口调用监控
你可以理解为:
response_metadata:这次请求的身份证
usage_metadata:这次请求的消费账单
3.输出解释器
把模型返回的复杂对象,解析成我们想要的格式。~
使用方法:
fromlangchain_core.output_parsersimportStrOutputParser 。 。 。 。 parser=StrOutputParser()final_result=parser.invoke(result)print(final_result)exmaple:
fromlangchain_deepseekimportChatDeepSeekfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlangchain_core.output_parsersimportStrOutputParser# 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.链式调用大模型
fromlangchain_deepseekimportChatDeepSeekfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlangchain_core.output_parsersimportStrOutputParser# 1. 定义模型model=ChatDeepSeek(model="deepseek-chat")# 2. 定义消息 列表messages=[SystemMessage(content="你是一个C++学习助手,请用简洁中文回答。"),HumanMessage(content="一加一等于几?")]parser=StrOutputParser()chain=model|parser result=chain.invoke(messages)print(result)运行结果
一加一等于二。2.三种构建链的方式
第一种:管道符 |
这是最常用的写法。
chain=model|parser第二种:RunnableSequence
手动创建:
fromlangchain_core.runnablesimportRunnableSequence chain=RunnableSequence(first=model,last=parser)第三种:pipe 方法
chain=model.pipe(parser)三:LangChain 底层:Runnable 和 LCEL
1.Runnable
Runnable 可以理解成 LangChain 里面的一个标准接口。
ChatDeepSeek 继承 BaseChatDeepSeek BaseChatDeepSeek 继承 Runnable 接口model.invoke(...)parser.invoke(...)chain.invoke(...)对象虽然功能不同,但它们都遵守同一套调用规范
不管你是模型、解析器、Prompt、还是链,只要你是 Runnable,就可以用统一方式运行
LangChain 解决了 原生大模型切换困难 的问题
Runnable 接口:
| 方法 | 作用 |
|---|---|
invoke() | 单次调用,一个输入对应一个输出 |
batch() | 批处理,多个输入一起处理 |
stream() | 流式输出,一个字/词/token 慢慢返回 |
ainvoke() | 异步调用 |
astream() | 异步流式输出 |
2.LCEL -LangChain Expression Language
LangChain 表达式语言
LCEL让各个组件进行管道输出
chain=prompt|model|parser result=chain.invoke({"topic":"C++ RAII"})前一个组件的输出,自动作为后一个组件的输入底层:
chain :
看起来好像只是把两个对象用 | 连起来,但底层其实生成了一个新的对象:
RunnableSequence 可运行序列 chain = model|parser 理解成: chain = RunnableSequence(first=model,last=parser)林外:chain 自己也是一个 Runnable
四:进阶使用Langchain的接口
init_chat_model()
这个函数是 ChatDeepSeek()的进阶替代。
代码:
fromlangchain.chat_modelsimportinit_chat_modelfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlangchain_core.output_parsersimportStrOutputParser# 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
代码:
fromlangchain_deepseekimportChatDeepSeekfromlangchain.chat_modelsimportinit_chat_modelfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlangchain_core.output_parsersimportStrOutputParser# 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 更多用于: |
日志追踪 链路观测 调试分析 LangSmith 追踪六:带默认参数的可配置模型
初始化时已经有默认模型,但调用时想临时改参数。
我们需要知道的一个前提就是:
LangChain 默认不会让你随便在运行时修改已有属性。
也就是你在init_chat_model定义的参数,在后面就绝对不能修改!!!
configurable_fields 和 config_prefix
这个其实就是让标记init_chat_model 里面的参数,告诉我们哪些可以修改
字面意思就是给那些上锁的门解锁
configurable_fields:声明哪些字段允许运行时修改
config_prefix:给配置项加前缀
老师还加了一个参数:
上代码:
fromlangchain_deepseekimportChatDeepSeekfromlangchain.chat_modelsimportinit_chat_modelfromlangchain_core.messagesimportSystemMessage,HumanMessagefromlangchain_core.output_parsersimportStrOutputParser# 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
代码:
fromlangchain_ollamaimportChatOllama 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 计费 | 主要消耗本机算力 |