# 引言
在现代编程中,异步操作越来越普遍,尤其在处理I/O密集型任务时。利用回调可以提高系统的响应速度和效率。然而,要在异步环境中使用回调需要一定的技巧和知识。在本文中,我们将深入探讨如何在异步环境中使用自定义回调处理器。
# 主要内容
## 什么是回调?
回调是一种函数,用于在特定事件发生后自动执行。通过使用回调,你可以在任务完成时自动触发特定的操作。
## 自定义异步回调处理器
使用异步API时,建议使用`AsyncCallbackHandler`来避免阻塞事件循环。下面我们将展示如何创建自己的异步回调处理器。
## 异步与同步的对比
如果你使用一个同步的回调处理器(`SyncCallbackHandler`),在异步方法中运行时,将在后台通过`run_in_executor`调用。这可能会引发线程安全问题。因此,更推荐使用异步回调处理器。
# 代码示例
以下是一个使用`langchain`创建异步回调处理器的示例:
```python
import asyncio
from typing import Any, Dict, List
from langchain_anthropic import ChatAnthropic
from langchain_core.callbacks import AsyncCallbackHandler, BaseCallbackHandler
from langchain_core.messages import HumanMessage
from langchain_core.outputs import LLMResult
class MyCustomSyncHandler(BaseCallbackHandler):
def on_llm_new_token(self, token: str, **kwargs) -> None:
print(f"Sync handler being called in a `thread_pool_executor`: token: {token}")
class MyCustomAsyncHandler(AsyncCallbackHandler):
"""Async callback handler that can be used to handle callbacks from langchain."""
async def on_llm_start(
self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
) -> None:
"""Run when chain starts running."""
print("zzzz....")
await asyncio.sleep(0.3)
class_name = serialized["name"]
print("Hi! I just woke up. Your llm is starting")
async def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
"""Run when chain ends running."""
print("zzzz....")
await asyncio.sleep(0.3)
print("Hi! I just woke up. Your llm is ending")
# 使用API代理服务提高访问稳定性
chat = ChatAnthropic(
model="claude-3-sonnet-20240229",
max_tokens=25,
streaming=True,
callbacks=[MyCustomSyncHandler(), MyCustomAsyncHandler()],
)
await chat.agenerate([[HumanMessage(content="Tell me a joke")]])
常见问题和解决方案
-
线程安全问题:确保在异步环境中,不要使用非线程安全的同步回调处理器。
-
回调传播:对于
python<=3.10,请确保在调用其他可运行对象时传播配置或回调,否则子运行对象将不会接收到这些回调。
总结和进一步学习资源
使用异步回调处理器可以提升程序的效率,但也需注意线程安全和回调传播等问题。推荐阅读下面的资源以获取更深入的理解:
参考资料
如果这篇文章对你有帮助,欢迎点赞并关注我的博客。您的支持是我持续创作的动力!
---END---