第02章:模型的创建与调用 (中)

目录

5、模型的调用

[5.1 invoke()](#5.1 invoke())

[5.1.1 invoke()说明](#5.1.1 invoke()说明)

[5.1.2 输入参数详解](#5.1.2 输入参数详解)

[5.1.3 返回值详解](#5.1.3 返回值详解)

[5.2 流式调用](#5.2 流式调用)

[5.3 批量调用](#5.3 批量调用)

[5.3.1 一次性接收所有响应](#5.3.1 一次性接收所有响应)

[5.3.2 按完成顺序接收响应](#5.3.2 按完成顺序接收响应)

[5.4.3 性能对比](#5.4.3 性能对比)

[5.4 异步调用](#5.4 异步调用)

ainvoke

astream()

abatch()

[5.5 如何处理API调用失败](#5.5 如何处理API调用失败)


5、模型的调用

在 LangChain 中,模型调用(Invocation)是指通过特定方法触发大语言模型生成输出的过程。根据不 同的应用场景和需求,LangChain 提供了几种核心的调用方式,主要是 invoke() 、 stream() 和 batch() 方法,以及它们的异步版本 ainvoke() 、 astream() 和 abatch() ,下面将系统地介绍这些方 法。

  • invoke() :阻塞式,一次性返回完整结果问答、批处理任务、无需实时反馈的场景。
  • ainvoke() :非阻塞式,提高系统吞吐量高并发Web应用、IO密集型任务。
  • stream() :流式输出,实时返回每个token聊天机器人、长文本生成、需要提升用户体验的交互 应用。
  • asteam() :非阻塞式,提高系统吞吐量高并发Web应用、IO密集型任务。
  • batch() :批量处理多个输入高并发场景,需要同时处理大量请求。
  • abatch() :非阻塞式,提高系统吞吐量高并发Web应用、IO密集型任务。

5.1 invoke()

invoke() 是 LangChain 中最核心的方法,它的工作模式是阻塞式的,即程序会等待模型完全生成整个响 应后,再一次性将结果返回给用户。

5.1.1 invoke()说明

简单来说, invoke 方法的作用就是:

    1. 接收你的输入(问题、指令、对话历史等)
    1. 发送给 LLM 模型(如 GPT-4、Llama、Claude 等)
    1. 返回模型的响应(文本回复 + 元数据信息)

基本语法:

复制代码
response = model.invoke(input, config=None)

参数详解:

5.1.2 输入参数详解

invoke方法非常灵活,支持三种形式的输入: 文本输入 、 字典列表 、 消息对象列表 。

1、文本输入(最简单)

简单的一次性问答,直接传入一个问题或指令。

✅适用场景:快速测试,不需要保留对话历史的简单生成任务。

❌缺点:无法设置系统提示(system prompt),无法传递对话历史

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")

model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  #model_provider="deepseek",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)
# 向模型发送单条数据
response = model.invoke("你好,用一句话回答")
# 打印响应
print(response)

2、字典列表(推荐,最灵活)

创建字典列表组成消息。一条消息通常包含 role(角色) 、 content(内容) 等信息。

✅适用场景:可以设置系统提示,表达多轮对话历史,JSON 兼容,易于序列化和网络传输,生产环境 推荐。

❌缺点:代码稍微多一点(但更清晰)

复制代码
messages = [
{"role": "system", "content": "系统提示"},
{"role": "user", "content": "用户消息"},
{"role": "assistant", "content": "AI回复"}, # 可选,用于对话历史
{"role": "user", "content": "继续提问"}
]

角色说明:

"user"和 "human"有时可以互换,但遵循你选择的主要模型提供商(如OpenAI)的惯例使用 "user"是最稳妥的做法。

举例1

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")

model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

messages1 = [
{"role": "system", "content": "你是一个非常友好的AI助手"},
{"role": "user", "content": "你好,我叫小明"},
]
# 第一次对话
response1 = model.invoke(messages1)
# 打印响应
print(f"AI的回复1:{response1.content}")

messages2 = [
{"role": "user", "content": "我叫什么名字?"}
]
# 第二次对话
response2 = model.invoke(messages2)
# 打印响应
print(f"AI的回复2:{response2.content}")

举例2:多轮对话(带历史)

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")

# 使用字典格式构建消息
messages = [
{"role":"system","content":"你是一个专业的数学老师。"},
{"role":"user","content":"2 + 3 * 2 = ?"},
{"role":"assistant","content":"8"},
{"role":"user","content":"我刚才问了什么问题?"}
]
model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 向模型发送单条数据
response = model.invoke(messages)
# 打印响应
print(response)

AI的回复:你刚才问的是:**"2 + 3 * 2 = ?

举例3:如果不传递历史,AI 会"失忆"

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")

model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

messages1 = [
{"role": "system", "content": "你是一个非常友好的AI助手"},
{"role": "user", "content": "你好,我叫小明"},
]
# 第一次对话
response1 = model.invoke(messages1)
# 打印响应
print(f"AI的回复1:{response1.content}")

messages2 = [
{"role": "user", "content": "我叫什么名字?"}
]
# 第二次对话
response2 = model.invoke(messages2)
# 打印响应
print(f"AI的回复2:{response2.content}")

作为对比,传递记忆:

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

conversation = [
{"role": "system", "content": "你是一个非常友好的AI助手"},
{"role": "user", "content": "你好,我叫小明"}
]
# 第一次对话
response1 = model.invoke(conversation)
# 打印响应
print(f"AI的回复1:{response1.content}")
# 添加记忆
conversation.append({"role": "assistant", "content": response1.content})
conversation.append({"role": "user", "content": "我叫什么名字?"})
# 第二次对话
response2 = model.invoke(conversation)
print(f"AI的回复2:{response2.content}")

3、消息对象列表

使用内置的消息类(如 SystemMessage, HumanMessage, AIMessage),将消息对象列表输入模型。

✅适用场景:需要类型检查(针对大型项目)、IDE 自动补全的场景

❌缺点:代码较长、不如字典简洁、难以序列化(JSON)

举例1:

复制代码
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用消息对象格式构建消息
messages = [
SystemMessage("你是一个专业的数学老师。"),
HumanMessage("2 + 3 * 2 = ?"),
AIMessage("8"),
HumanMessage("我刚才问什么问题了?")
]
response = model.invoke(messages)
# 打印响应
print(f"AI的回复:{response.content}")

举例2

复制代码
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

messages = [
SystemMessage(content="你是一个 Python 专家"),
HumanMessage(content="什么是生成器?"),
]
response = model.invoke(messages)
# print(response)
# 继续对话
messages.append(AIMessage(content=response.content))
messages.append(HumanMessage(content="能给个例子吗?"))
response1 = model.invoke(messages)
print(response1)

5.1.3 返回值详解

nvoke 返回一个 AIMessage对象 ,源码如下:

复制代码
def invoke(
self,
input: LanguageModelInput,
config: RunnableConfig | None = None,
*,
stop: list[str] | None = None,
**kwargs: Any,
) -> AIMessage:

举例:

复制代码
from rich import print as rprint
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用字典格式构建消息
response = model.invoke([HumanMessage("2 + 3 * 2 = ?")])
# 打印响应
print(type(response))
# <class 'langchain_core.messages.ai.AIMessage'>
rprint(response)

AIMessage中包含丰富的信息,以上面案例的输出为例,整体说明如下

复制代码
AIMessage(
    # 模型真正返回给用户的内容
    content='根据运算优先级,先算乘法再算加法:3 × 2 = 6,然后 2 + 6 = 8。所以答案是8。',

    # OpenAI/DeepSeek 等厂商返回的一些额外信息
    additional_kwargs={
        # 是否拒绝回答(正常回答时为 None)
        'refusal': None,

        # 推理模型(Thinking 模型)的思考过程
        # 注意:只有开启 thinking 的模型才会有
        'reasoning_content': (
            '我们被问到:"2 + 3 * 2 = ?" '
            '这是一个简单的算术表达式。'
            '根据运算顺序,乘法的优先级高于加法,'
            '所以先计算3 * 2 = 6,然后加上2得到8。'
            '所以答案是8。'
        )
    },

    # 本次调用的一些元数据
    response_metadata={

        # Token 使用情况
        'token_usage': {

            # 输出 Token(包含思考 Token)
            'completion_tokens': 102,

            # 输入 Token
            'prompt_tokens': 14,

            # 总 Token
            'total_tokens': 116,

            # 输出 Token 详细信息
            'completion_tokens_details': {

                # 预测 Token(部分模型支持)
                'accepted_prediction_tokens': None,

                # 音频 Token(语音模型使用)
                'audio_tokens': None,

                # Thinking Token(思考 Token)
                'reasoning_tokens': 68,

                # 被拒绝的预测 Token
                'rejected_prediction_tokens': None
            },

            # Prompt Token 详情
            'prompt_tokens_details': {
                'audio_tokens': None,
                'cached_tokens': 0      # 命中缓存的 Token 数
            },

            # Prompt Cache 命中数量
            'prompt_cache_hit_tokens': 0,

            # Prompt Cache 未命中数量
            'prompt_cache_miss_tokens': 14
        },

        # 模型提供商
        'model_provider': 'deepseek',

        # 实际调用的模型名称
        'model_name': 'deepseek-v4-flash',

        # 模型版本指纹(用于定位具体模型版本)
        'system_fingerprint': 'fp_8b330d02d0_prod0820_fp8_kvcache_20260402',

        # 本次请求唯一 ID
        'id': '928f644d-82a9-46be-a12c-8a2ea263a977',

        # 结束原因
        # stop:正常结束
        # length:达到最大 Token 数
        # tool_calls:等待工具调用
        'finish_reason': 'stop',

        # 每个 Token 的概率(开启 logprobs 时才有)
        'logprobs': None
    },

    # LangChain 本次运行的唯一 ID
    id='lc_run--019f12c5-a88d-77f1-8fa0-be986f0220bd-0',

    # 模型请求调用的工具(Function Calling)
    # 当前为空,说明没有调用工具
    tool_calls=[],

    # 非法或解析失败的工具调用
    invalid_tool_calls=[],

    # LangChain 统一封装后的 Token 使用信息
    usage_metadata={

        # 输入 Token
        'input_tokens': 14,

        # 输出 Token
        'output_tokens': 102,

        # 总 Token
        'total_tokens': 116,

        # 输入 Token 详情
        'input_token_details': {
            'cache_read': 0
        },

        # 输出 Token 详情
        'output_token_details': {
            # Thinking Token 数量
            'reasoning': 68
        }
    }
)

总结一下:

1. 核心内容与基本信息

  • content : 模型生成的文本回答。这是你最关心的核心输出。
  • id : 本次运行在 LangChain 内部生成的唯一标识符(Run ID)。
  • additional_kwargs : 包含特定供应商的额外参数。
  • refusal : 如果模型拒绝回答(涉及敏感政策),此处会显示拒绝原

2. 消耗统计 (Token Usage)

  • 这部分决定了你这一行输入操作花了多少钱:
  • prompt_tokens / input_tokens : 输入 Token 数。你发送给模型的问题长度。
  • completion_tokens / output_tokens : 输出 Token 数。模型回答生成的长度。
  • total_tokens : 总消耗。 两者之和。
  • reasoning_tokens : 推理 Token 数。 如果是 O1/O3 等推理模型,这里会显示它在"思考"时消耗 的 Token。
  • cached_tokens : 缓存命中的 Token 数。重复提问时,如果命中了模型商的缓存,这部分费用通 常更低。

3. 响应元数据 (Response Metadata)

  • 这部分是 API 返回的原始详细信息:
  • model_name : 实际调用的模型具体版本(如 gpt-5.4-mini )。
  • model_provider : 模型供应商(如 openai )。
  • finish_reason : 生成停止的原因。 stop : 正常回答结束。 length : 达到最大 Token 限制被截断。
  • system_fingerprint : 系统指纹,用于追踪模型后端的配置变更

4. 性能与延迟 (Latency Checkpoint)

  • total_duration_ms : 总耗时。从请求发出到完全收到的总时间(259ms)。
  • user_visible_ttft_ms : 首字到达时间。用户看到第一个字跳出来等待的时间(194ms),这是体 感快慢的关键。
  • engine_ttft_ms : 引擎层面的首字到达时间(36ms)
  • engine_ttlt_ms : 引擎生成最后一个字的时间(100ms)。
  • pre_inference_ms : 推理前处理耗时。包括安全审核、Token 化等预处理(86ms)。
  • service_tbt_ms : Time Between Tokens。字与字之间生成的间隔时间,决定了打字机效果是否 丝滑。

5. 工具调用信息

  • tool_calls : 结构化工具调用列表。如果模型决定调用某个 Python 函数或搜索工具,参数会在这 里。
  • invalid_tool_calls : 格式错误的工具调用尝试

举例:访问所有信息

复制代码
from rich import print as rprint
from langchain_core.messages import SystemMessage, HumanMessage, AIMessage
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用字典格式构建消息
response = model.invoke("用一句话解释什么是 AI")
# 1. 获取回复内容
print("AI 回复:", response.content)
# 2. 获取响应元数据
metadata = response.response_metadata
print(f"使用的模型: {metadata['model_name']}")
print(f"结束原因: {metadata['finish_reason']}")
print(f"模型提供商:{metadata['model_provider']}\n")
# 3. 获取 Token 使用情况
usage = metadata.get('token_usage', {})
print(f"输入 tokens: {usage.get('prompt_tokens')}")
print(f"输出 tokens: {usage.get('completion_tokens')}")
print(f"总计 tokens: {usage.get('total_tokens')}")
# 4. 获取消息 ID
print(f"消息 ID: {response.id}")

AI 回复: AI是让机器模仿人类学习、推理和决策,从而执行任务的技术(简单说就是让计算机像人一样思考和解决问题)。
使用的模型: deepseek-v4-flash
结束原因: stop
模型提供商:deepseek

输入 tokens: 9
输出 tokens: 142
总计 tokens: 151
消息 ID: lc_run--019f12d1-74aa-7fe1-a4a3-d224ec004394-0

5.2 流式调用

invoke 和 stream 有什么区别?

invoke() :同步调用,在模型输出完成后一次性获取响应,对于输出文本很长的场景,用户体验 不好。

stream() :流式调用,实时返回响应片段。调用后,返回一个 迭代器(iterator) ,可以通过循环 来实时处理每一个新生成的chunk内容块。

注意:流式输出依赖于模型供应商对于流式输出的支持

举例:

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用字典格式构建消息
for chunk in model.stream("写一首七言律诗,总结大模型的发展"):
 print(chunk.text, end="", flush=True) # 逐token输出

输出不再是整段返回,而是流式输出。

stream()方式的优点:

  • 响应速度更快 --- 用户不必等待完整输出
  • 交互体验更流畅 --- 尤其在长文本或复杂推理场景下
  • 可实时展示模型思考过程

5.3 批量调用

batch() 方法允许你一次性 发送一组请求 (含多条独立请求),模型会在后台 并行处理 ,然后返回 所 有结果的列表 。

与逐个顺序调用(invoke)相比,能大幅 减少网络往返开销 和 等待时间 ,显著提升性能、降低成本。

适用场景:文档摘要、批量问答、数据预处理、多样本分类等。

5.3.1 一次性接收所有响应

batch()特点是等待所有请求处理完毕,按原始输入顺序返回结果列表。

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用字典格式构建消息
messages = [
"你好,你是谁?",
"2 + 3 * 5 = ?",
"中国首都在哪里?"
]
responses = model.batch(messages)
for response in responses:
 print(response)

5.3.2 按完成顺序接收响应

当输入列表很大或单个模型调用耗时差异显著时, batch_as_completed() 允许应用在收到第一个结果 后立即返回响应,而不会等待批次内所有任务完成才响应。即batch_as_completed() 每个请求完成后立 即 yield 结果, 结果可能乱序 。

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 使用字典格式构建消息
messages = [
"你好,你是谁?",
"2 + 3 * 5 = ?",
"中国首都在哪里?"
]
responses = model.batch_as_completed(messages)
for response in responses:
 print(response)

5.4.3 性能对比

使用batch():

复制代码
import os
from langchain.chat_models import init_chat_model
from dotenv import load_dotenv
# 从.env文件中加载环境变量
load_dotenv(override=True)

# 从环境变量读取配置
DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)

# 准备多个输入
inputs = [
"翻译成英文:春天来了",
"翻译成英文:夏天很热",
"翻译成英文:秋天落叶",
"翻译成英文:冬天下雪"
]
# ✅ 批量调用(高效)
import time
start = time.time()
responses = model.batch(inputs)
batch_time = time.time() - start
print("批量调用结果:")
for i, response in enumerate(responses):
 print(f"{i+1}. {response.content}")
print(f"耗时: {batch_time:.2f}秒\n")

批量调用结果:

  1. Spring is coming.

  2. Summer is very hot.

  3. Autumn leaves

  4. Snow in winter.

耗时: 3.57秒

使用循环调用invoke():

复制代码
inputs = [
"翻译成英文:春天来了",
"翻译成英文:夏天很热",
"翻译成英文:秋天落叶",
"翻译成英文:冬天下雪"
]
start = time.time()
loop_responses = []
for inp in inputs:
 response = model.invoke(inputs)
 loop_responses.append(response)
loop_time = time.time() - start
for i, response in enumerate(responses):
 print(f"{i+1}. {response.content}")
print(f"循环调用耗时: {loop_time:.2f}秒")
print(f"批量调用节省: {((loop_time - batch_time) / loop_time * 100):.1f}%")
  1. Spring is coming.

  2. Summer is very hot.

  3. Autumn leaves

  4. Snow in winter.

循环调用耗时: 14.04秒

批量调用节省: 74.6%

5.4 异步调用

复习:同步 vs 异步

同步(sync) :

  • 概念:发起一个任务之后,需要 等待该任务完成后 ,才能继续执行后续任务。
  • 表现:当前执行流 会被『阻塞』 。

异步(async) :

  • 概念:发起一个任务之后, 不必等该任务完成 ,就可以继续执行其他任务。 备注:虽然不必等待任务完成,但任务完成后,仍然可以通过特定方式获取结果。
  • 表现:当前执行流 不会被『阻塞』 。

举例:

在LangChain框架中,异步方法(ainvoke、astream、abatch)与它们的同步版本(invoke、 stream、batch)相比,具备如下特点:

  • 避免阻塞主线程 :同步调用会阻塞程序执行,而异步方法让应用程序在等待API响应时保持响应 性。
  • 优化资源利用 :异步操作可以更高效地利用系统资源,减少空闲等待时间

ainvoke

复制代码
"""
@Author: shkstart
@Desc:
"""

import asyncio
import os
import time

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

# 从 .env 文件中加载环境变量
load_dotenv(override=True)

DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)



async def demo_async_invoke():
    """演示 ainvoke 的异步(非阻塞)效果"""

    print("=== 演示:ainvoke 的异步(非阻塞)效果 ===")

    # 记录开始时间
    start_time = time.perf_counter()

    print("程序开始...")

    # 1. 创建异步任务
    print(">>> 发起异步模型调用 (ainvoke)...")
    async_task = asyncio.create_task(
        model.ainvoke("用一句话解释人工智能。")
    )

    # 2. 并行执行其他任务
    print(">>> 模型请求已在后台发送,继续执行本地逻辑...")

    for i in range(3):
        await asyncio.sleep(1)  # 异步等待,不阻塞事件循环
        print(
            f">>> 正在执行第{i + 1}个任务... "
            f"(已耗时 {time.perf_counter() - start_time:.2f}s)"
        )

    # 3. 获取模型结果
    print(">>> 本地任务完成,检查模型状态...")

    response = await async_task

    end_time = time.perf_counter()

    print(f">>> 模型返回: {response.content}")
    print(f"=== 总运行耗时: {end_time - start_time:.2f}s ===")


async def main():
    """主函数"""
    await demo_async_invoke()


if __name__ == "__main__":
    asyncio.run(main())

=== 演示:ainvoke 的异步(非阻塞)效果 ===
程序开始...
>>> 发起异步模型调用 (ainvoke)...
>>> 模型请求已在后台发送,继续执行本地逻辑...
>>> 正在执行第1个任务... (已耗时 1.00s)
>>> 正在执行第2个任务... (已耗时 2.00s)
>>> 正在执行第3个任务... (已耗时 3.01s)
>>> 本地任务完成,检查模型状态...
>>> 模型返回: 人工智能是研究如何让计算机模拟人类智能行为(如学习、推理、感知和决策)的科学技术。
=== 总运行耗时: 3.01s ===

说明:在.py文件中执行,而非jupyter中执行。

astream()

复制代码
"""
@Author: shkstart
@Desc:
"""

import asyncio
import os
import time

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

# 从 .env 文件中加载环境变量
load_dotenv(override=True)

DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")


model = init_chat_model(
  model="deepseek:deepseek-v4-flash",
  api_key=DEEPSEEK_API_KEY,
  base_url=DEEPSEEK_BASE_URL)


async def demo_async_stream():
    """演示异步流式调用的非阻塞特性"""

    print("=== 演示:astream 的异步(非阻塞)效果 ===")

    # 记录开始时间
    start_time = time.perf_counter()

    print("程序开始...")

    # 1. 发起异步流式请求
    # 注意:此时请求已发出,返回的是一个异步生成器
    print(">>> 发起异步流式调用 (astream)...")
    stream_resp = model.astream(
        "请用一句话解释机器学习的基本概念。"
    )

    # 2. 在等待流式响应的同时,执行其他任务
    print(">>> 流式请求已发送,程序无需等待,继续执行其他异步任务...")

    for i in range(3):
        # asyncio.sleep 不会阻塞事件循环
        await asyncio.sleep(1)
        print(
            f">>> 正在执行第{i + 1}个任务... "
            f"(已耗时 {time.perf_counter() - start_time:.2f}s)"
        )

    # 3. 开始处理流式结果
    print(">>> 模拟任务已完成,开始读取缓冲区中的流式结果...")

    print(">>> 流式输出: ", end="", flush=True)

    async for chunk in stream_resp:
        # LangChain 的消息块通常通过 .content 获取内容
        content = chunk.content if hasattr(chunk, "content") else str(chunk)
        print(content, end="", flush=True)

    end_time = time.perf_counter()

    print("\n>>> 流式输出结束\n")
    print(f"=== 总运行耗时: {end_time - start_time:.2f}s ===")


async def main():
    """主函数"""
    await demo_async_stream()


if __name__ == "__main__":
    asyncio.run(main())

=== 演示:astream 的异步(非阻塞)效果 ===

程序开始...

>>> 发起异步流式调用 (astream)...

>>> 流式请求已发送,程序无需等待,继续执行其他异步任务...

>>> 正在执行第1个任务... (已耗时 1.00s)

>>> 正在执行第2个任务... (已耗时 2.00s)

>>> 正在执行第3个任务... (已耗时 3.00s)

>>> 模拟任务已完成,开始读取缓冲区中的流式结果...

>>> 流式输出: 机器学习的基本概念是:让计算机通过分析大量数据自动发现规律,并利用这些规律对未知数据做出预测或决策。

>>> 流式输出结束

=== 总运行耗时: 4.55s ===

abatch()

复制代码
"""
@Author: shkstart
@Desc:
"""

import asyncio
import os
import time

from dotenv import load_dotenv
from langchain.chat_models import init_chat_model

# 从 .env 文件中加载环境变量
load_dotenv(override=True)

DEEPSEEK_API_KEY = os.getenv("DEEPSEEK_API_KEY")
DEEPSEEK_BASE_URL = os.getenv("DEEPSEEK_BASE_URL")

model = init_chat_model(
    model="deepseek:deepseek-v4-flash",
    api_key=DEEPSEEK_API_KEY,
    base_url=DEEPSEEK_BASE_URL,
)


async def demo_async_batch():
    """演示 abatch 的异步(非阻塞)效果"""

    print("=== 演示:abatch 的异步(非阻塞)效果 ===")

    start_time = time.perf_counter()

    print("程序开始...")

    # 准备批量输入
    questions = [
        "用一句话说明深度学习与传统机器学习的区别",
        "中国首都在哪里?",
    ]

    # 1. 发起异步批量请求
    print(">>> 发起异步批量调用 (abatch)...")
    batch_task = asyncio.create_task(
        model.abatch(questions)
    )

    # 2. 执行其他异步任务
    print(">>> 批量任务已在后台运行,主程序继续执行...")

    for i in range(3):
        await asyncio.sleep(1)
        print(
            f">>> 正在执行第{i + 1}个任务... "
            f"(已耗时 {time.perf_counter() - start_time:.2f}s)"
        )

    # 3. 获取批量结果
    print(">>> 其他任务已完成,现在获取后台批量任务的结果...")

    responses = await batch_task

    end_time = time.perf_counter()

    for response in responses:
        content = (
            response.content
            if hasattr(response, "content")
            else str(response)
        )
        print(f">>> 响应内容: {content}")

    print(f"=== 总运行耗时: {end_time - start_time:.2f}s ===")


async def main():
    """主函数"""
    await demo_async_batch()


if __name__ == "__main__":
    asyncio.run(main())

=== 演示:abatch 的异步(非阻塞)效果 ===

程序开始...

>>> 发起异步批量调用 (abatch)...

>>> 批量任务已在后台运行,主程序继续执行...

>>> 正在执行第1个任务... (已耗时 1.00s)

>>> 正在执行第2个任务... (已耗时 2.00s)

>>> 正在执行第3个任务... (已耗时 3.00s)

>>> 其他任务已完成,现在获取后台批量任务的结果...

>>> 响应内容: 一句话:**深度学习通过多层神经网络自动从数据中学习特征,而传统机器学习通常依赖人工设计特征。**

>>> 响应内容: 中国首都是北京。

=== 总运行耗时: 3.00s ===

5.5 如何处理API调用失败

使用 try-except 块捕获异常:

复制代码
try:
response = model.invoke("Hello")
    print(response.content)
except ValueError as e:
    print(f"配置错误: {e}")
except ConnectionError as e:
    print(f"网络错误: {e}")
except Exception as e:
    print(f"未知错误: {e}")