如何调度自定义回调事件

## 技术背景介绍

在开发复杂的应用程序时,事件驱动编程是一种常见的设计模式。它允许程序在特定操作或状态改变时触发事件,并执行对应的处理程序。在一些长时间运行的任务中,我们可以在各步骤之间调度自定义事件,以此来监控进度或向最终用户报告任务状态。

本文将介绍如何通过LangChain库调度自定义事件,并消费这些事件。

## 核心原理解析

LangChain支持调度自定义回调事件,通过`adispatch_custom_event`方法可以在异步环境下发出事件。此外,你还可以使用`dispatch_custom_event`在同步环境中发送事件。事件包括两个关键属性:`name`(事件名称)和`data`(事件数据),建议数据是JSON可序列化的。

## 代码实现演示

下面的代码演示如何在不同的Python版本中调度自定义事件,并处理这些事件。

### 异步事件调度

如果你使用Python >=3.11,可以自动传播配置;否则需要手动传播:

```python
from langchain_core.callbacks.manager import adispatch_custom_event
from langchain_core.runnables import RunnableLambda
from langchain_core.runnables.config import RunnableConfig


@RunnableLambda
async def foo(x: str) -> str:
    await adispatch_custom_event("event1", {"x": x})
    await adispatch_custom_event("event2", 5)
    return x


async for event in foo.astream_events("hello world", version="v2"):
    print(event)

手动配置传播(Python <=3.10)

@RunnableLambda
async def bar(x: str, config: RunnableConfig) -> str:
    """An example that shows how to manually propagate config."""
    await adispatch_custom_event("event1", {"x": x}, config=config)
    await adispatch_custom_event("event2", 5, config=config)
    return x


async for event in bar.astream_events("hello world", version="v2"):
    print(event)

异步回调处理

你可以使用异步回调处理器来消费事件:

from typing import Any, Dict, List, Optional
from uuid import UUID
from langchain_core.callbacks import AsyncCallbackHandler

class AsyncCustomCallbackHandler(AsyncCallbackHandler):
    async def on_custom_event(self, name: str, data: Any, *, run_id: UUID, tags: Optional[List[str]] = None, metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) -> None:
        print(f"Received event {name} with data: {data}, with tags: {tags}, with metadata: {metadata} and run_id: {run_id}")

async_handler = AsyncCustomCallbackHandler()
await foo.ainvoke(1, {"callbacks": [async_handler], "tags": ["foo", "bar"]})

同步事件调度

from langchain_core.callbacks import BaseCallbackHandler

class CustomHandler(BaseCallbackHandler):
    def on_custom_event(self, name: str, data: Any, *, run_id: UUID, tags: Optional[List[str]] = None, metadata: Optional[Dict[str, Any]] = None, **kwargs: Any) -> None:
        print(f"Received event {name} with data: {data}, with tags: {tags}, with metadata: {metadata} and run_id: {run_id}")

@RunnableLambda
def foo(x: int, config: RunnableConfig) -> int:
    dispatch_custom_event("event1", {"x": x})
    dispatch_custom_event("event2", {"x": x})
    return x

handler = CustomHandler()
foo.invoke(1, {"callbacks": [handler], "tags": ["foo", "bar"]})

应用场景分析

调度自定义事件对于长时间运行的任务非常有用,例如数据处理流程中的多个步骤。通过调度自定义事件,我们可以更好地追踪和记录任务的进展,并提供实时反馈给最终用户。

实践建议

  • 确保事件数据是JSON可序列化的,以便更好地传递和处理。
  • 在Python <=3.10环境中,记得手动传播配置对象。
  • 使用版本v2的astream事件以确保正确地看到自定义事件。

如果遇到问题欢迎在评论区交流。

---END---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值