作者:互联网 时间: 2026-07-11 09:05:52
在基于大模型开发应用时,如何向 LLM 发送请求、接收回复直接决定程序性能与用户体验。LangChain 基于 init_chat_model 封装了三套核心同步调用接口 invoke、stream、batch,同时配套异步版本适配高并发服务场景。三者底层共用同一套消息结构,但在返回形式、阻塞逻辑、适用业务场景上差异显著。本文聚焦三大核心调用方法,同步对比异步调用,理清选型标准与实战用法。

所有示例共用一套 OpenRouter 兼容模型配置,支持字典消息、LangChain 内置 HumanMessage/SystemMessage 传参:
from langchain.chat_models import init_chat_modelfrom langchain_core.messages import HumanMessage, SystemMessagefrom dotenv import load_dotenvimport osimport asynciofrom rich import print as rprint# 加载环境变量load_dotenv(override=True)llm = init_chat_model(model="deepseek-v4-flash",model_provider="openai",api_key=os.getenv("OPENROUTER_API_KEY"),base_url=os.getenv("OPENROUTER_BASE_URL"))
AIMessage 对象,内置完整文本、Token 消耗、接口延迟、模型元数据、工具调用信息;# 基础单轮提问res = llm.invoke([SystemMessage(content="专业数学老师"),HumanMessage(content="什么是斐波那契数列")])print("完整回答:", res.content)# 查看计费Token消耗print("输入Token:", res.usage_metadata["input_tokens"])print("输出Token:", res.usage_metadata["output_tokens"])
LLM 无内置记忆,无论哪种调用方式,都需要手动拼接完整对话历史:
conversation = [{"role": "system", "content": "友好AI助手"},{"role": "user", "content": "我叫小张"}]# 第一轮调用res1 = llm.invoke(conversation)# 追加AI回复与新提问,留存上下文conversation.append({"role": "assistant", "content": res1.content})conversation.append({"role": "user", "content": "我叫什么名字?"})res2 = llm.invoke(conversation)print(res2.content)
优点:返回信息完整,可直接获取 Token 统计、响应耗时等全量元数据,代码简洁;缺点:长文本生成时全程阻塞,前端会出现长时间空白,交互体验差。
Chunk 对象,通过 .text 实时拼接文本;print("流式实时输出:")for chunk in llm.stream("详细讲解高等数学的作用"):print(chunk.text, end="", flush=True)
优点:首字返回速度快,实现打字机实时输出,大幅优化用户体感;缺点:分片无法直接拿到完整 Token 统计,需要手动累加所有 chunk 的消耗数据。
批量接口一次性提交多条独立问题,减少重复网络握手、鉴权开销,相比循环多次调用 invoke 成本更低、耗时更短,分为两种执行模式。
batch():等待所有任务全部完成,按输入顺序统一返回结果列表;batch_as_completed():任务完成一条立即返回一条,输出顺序打乱,适合任务耗时差异大的场景。tasks = ["1+99等于多少","什么是大语言模型","中国的首都"]results = llm.batch(tasks)for index, ans in enumerate(results):print(f"问题{index+1}:{ans.content}n")
tasks = ["介绍Python", "解释微积分", "一年多少天"]for res in llm.batch_as_completed(tasks):print("单条批量结果:", res.content)
优点:批量处理海量问答、数据清洗场景下节约接口开销;缺点:仅适合无关联独立问题,无法批量传递多轮对话上下文。
线上后端、FastAPI Web 服务、多任务并发场景,同步接口会阻塞事件循环,降低服务并发承载能力,LangChain 为上述三种方法提供了全套异步版本:
ainvoke:异步单次完整调用,对应同步 invokeastream:异步流式分片调用,对应同步 streamabatch:异步批量调用,对应同步 batchasync def async_invoke_demo():res = await llm.ainvoke(HumanMessage(content="2+5*8等于几"))print("异步回答:", res.content)asyncio.run(async_invoke_demo())
async def async_stream_demo():print("异步流式输出:")async for chunk in llm.astream("解释人工智能定义"):print(chunk.text, end="", flush=True)asyncio.run(async_stream_demo())
async def async_batch_demo():tasks = ["春天的特点", "什么是向量", "地球公转周期"]results = await llm.abatch(tasks)for r in results:print(r.content, "n")asyncio.run(async_batch_demo())
表格
| 调用方式 | 同步方法 | 异步方法 | 返回形式 | 最佳适用场景 |
|---|---|---|---|---|
| 单次完整问答 | invoke | ainvoke | 完整 AIMessage 对象 | 后台脚本、简单接口、多轮对话 |
| 实时流式输出 | stream | astream | 分段迭代器 | 网页聊天、长文本生成 |
| 批量多任务处理 | batch | abatch | 有序结果列表 | 离线批量数据清洗、批量问答 |
| 无序批量返回 | batch_as_completed | - | 随完成随输出 | 任务耗时差距大的批量任务 |
invoke,代码简单,信息完整;stream,线上服务选 astream;batch / abatch,降低接口开销;ainvoke/astream/abatch;invoke、stream、batch 构成 LangChain 模型请求的三大基础能力,分别覆盖单次问答、实时交互、批量处理三大业务场景。同步接口适合本地开发、低并发场景,异步接口是线上高并发服务的标准方案。所有调用方法共用一套消息传递规则,上下文记忆均依赖手动拼接对话列表,开发时只需根据并发量、交互形式选择对应接口,即可兼顾性能与用户体验。