回调函数和异步编程
回调函数是一种编程模式,其中一个函数作为参数传给另一个函数,并在适当的时候被调用。这种模式在处理异步操作时非常有用。
异步编程
异步编程允许代码在等待某个操作完成时继续执行,这与同步编程形成对比,后者必须等待操作按顺序完成。
回调函数示例
def compute(x, y, callback):
result = x + y
callback(result)
def print_result(value):
print(f"The result is: {value}")
compute(3, 4, print_result) # 输出: The result is: 7
异步回调示例
import asyncio
async def compute(x, y, callback):
print("Starting compute...")
await asyncio.sleep(0.5) # 模拟异步操作
result = x + y
print("Finished compute...")
async def main():
print("Main starts...")
await compute(3, 4, print_result)
print("Main ends...")
asyncio.run(main())
LangChain 中的 Callback 处理器
LangChain 的 Callback 机制允许在应用程序的不同阶段进行自定义操作,如日志记录和监控。
CallbackHandler 接口
继承 BaseCallbackHandler 来创建自定义回调处理器,包含多种方法如 on_llm_start、on_chat 和 on_llm_error。
内置处理器
LangChain 提供内置处理器,如 StdOutCallbackHandler 和 FileCallbackHandler。
使用回调处理器
在 LangChain 组件中,可以通过构造函数回调和请求回调两种方式使用回调处理器。
示例代码
from langchain.callbacks import FileCallbackHandler
from langchain.chains import LLMChain
from langchain.llms import OpenAI
from langchain.prompts import PromptTemplate
logfile = "output.log"
handler = FileCallbackHandler(logfile)
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler], verbose=True)
answer = chain.run(number=2)
自定义回调函数
通过 BaseCallbackHandler 和 AsyncCallbackHandler 自定义回调函数。
同步回调处理器示例
class MyFlowerShopSyncHandler(BaseCallbackHandler):
def on_llm_new_token(self, token: str, **kwargs) -> None:
print(f"获取花卉数据: token: {token}")
异步回调处理器示例
class MyFlowerShopAsyncHandler(AsyncCallbackHandler):
async def on_llm_start(self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any) -> None:
print("正在获取花卉数据...")
await asyncio.sleep(0.5) # 模拟异步操作
print("花卉数据获取完毕。提供建议...")
async def on_llm_end(self, response: LLMResult, **kwargs: Any) -> None:
print("整理花卉建议...")
await asyncio.sleep(0.5) # 模拟异步操作
print("祝你今天愉快!")
用 get_openai_callback 构造令牌计数器
使用 get_openai_callback 上下文管理器监控与 OpenAI 交互的 Token 数量。
示例代码
from langchain.callbacks import get_openai_callback
with get_openai_callback() as cb:
conversation("我姐姐明天要过生日,我需要一束生日花束。")
print("\n总计使用的tokens:", cb.total_tokens)
总结
回调函数是计算机科学中一个重要和广泛应用的概念,它允许我们在特定的时间或条件下执行特定的代码。在 LangChain 中,回调机制为用户提供了灵活性和自定义能力,以便更好地控制和响应事件。
思考题
- 如何将令牌计数器实现到其他记忆机制中?
- 如何在请求过程中引入回调机制?
延伸阅读
- GitHub 代码:CallbackHandler 中的可监控事件和方法
- 文档:LangChain中的回调机制
- 知乎:什么是回调函数