2.3 Runnable 核心方法详解(invoke/ainvoke、batch/abatch、stream/astream 等)

2.3 Runnable 核心方法详解(invoke/ainvoke、batch/abatch、stream/astream 等)

2.3.1 引言

Runnable 协议作为 LangChain 1.2.7 版本的核心执行层抽象,其核心方法提供了同步/异步、单条/批量、完整/流式的全场景执行能力。这些方法遵循统一的接口设计规范,确保所有实现 Runnable 协议的组件(模型、链、工具等)具备一致的调用体验。本节将从基础定义、参数详解、实战案例、进阶技巧到最佳实践,系统拆解 invoke/ainvoke、batch/abatch、stream/astream 六大核心方法,同时覆盖方法间的差异与适用场景。

2.3.2 环境准备与依赖说明
<2.3.2.1> 版本约束(强制要求)
Bash 复制代码
# 核心依赖(严格指定版本)
pip install langchain==1.2.7 langchain-core==1.2.7
# 辅助依赖(匹配1.2.7版本兼容性)
pip install langchain-openai==1.1.7 langchain-community==0.4.1 langchain-classic==1.0.1
# 其他依赖(最新稳定版)
pip install openai==1.13.3 python-dotenv==1.0.1
<2.3.2.2> 基础导入模板
python 复制代码
import os
from dotenv import load_dotenv
from langchain_core.runnables import RunnablePassthrough, RunnableLambda
from langchain_openai import ChatOpenAI
from langchain_core.outputs import ChatResult

# 加载环境变量(OpenAI API密钥)
load_dotenv()
os.environ["OPENAI_API_KEY"] = os.getenv("OPENAI_API_KEY")

# 初始化示例组件(所有案例基于此组件演示)
llm = ChatOpenAI(
    model="gpt-3.5-turbo",
    temperature=0.7,
    max_tokens=512
)

2.3.3 同步核心方法:invoke / batch
<2.3.3.1> invoke:单条输入同步执行
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
def invoke(
    self,
    input: Input,
    config: RunnableConfig | None = None,
    **kwargs: Any
) -> Output:
    """
    同步执行单条输入,返回完整结果
    :param input: 输入数据(支持 dict、str、Message 等,取决于组件类型)
    :param config: 执行配置(RunnableConfig 类型,包含回调、标签、元数据等)
    :param kwargs: 额外参数(模型参数、执行参数,会覆盖组件初始化配置)
    :return: 组件输出结果(类型由组件定义,如 ChatResult、str 等)
    """
关键参数详解
参数 类型 说明
input Input(泛型) 必须参数,输入格式需与组件兼容(如 ChatOpenAI 要求输入为 list[BaseMessage] 或 str)
config Optional[RunnableConfig] 可选配置,支持 tags(标签)、metadata(元数据)、callbacks(回调函数)等
**kwargs Any 动态参数,支持模型参数(如 stoptemperature)和执行参数(如 timeout
实战案例(独立可运行)
python 复制代码
# 案例1:基础字符串输入
result1 = llm.invoke("请解释 LangChain Runnable 的核心作用")
print("案例1输出(字符串输入):", result1.content)

# 案例2:Message 类型输入(更精准的对话控制)
from langchain_core.messages import HumanMessage, SystemMessage

messages = [
    SystemMessage(content="你是技术文档助手,回答简洁专业"),
    HumanMessage(content="Runnable.invoke 与直接调用模型的区别是什么?")
]
result2 = llm.invoke(messages)
print("案例2输出(Message输入):", result2.content)

# 案例3:通过 kwargs 覆盖组件初始化参数
result3 = llm.invoke(
    "生成3条Python性能优化建议",
    temperature=0.2,  # 覆盖初始化的 0.7
    max_tokens=300    # 覆盖初始化的 512
)
print("案例3输出(参数覆盖):", result3.content)

# 案例4:带 config 配置(标签与回调)
from langchain_core.callbacks import ConsoleCallbackHandler

config = {
    "tags": ["runnable-demo", "invoke-method"],
    "metadata": {"user_id": "test-001"},
    "callbacks": [ConsoleCallbackHandler()]  # 控制台打印执行日志
}
result4 = llm.invoke("LangChain 1.2.7 中 Runnable 的优势", config=config)
print("案例4输出(带配置):", result4.content)
注意事项
  1. input 格式需严格匹配组件要求,否则抛出 ValidationError

  2. **kwargs 中的参数优先级:调用时传入 > 组件初始化 > 全局默认

  3. config 中的 callbacks 支持自定义回调(如日志记录、性能监控),需实现 BaseCallbackHandler 接口

  4. 同步方法会阻塞当前线程,适用于单条、低延迟的执行场景

<2.3.3.2> batch:多条输入批量同步执行
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
def batch(
    self,
    inputs: List[Input],
    config: Optional[Union[RunnableConfig, List[RunnableConfig]]] = None,
    return_exceptions: bool = False,
    chunk_size: Optional[int] = None,
    **kwargs: Any
) -> List[Output]:
    """
    同步批量执行多条输入,返回结果列表
    :param inputs: 输入列表,每个元素格式需与组件兼容
    :param config: 全局配置或配置列表(与 inputs 长度一致)
    :param return_exceptions: 是否返回异常(False 直接抛出,True 异常对象存入结果列表)
    :param chunk_size: 批处理分片大小(None 表示单次处理所有输入)
    :param kwargs: 全局额外参数(适用于所有输入)
    :return: 输出结果列表,顺序与 inputs 一致
    """
关键参数详解
参数 类型 说明
inputs List[Input] 必须参数,多条输入的列表(长度≥1)
config Optional[Union[RunnableConfig, List[RunnableConfig]]] 可选配置:单个配置(全局生效)或配置列表(逐条对应输入)
return_exceptions bool 可选参数(默认False),True时异常不中断执行,异常对象存入结果列表
chunk_size Optional[int] 可选参数,大列表分片处理(如 inputs 长度1000,chunk_size=100 分10批)
**kwargs Any 全局参数,所有输入共享(如统一设置 temperature=0.5)
实战案例(独立可运行)
python 复制代码
# 案例1:基础批量输入(无个性化配置)
batch_inputs = [
    "解释 Python 装饰器的作用",
    "说明 HTTP 1.1 与 HTTP 2.0 的区别",
    "列举3种常见的数据库索引类型"
]
batch_results1 = llm.batch(batch_inputs)
for idx, result in enumerate(batch_results1):
    print(f"案例1-第{idx+1}条输出:", result.content)

# 案例2:逐条配置(config 为列表)
configs = [
    {"tags": ["batch-demo", "input-1"], "metadata": {"priority": "high"}},
    {"tags": ["batch-demo", "input-2"], "metadata": {"priority": "medium"}},
    {"tags": ["batch-demo", "input-3"], "metadata": {"priority": "low"}}
]
batch_results2 = llm.batch(batch_inputs, config=configs)
for idx, result in enumerate(batch_results2):
    print(f"案例2-第{idx+1}条输出:", result.content)

# 案例3:异常处理(return_exceptions=True)
invalid_inputs = [
    "解释 RESTful API",  # 有效输入
    12345,               # 无效输入(类型错误)
    "什么是微服务架构"    # 有效输入
]
# 返回异常对象,不中断执行
batch_results3 = llm.batch(invalid_inputs, return_exceptions=True)
for idx, result in enumerate(batch_results3):
    if isinstance(result, Exception):
        print(f"案例3-第{idx+1}条:异常 - {type(result).__name__}: {str(result)}")
    else:
        print(f"案例3-第{idx+1}条输出:", result.content)

# 案例4:大列表分片处理(chunk_size)
large_inputs = [f"生成第{i}条Python学习路径" for i in range(10)]  # 10条输入
# 分2批处理(每批5条)
batch_results4 = llm.batch(large_inputs, chunk_size=5, temperature=0.3)
for idx, result in enumerate(batch_results4):
    print(f"案例4-第{idx+1}条输出:", result.content[:50] + "...")  # 截断输出
注意事项
  1. inputs 列表中若存在无效输入,默认会抛出第一个异常,需通过 return_exceptions=True 捕获所有异常

  2. chunk_size 用于优化大批量输入的内存占用和API调用频率(如第三方模型API的QPS限制)

  3. config 为列表时,长度必须与 inputs 一致,否则抛出 ValueError

  4. 批量方法的执行效率高于循环调用 invoke(减少网络开销和初始化成本)


2.3.4 异步核心方法:ainvoke / abatch
<2.3.4.1> ainvoke:单条输入异步执行
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
async def ainvoke(
    self,
    input: Input,
    config: Optional[RunnableConfig] = None,
    **kwargs: Any
) -> Output:
    """
    异步执行单条输入,返回完整结果(需在异步上下文调用)
    :param input: 输入数据(与 invoke 格式一致)
    :param config: 执行配置(与 invoke 一致)
    :param kwargs: 额外参数(与 invoke 一致)
    :return: 组件输出结果(与 invoke 一致)
    """
关键特性
  1. 基于 Python asyncio 实现,非阻塞执行,适用于高并发场景

  2. 方法签名与 invoke 完全一致,仅增加 async 关键字,降低学习成本

  3. 支持异步回调(AsyncCallbackHandler),需配合异步上下文使用

实战案例(独立可运行)
python 复制代码
import asyncio

# 定义异步执行函数
async def async_invoke_demo():
    # 案例1:基础异步调用
    result1 = await llm.ainvoke("用异步方式解释 ainvoke 的优势")
    print("案例1输出:", result1.content)

    # 案例2:带异步回调
    from langchain_core.callbacks import AsyncConsoleCallbackHandler

    async_config = {
        "tags": ["async-demo", "ainvoke-method"],
        "callbacks": [AsyncConsoleCallbackHandler()]  # 异步回调
    }
    result2 = await llm.ainvoke(
        "LangChain 异步方法的底层实现原理",
        config=async_config,
        temperature=0.4
    )
    print("案例2输出:", result2.content)

    # 案例3:并发执行多个 ainvoke(核心优势)
    task1 = llm.ainvoke("生成10个Python异步编程技巧")
    task2 = llm.ainvoke("解释 async/await 的工作机制")
    task3 = llm.ainvoke("对比同步与异步的性能差异")
    
    # 并发执行,等待所有任务完成
    results = await asyncio.gather(task1, task2, task3)
    for idx, result in enumerate(results, 1):
        print(f"案例3-任务{idx}输出:", result.content[:40] + "...")

# 运行异步函数
asyncio.run(async_invoke_demo())
注意事项
  1. 必须在异步上下文(async def 函数)中通过 await 调用,否则抛出 RuntimeWarning

  2. 异步回调需实现 AsyncCallbackHandler 接口,不可混用同步回调类

  3. 适用于高并发场景(如Web服务接口),可避免线程阻塞导致的性能瓶颈

  4. 异常处理需使用 try/except 包裹 await 语句,捕获异步异常

<2.3.4.2> abatch:多条输入批量异步执行
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
async def abatch(
    self,
    inputs: List[Input],
    config: Optional[Union[RunnableConfig, List[RunnableConfig]]] = None,
    return_exceptions: bool = False,
    chunk_size: Optional[int] = None,
    **kwargs: Any
) -> List[Output]:
    """
    异步批量执行多条输入,返回结果列表(需在异步上下文调用)
    :param inputs: 输入列表(与 batch 格式一致)
    :param config: 全局配置或配置列表(与 batch 一致)
    :param return_exceptions: 是否返回异常(与 batch 一致)
    :param chunk_size: 批处理分片大小(与 batch 一致)
    :param kwargs: 全局额外参数(与 batch 一致)
    :return: 输出结果列表(与 batch 一致)
    """
关键特性
  1. 结合批量处理与异步并发的优势,适用于大规模高并发场景

  2. 分片处理(chunk_size)在异步场景中可控制并发数,避免资源耗尽

  3. batch 接口完全对齐,迁移成本低

实战案例(独立可运行)
python 复制代码
import asyncio

async def async_batch_demo():
    # 案例1:基础异步批量调用
    batch_inputs = [
        "解释 Kafka 的消息投递机制",
        "说明 Redis 的数据持久化方式",
        "列举5种常见的微服务通信协议"
    ]
    batch_results1 = await llm.abatch(batch_inputs)
    for idx, result in enumerate(batch_results1):
        print(f"案例1-第{idx+1}条输出:", result.content[:50] + "...")

    # 案例2:分片异步批量(控制并发数)
    large_inputs = [f"生成第{i}条云原生技术知识点" for i in range(8)]  # 8条输入
    # 分4批,每批2条(控制并发数为2)
    batch_results2 = await llm.abatch(
        large_inputs,
        chunk_size=2,
        temperature=0.2,
        return_exceptions=True
    )
    for idx, result in enumerate(batch_results2):
        if isinstance(result, Exception):
            print(f"案例2-第{idx+1}条:异常 - {str(result)}")
        else:
            print(f"案例2-第{idx+1}条输出:", result.content[:40] + "...")

    # 案例3:混合同步与异步批量(通过 Runnable 组合)
    from langchain_core.runnables import RunnableSequence

    # 定义同步处理函数(格式化输入)
    def format_input(input_text: str) -> List[HumanMessage]:
        return [HumanMessage(content=f"技术详解:{input_text}")]

    # 构建链:同步格式化 + 异步批量执行
    chain = RunnableLambda(format_input) | llm
    chain_inputs = ["Docker", "Kubernetes", "Istio"]
    chain_results = await chain.abatch(chain_inputs)
    for idx, result in enumerate(chain_results):
        print(f"案例3-第{idx+1}条输出:", result.content[:50] + "...")

# 运行异步函数
asyncio.run(async_batch_demo())
注意事项
  1. chunk_size 在异步场景中直接控制并发任务数(如 chunk_size=5 表示同时执行5个异步任务)

  2. 大规模异步批量(如输入数>100)需合理设置 chunk_size,避免触发API速率限制或本地资源耗尽

  3. 异常处理逻辑与 batch 一致,但需在异步函数内使用 try/except 捕获

  4. Runnable 组合使用时,同步组件会自动适配异步执行流程(LangChain 1.2.7 内置适配逻辑)


2.3.5 流式核心方法:stream / astream
<2.3.5.1> stream:同步流式输出
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
def stream(
    self,
    input: Input,
    config: Optional[RunnableConfig] = None,
    **kwargs: Any
) -> Iterator[OutputChunk]:
    """
    同步流式输出结果片段(迭代器形式)
    :param input: 输入数据(与 invoke 格式一致)
    :param config: 执行配置(与 invoke 一致)
    :param kwargs: 额外参数(支持 `stream_options` 等流式专用参数)
    :return: 结果片段迭代器(每个元素为 OutputChunk 类型)
    """
关键特性
  1. 流式输出:结果分片段返回,无需等待完整响应,降低交互延迟

  2. 迭代器接口:通过 for 循环迭代获取片段,支持实时处理(如前端渲染)

  3. 片段类型:OutputChunk 包含 content(内容)、metadata(元数据)、type(片段类型)等属性

实战案例(独立可运行)
python 复制代码
# 案例1:基础流式输出(文本片段迭代)
print("案例1:基础流式输出")
for chunk in llm.stream("详细解释 LangChain 流式输出的应用场景"):
    print(chunk.content, end="", flush=True)  # 实时打印,不换行
print("\n" + "-"*50)

# 案例2:流式片段元数据解析
print("案例2:流式片段元数据")
for chunk in llm.stream(
    "生成5条数据可视化的最佳实践",
    config={"tags": ["stream-demo"]},
    stream_options={"include_usage": True}  # 启用使用量统计(部分模型支持)
):
    print(f"内容片段:{chunk.content}")
    print(f"片段类型:{chunk.type}")
    print(f"元数据:{chunk.metadata}")
    print("-"*30)

# 案例3:流式结果拼接(获取完整结果)
print("案例3:流式结果拼接")
full_content = []
for chunk in llm.stream("LangChain stream 方法的底层实现原理"):
    full_content.append(chunk.content)
    print(chunk.content, end="", flush=True)
complete_result = "".join(full_content)
print(f"\n完整结果:{complete_result}")

# 案例4:流式与 Runnable 组合
from langchain_core.runnables import RunnableParallel

# 定义并行链:同时流式输出两个结果
parallel_chain = RunnableParallel(
    task1=llm.stream,
    task2=RunnableLambda(lambda x: f"总结:{x}") | llm.stream
)
input_text = "解释 MLOps 的核心流程"
print("案例4:并行流式输出")
for key, chunk in parallel_chain.stream(input_text):
    print(f"[{key}] {chunk.content}", end="", flush=True)
print("\n")
注意事项
  1. 流式方法返回的是迭代器,需通过 for 循环或 next() 方法获取片段,不可直接打印迭代器对象

  2. stream_options 参数为模型专用(如 OpenAI 支持 include_usagelogprobs 等),需根据模型文档配置

  3. 流式输出过程中不可中断迭代(除非捕获 StopIteration),否则可能导致连接泄漏

  4. 适用于实时交互场景(如聊天机器人、实时日志展示),需配合前端或终端的流式渲染逻辑

<2.3.5.2> astream:异步流式输出
方法定义(LangChain 1.2.7 源码规范)
python 复制代码
async def astream(
    self,
    input: Input,
    config: Optional[RunnableConfig] = None,
    **kwargs: Any
) -> AsyncIterator[OutputChunk]:
    """
    异步流式输出结果片段(异步迭代器形式)
    :param input: 输入数据(与 stream 格式一致)
    :param config: 执行配置(与 stream 一致)
    :param kwargs: 额外参数(与 stream 一致)
    :return: 异步结果片段迭代器(需通过 async for 迭代)
    """
关键特性
  1. 结合异步非阻塞与流式输出的优势,适用于高并发实时场景(如异步Web服务)

  2. 异步迭代器:通过 async for 循环迭代,支持并发处理多个流式任务

  3. stream 接口完全对齐,仅迭代方式不同(async for vs for

实战案例(独立可运行)
python 复制代码
import asyncio

async def async_stream_demo():
    # 案例1:基础异步流式输出
    print("案例1:基础异步流式输出")
    async for chunk in llm.astream("异步流式输出的核心优势是什么?"):
        print(chunk.content, end="", flush=True)
    print("\n" + "-"*50)

    # 案例2:并发异步流式任务
    async def stream_task(prompt: str, task_name: str):
        print(f"\n案例2 - {task_name} 开始:")
        async for chunk in llm.astream(prompt):
            print(f"[{task_name}] {chunk.content}", end="", flush=True)
        print(f"\n案例2 - {task_name} 结束")

    # 并发执行两个异步流式任务
    task1 = stream_task("解释异步迭代器的工作原理", "任务1")
    task2 = stream_task("列举3种异步流式处理框架", "任务2")
    await asyncio.gather(task1, task2)

    # 案例3:异步流式结果拼接与处理
    print("\n案例3:异步流式结果拼接")
    full_content = []
    async for chunk in llm.astream(
        "LangChain astream 与 stream 的差异对比",
        temperature=0.3
    ):
        full_content.append(chunk.content)
        print(chunk.content, end="", flush=True)
    complete_result = "".join(full_content)
    print(f"\n完整结果:{complete_result}")

# 运行异步函数
asyncio.run(async_stream_demo())
注意事项
  1. 必须通过 async for 迭代异步流式迭代器,不可使用普通 for 循环

  2. 并发处理多个异步流式任务时,需通过 asyncio.gather 或任务组管理,避免并发数过高

  3. 异步流式输出的异常需在 async for 循环内通过 try/except 捕获

  4. 适用于异步Web框架(如 FastAPI)的实时响应场景,需配合异步响应对象(如 StreamingResponse


2.3.6 核心方法对比与适用场景
方法 执行模式 输入数量 输出形式 核心适用场景 性能特点
invoke 同步 单条 完整结果 单条请求、低并发、需立即获取结果 简单直接,阻塞线程
ainvoke 异步 单条 完整结果 高并发单条请求、异步服务 非阻塞,支持高并发
batch 同步 多条 结果列表 批量处理、低并发批量任务 批量优化,减少开销
abatch 异步 多条 结果列表 高并发批量任务、大规模处理 异步并发+批量优化,效率最高
stream 同步 单条 片段迭代器 实时交互、同步终端展示 低延迟,实时反馈
astream 异步 单条 异步片段迭代器 高并发实时交互、异步Web服务 非阻塞+实时反馈,支持高并发

2.3.7 进阶实践:最佳实践与架构扩展
<2.3.7.1> 配置透传最佳实践

Runnable 核心方法的 config 参数支持全局配置透传,结合 LangChain 1.2.7 的上下文管理机制,可实现:

  1. 全链路标签追踪 :通过 tags 标记请求来源,用于日志分析和链路追踪

  2. 统一回调管理:全局注册回调函数,监控所有方法的执行状态(开始、结束、异常)

  3. 动态元数据注入 :通过 metadata 传递用户信息、请求ID等上下文数据

python 复制代码
# 全局配置示例(适用于所有核心方法)
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.runnables import RunnableConfig

class CustomCallback(BaseCallbackHandler):
    """自定义回调函数(监控执行生命周期)"""
    def on_chain_start(self, serialized: dict, inputs: dict, **kwargs):
        print(f"[回调] 执行开始 - 组件:{serialized['name']},输入:{inputs.keys()}")
    
    def on_chain_end(self, outputs: dict, **kwargs):
        print(f"[回调] 执行结束 - 输出长度:{len(str(outputs))}")

# 全局统一配置
global_config: RunnableConfig = {
    "tags": ["production", "runnable-best-practice"],
    "metadata": {"app_name": "langchain-demo", "env": "prod"},
    "callbacks": [CustomCallback()]
}

# 所有核心方法共享配置
# 1. invoke 用全局配置
result_invoke = llm.invoke("配置透传示例", config=global_config)

# 2. batch 用全局配置
batch_results = llm.batch(["配置透传1", "配置透传2"], config=global_config)

# 3. stream 用全局配置
for chunk in llm.stream("配置透传3", config=global_config):
    pass
<2.3.7.2> 性能优化指南
  1. 批量方法优化

    • 大批量输入优先使用 batch/abatch,避免循环调用 invoke/ainvoke

    • 根据API QPS限制调整 chunk_size(如 OpenAI 免费版 QPS=3,chunk_size=3

    • 启用 return_exceptions=True 避免单条输入异常导致批量任务失败

  2. 异步方法优化

    • 高并发场景优先使用 ainvoke/abatch/astream,避免线程池耗尽

    • 异步批量任务通过 chunk_size 控制并发数(推荐值:CPU核心数×2 + 1)

    • 避免在异步方法内执行同步阻塞操作(如 time.sleep),需使用 asyncio.sleep

  3. 流式方法优化

    • 实时交互场景优先使用 stream/astream,减少用户等待感

    • 流式输出时避免频繁IO操作(如打印、数据库写入),可批量缓存片段后处理

    • 大文本输出场景使用流式方法,避免内存占用过高

<2.3.7.3> 可扩展性设计(自定义 Runnable 方法重写)

当自定义 Runnable 组件时,需遵循 1.2.7 版本的协议规范,重写核心方法时需注意:

  1. 方法签名一致性:严格遵循官方方法的参数定义(输入、输出、配置参数)

  2. 异步同步适配 :若重写 invoke,建议同时重写 ainvoke(或依赖默认实现)

  3. 配置透传完整性 :确保 config 参数在自定义逻辑中正确传递和使用

  4. 异常处理标准化 :统一抛出 LangChainException 及其子类,便于上层捕获

python 复制代码
from langchain_core.runnables import Runnable
from langchain_core.exceptions import LangChainException
from typing import Any, Iterator, Optional, List

class CustomRunnable(Runnable):
    """自定义 Runnable 示例(重写核心方法)"""
    def invoke(
        self,
        input: str,
        config: Optional[RunnableConfig] = None,
        **kwargs: Any
    ) -> str:
        try:
            # 自定义同步逻辑
            if not isinstance(input, str):
                raise ValueError("输入必须为字符串")
            return f"自定义处理结果:{input.upper()}"
        except Exception as e:
            raise LangChainException(f"invoke 执行失败:{str(e)}") from e

    async def ainvoke(
        self,
        input: str,
        config: Optional[RunnableConfig] = None,
        **kwargs: Any
    ) -> str:
        # 自定义异步逻辑(可调用同步逻辑并包装为异步)
        return await asyncio.get_event_loop().run_in_executor(
            None, self.invoke, input, config, **kwargs
        )

    def stream(
        self,
        input: str,
        config: Optional[RunnableConfig] = None,
        **kwargs: Any
    ) -> Iterator[str]:
        # 自定义流式逻辑
        result = self.invoke(input, config, **kwargs)
        for char in result:
            yield char  # 逐字符流式输出

# 测试自定义 Runnable
custom_runnable = CustomRunnable()

# 调用核心方法
print("自定义 Runnable invoke:", custom_runnable.invoke("test input"))

# 异步调用
async def test_ainvoke():
    print("自定义 Runnable ainvoke:", await custom_runnable.ainvoke("async test"))
asyncio.run(test_ainvoke())

# 流式调用
print("自定义 Runnable stream:", end="")
for chunk in custom_runnable.stream("stream test"):
    print(chunk, end="", flush=True)
<2.3.7.4> 错误处理最佳实践
  1. 分层异常捕获

    • 顶层:捕获 LangChainException(所有LangChain组件的基础异常)

    • 中层:捕获方法特定异常(如 ValidationError 输入格式错误、APIError 第三方API错误)

    • 底层:捕获通用异常(如 ValueErrorTypeError

  2. 批量方法异常处理

    • 关键任务:return_exceptions=False,快速失败并排查问题

    • 非关键任务:return_exceptions=True,记录异常并继续执行其他输入

  3. 流式方法异常处理

    • 同步流式:在 for 循环内捕获 StopIteration 和自定义异常

    • 异步流式:在 async for 循环内捕获 StopAsyncIteration 和自定义异常

python 复制代码
# 异常处理示例
try:
    # 1. 输入格式错误
    invalid_input = {"text": "错误格式"}
    llm.invoke(invalid_input)  # 抛出 ValidationError
except ValueError as e:
    print(f"输入格式错误:{str(e)}")
except Exception as e:
    print(f"其他异常:{str(e)}")

# 2. 批量方法异常处理(关键任务)
try:
    critical_inputs = ["有效输入", 123, "另一个有效输入"]
    llm.batch(critical_inputs, return_exceptions=False)  # 抛出第一个异常
except Exception as e:
    print(f"批量任务失败:{str(e)}")
    # 执行回滚逻辑

# 3. 流式方法异常处理
try:
    for chunk in llm.stream(12345):  # 无效输入
        print(chunk.content, end="")
except Exception as e:
    print(f"\n流式执行失败:{str(e)}")
相关推荐
九.九10 小时前
ops-transformer:AI 处理器上的高性能 Transformer 算子库
人工智能·深度学习·transformer
春日见10 小时前
拉取与合并:如何让个人分支既包含你昨天的修改,也包含 develop 最新更新
大数据·人工智能·深度学习·elasticsearch·搜索引擎
恋猫de小郭10 小时前
AI 在提高你工作效率的同时,也一直在增加你的疲惫和焦虑
前端·人工智能·ai编程
deephub10 小时前
Agent Lightning:微软开源的框架无关 Agent 训练方案,LangChain/AutoGen 都能用
人工智能·microsoft·langchain·大语言模型·agent·强化学习
大模型RAG和Agent技术实践11 小时前
从零构建本地AI合同审查系统:架构设计与流式交互实战(完整源代码)
人工智能·交互·智能合同审核
老邋遢11 小时前
第三章-AI知识扫盲看这一篇就够了
人工智能
互联网江湖11 小时前
Seedance2.0炸场:长短视频们“修坝”十年,不如AI放水一天?
人工智能
PythonPioneer11 小时前
在AI技术迅猛发展的今天,传统职业该如何“踏浪前行”?
人工智能
冬奇Lab11 小时前
一天一个开源项目(第20篇):NanoBot - 轻量级AI Agent框架,极简高效的智能体构建工具
人工智能·开源·agent
山塘小鱼儿12 小时前
本地Ollama+Agent+LangGraph+LangSmith运行
python·langchain·ollama·langgraph·langsimth