LangChain LangGraph
Module 1 Module 2 Module 3
Module 1 · 基础能力
1 1.1a 基础模型
2 1.1b Prompting
3 1.2a Tools
4 1.2b Web Search
5 1.3 Memory
6 1.4 Multimodal
7 1.5 Personal Chef
SUM Module Summary
HomeLangChainModule 1 · 基础能力1.1a 基础模型
📓 Notebook 📖 Explained
LANGCHAIN MODULE 1 · LESSON 1.1a

LangChain 基础模型
init_chat_model · create_agent · 流式输出

init_chat_model 初始化任意聊天模型,用 create_agent 构建 Agent,再用流式输出让响应实时显示。

1 什么是 LangChain 基础模型层?核心概念总览

LangChain 的 Module 1 从最基础的能力入手:如何调用大语言模型(LLM)?如何构建一个能记住对话、会调用工具的 Agent?

这一节(1.1_foundational_models)关注的是最基础的三件事:

Module 1 整体架构:从模型到 Agent

init_chat_model
初始化 LLM
create_agent
构建 Agent
invoke / stream
执行 / 流式输出
课程背景

本课程使用 DeepSeek 作为主要 LLM(也支持 Gemini 等)。DeepSeek 提供兼容 OpenAI API 格式的接口,因此在 LangChain 里用 model_provider="openai" 加上自定义 base_url 即可接入。这种"兼容层"设计让你可以用同一套 LangChain 代码切换不同厂商的模型。

2 init_chat_model:统一的模型初始化接口

LangChain 提供 init_chat_model 函数,统一了不同 LLM 提供商的初始化方式。你只需要传入模型名称、提供商标识符和 API 密钥,就能得到一个标准的聊天模型对象。

基础用法:直接初始化 Google Gemini

最简单的用法是直接用 LangChain 官方集成的模型类:

from langchain_google_genai import ChatGoogleGenerativeAI

# 直接初始化 Gemini 模型
model = ChatGoogleGenerativeAI(model="gemini-2.5-flash-lite")

# 直接调用:注意这是 model.invoke,不是 agent.invoke
response = model.invoke("What's the capital of the Moon?")
print(response.content)
注意区别

model.invoke() 直接调用原始模型,返回的是 AIMessage 对象,通过 .content 取文本内容。而 agent.invoke() 返回的是包含完整消息历史的字典 {"messages": [...]}。两者的接口不同。

封装 DeepSeek 的工厂函数

notebook 里定义了一个 deepseek_model() 工厂函数,封装了所有 DeepSeek 相关的初始化细节:

from dotenv import load_dotenv
load_dotenv()  # 从 .env 文件加载 DEEPSEEK_API_KEY 等环境变量

import os
from langchain.chat_models import init_chat_model

DEEPSEEK_MODEL = "deepseek-v4-flash"
DEEPSEEK_BASE_URL = "https://api.deepseek.com"

def deepseek_model(model: str = DEEPSEEK_MODEL, max_tokens=200, **kwargs):
    return init_chat_model(
        model=model,
        model_provider="deepseek",   # 或 "openai"(DeepSeek 兼容 OpenAI 格式)
        max_tokens=max_tokens,
        base_url=DEEPSEEK_BASE_URL,
        api_key=os.environ["DEEPSEEK_API_KEY"],
        **kwargs
    )

使用工厂函数初始化模型:

model = deepseek_model(temperature=1)
print(model)  # 打印模型对象,确认配置

# 直接调用模型(不经过 Agent)
response = model.invoke("what is 1+1?")
print(response.content)  # → "The answer is 2."
执行输出
ChatDeepSeek(model_name='deepseek-v4-flash', temperature=1.0, ...)

The answer is 2.

init_chat_model 的关键参数

参数说明示例值
model 模型 ID 字符串 "deepseek-v4-flash"
model_provider LangChain 路由到哪个 provider 的适配器 "deepseek" / "openai" / "google-genai"
max_tokens 最大输出 token 数量 200 / 1000
temperature 输出随机性(0=确定性,1=最随机) 0 / 1
base_url 自定义 API 端点(DeepSeek/本地模型用) "https://api.deepseek.com"

3 create_agent:用模型构建 Agent

create_agent 是 LangChain 提供的高层 API,它把一个聊天模型包装成一个完整的 LangGraph Agent(底层是一个带 checkpointer 的 StateGraph)。

Agent 相比原始模型多了什么?

from langchain.agents import create_agent

# 最基础的用法:只传入模型
agent = create_agent(model=deepseek_model())
create_agent 的底层原理

create_agent 在底层构建了一个 LangGraph StateGraph,包含一个 model 节点(调用 LLM)和一个 tools 节点(执行工具调用)。它们通过条件边(conditional edge)连接:模型输出工具调用时走向 tools 节点,否则结束。这就是 ReAct(Reasoning + Acting)模式的实现。

4 Agent 的 invoke:同步调用与响应结构

调用 Agent 用 agent.invoke({"messages": [...]}),输入是一个包含 messages 键的字典,消息可以用 HumanMessage 对象或字典格式传入。

使用 HumanMessage 对象

from langchain.messages import HumanMessage

agent = create_agent(deepseek_model())

messages = [
    {"role": "user",      "content": "what is 1+1?"},
    {"role": "assistant", "content": "2"},
    {"role": "user",      "content": "how about times 5?"}
]

response = agent.invoke({"messages": messages})
print(response['messages'][-1].content)
执行输出
If you take the result of 1+1 (which is 2) and multiply it by 5, you get 10.

response 的结构解析

Agent 的响应是一个字典,核心键是 messages,它是一个消息列表,包含完整的对话历史:

print(len(response['messages']))  # → 4(3 条输入 + 1 条 AI 响应)

for msg in response['messages']:
    print(msg.content)
执行输出
what is 1+1?
2
how about times 5?
If you take the result of 1+1 (which is 2) and multiply it by 5, you get 10.
常用取值方式

通常只需要最后一条 AI 消息:response['messages'][-1].content。这是最常见的取值模式——取消息列表的最后一项,再取 .content 属性获取文本内容。

5 流式输出(stream_mode="messages"):逐 Token 实时打印

agent.invoke() 需要等模型全部生成完才能看到结果。agent.stream() 则让模型每生成一个 token 就立即推送,实现"打字机效果"——这在 UI 交互和长响应场景下体验要好得多。

基础流式用法

messages = [{"role": "user", "content": "Tell me all about Luna City, the capital of the Moon"}]

for token, metadata in agent.stream(
    {"messages": messages},
    stream_mode="messages"   # 关键:按消息/token 流式推送
):
    if token.content:          # 过滤空 token(工具调用消息没有 content)
        print(token.content, end="", flush=True)  # 不换行,实时打印
流式输出效果
Luna City is a fictional lunar capital featured in sci-fi.

stream_mode 参数说明

stream_mode推送时机适合场景
"messages" 每生成一个 token/消息片段就推送 UI 打字机效果、实时响应显示
"values" 每完成一个 LangGraph 节点就推送完整 State 监控 Agent 内部步骤状态
"updates" 每个节点完成后推送该节点的 State 变更 调试节点输出

6 metadata 元数据:了解 Agent 内部执行信息

在流式循环里,agent.stream() 同时返回 token(消息内容)和 metadata(执行元数据)。metadata 包含 LangGraph 内部运行时信息,对调试和追踪非常有用。

for token, metadata in agent.stream(
    {"messages": messages},
    stream_mode="messages"
):
    # 第一个 token 时打印 metadata
    print(metadata)
    break
metadata 内容示例
{
  'langgraph_step': 1,
  'langgraph_node': 'model',
  'langgraph_triggers': ('branch:to:model',),
  'ls_provider': 'deepseek',
  'ls_model_name': 'deepseek-v4-flash',
  'ls_model_type': 'chat',
  'ls_max_tokens': 500
}

metadata 关键字段解读

字段含义
langgraph_step 当前是 LangGraph 执行的第几步(从 1 开始)
langgraph_node 当前正在执行的节点名称(如 'model''tools'
langgraph_triggers 触发当前节点执行的来源(边/事件名称)
ls_provider 实际使用的 LLM 提供商
ls_model_name 实际使用的模型 ID
实际应用

在生产环境中,metadata 常用于:① 日志记录和监控(追踪每次调用使用了哪个模型);② 调试(查看 Agent 执行到了哪个节点出了问题);③ 计费分析(通过 ls_model_name 统计各模型的使用量)。

7 完整代码与关键概念速查

从零开始的完整示例

from dotenv import load_dotenv
load_dotenv()

import os
from langchain.chat_models import init_chat_model
from langchain.agents import create_agent
from langchain.messages import HumanMessage

# 1. 初始化模型
def deepseek_model(**kwargs):
    return init_chat_model(
        model="deepseek-v4-flash",
        model_provider="deepseek",
        api_key=os.environ["DEEPSEEK_API_KEY"],
        base_url="https://api.deepseek.com",
        max_tokens=500,
        **kwargs
    )

# 2. 构建 Agent
agent = create_agent(deepseek_model())

# 3. 同步调用
response = agent.invoke({"messages": [HumanMessage(content="Hello!")]})
print(response['messages'][-1].content)

# 4. 流式调用
for token, _ in agent.stream(
    {"messages": [{"role": "user", "content": "Tell me a joke"}]},
    stream_mode="messages"
):
    if token.content:
        print(token.content, end="", flush=True)

本节知识全景总结

Module 1 Lesson 1.1a 核心概念地图
init_chat_model
  • • 统一不同厂商模型的初始化接口
  • • 通过 model_provider 指定适配器
  • • 支持 DeepSeek、OpenAI、Google 等
create_agent
  • • 把模型包装成 LangGraph Agent
  • • 内置消息历史管理
  • • 支持工具调用(ReAct 模式)
invoke vs stream
  • invoke:等待完整响应,返回消息列表
  • stream:逐 token 推送,打字机效果
  • • 用 token.content 过滤空消息
响应结构
  • response['messages']:完整消息历史
  • response['messages'][-1].content:AI 最新回复
  • • metadata 含节点/模型执行信息