LangChain实战:回调函数

前言

毫无疑问,2024将是人工智能丰收年,开始寒假的我,准备先把LangChain捋一遍。

这篇文章来学习下callback机制, 之前聊过AutoGen的callback机制,我们来对比下。

回调和异步

作为js开发者,对于回调函数和异步编程非常熟悉。在事件监听、Ajax请求和定时器中,我们常会使用回调函数和打理异步任务。我们通过代码来熟悉下python的方式。

python 复制代码
# Python asyncio模块是用于异步编程的标准库,实现了协程、事件循环和异步I/O等功能
import asyncio
async def rectangleArea(w, h, callback):
    print("开始计算矩形的面积...")
    # 等待0.5秒
    await asyncio.sleep(0.5)
     = x * y
    print("计算结束")
   
async def circleArea():
   print("开始圆形计算")
   await asyncio.sleep(1)
   print("完成圆形计算")
    
# async 和 在js里一样, 是函数修饰符,内部可以使用await
async def main():
    print("主线程开始...")
    task1 = asyncio.create_task(rectangleArea(3, 4, print_result))
    task2 = asyncio.create_task(circleArea())
    
    await task1
    await task2
    print("主线程结束...")
    
asyncio.run(main())

当代码执行到sleep时,task会暂停,并开始执行另一个任务,这就是异步,跟js 里的async await 有些区别。

LangChain的Callback机制

LangChain在打理AI应用时,有太多需要通过CallbackHandler来实现,比如日志记录、监控、数据流处理等。

我们来看一个需求,要求在LangChain执行完一个LLM工作后,将输出写入output.log文件

ini 复制代码
from loguru import logger
# langchain callback 机制提供了各种callbackHandler,这里是File,处理文件加调
from langchain.callbacks import FileCallbackHandler
# 最基本的LLM工作Chain,
from langchain.chain from LLMChain
# Prompt模板
from langchain.prompts import PromptTemplate

logFile = "output.log"
logger.add(logfile, colorize=True, enqueue=True)
handler = FileCallbackHandler(logfile)

llm = OpenAI()
prompt = PromptTemplate.from_template("1 + {number} = ")
chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler], verbose=True)
answer = chain.run(number=2)
logger.info(answer)

上面是一个简单的callback例子。在之前熟悉的LLMChain实例化过程中,我们传入了callbacks参数,它是一个数组,里面是我们定义的文件回调处理。当大模型交互完成后,将结果写入logger。

自定义回调函数

我们来看一个老喻干货店客服中的例子。

python 复制代码
# Python asyncio模块是用于异步编程的标准库,实现了协程、事件循环和异步I/O等功能
import asyncio
# 从typing模块导入Any Dict  List 类型
from typing import Any, Dict, List
# ChatOpenAI
from langchain.chat_models import ChatOpenAI
# 从schema 中引入LLMResult、HumanMessage
from langchain.schema import LLMResult, HumanMessage

from langchain.callbacks.base import AsyncCallbackHandler, BaseCallbackHandler

上述代码引入了AsyncCallbackHandler 异步任务处理器、BaseCallbackHandler LangChain回调基类,等下可以自定义

python 复制代码
基于 BaseCallbackHandler 创建异步任务处理类
class MyDryFoodShopSyncHandler(BaseCallbackHandler): 
    # 当llm 接收到新token时 触发
    def on_llm_new_token(self, token: str, **kwargs) -> None: 
    print(f"干货数据: token: {token}")
python 复制代码
# 创建异步回调处理器
class MyDryFoodAsyncHandler(AsyncCallbackHandler): 
    # 在llm 开始工作前
    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("祝你买货愉快!")
ini 复制代码
# 异步函数
async def main(): 
    drayfood_shop_chat = ChatOpenAI( 
        max_tokens=100, 
        streaming=True, 
        callbacks=[MyDryFoodShopSyncHandler(), MyDryFoodAsyncHandler()], ) # 异步生成聊天回复 
        await drayfood_shop_chat.agenerate([[HumanMessage(content="哪种干货最适合炖鸡?只简单说3种,不超过60字")]])
        # 运行主异步函数
        asyncio.run(main())

当用户在我的干货店里提出关于营养汤相关的问题时,我们的AI客服,每当新的Token生成时,会有打印。在与OpenAI进行交互前后,又有打印,并最后祝客户买货愉快。

计算Tokens 开销及成本控制

python 复制代码
from langchain import OpenAI
# 聊天chain
from langchain.chains import ConversationChain
# memory
from langchain.chains.conversation.memory import ConversationBufferMemory

# 初始化大语言模型
llm = OpenAI(
    temperature=0.5,
    model_name="gpt-3.5-turbo-instruct")

# 初始化对话链
conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferMemory()
)

# 第一天的对话
# 回合1
conversation("我家明天要开party,我需要一些干海货。")
print("第一次对话后的记忆:", conversation.memory.buffer)

# 回合2
conversation("爷爷喜欢虾干,一两一只的。")
print("第二次对话后的记忆:", conversation.memory.buffer)

# 回合3 (第二天的对话)
conversation("我又来了,还记得我昨天为什么要买干海货吗?")
print("/n第三次对话后时提示:/n",conversation.prompt.template)
print("/n第三次对话后的记忆:/n", conversation.memory.buffer)

如果我们需要确切计算tokens开销,就需要用到calblack。

python 复制代码
from langchain import OpenAI
from langchain.chains import ConversationChain
from langchain.chains.conversation.memory import ConversationBufferMemory
from langchain.callbacks import get_openai_callback

# 初始化大语言模型
llm = OpenAI(temperature=0.5, model_name="gpt-3.5-turbo-instruct")

# 初始化对话链
conversation = ConversationChain(
    llm=llm,
    memory=ConversationBufferMemory()
)

# 使用context manager进行token counting
with get_openai_callback() as cb:
    # 第一天的对话
    # 回合1
    conversation("我家明天要开party,我需要一些干海货。")
    print("第一次对话后的记忆:", conversation.memory.buffer)

    # 回合2
    conversation("爷爷喜欢虾干,一两一只的。")
    print("第二次对话后的记忆:", conversation.memory.buffer)

    # 回合3 (第二天的对话)
    conversation("我又来了,还记得我昨天为什么要买干海货吗?")
    print("/n第三次对话后时提示:/n",conversation.prompt.template)
    print("/n第三次对话后的记忆:/n", conversation.memory.buffer)

# 输出使用的tokens
print("\n总计使用的tokens:", cb.total_tokens)

get_openai_callback 可以监控ConversationChain 的开销。正好我们可以计算在这些对话中使用的总 Tokens 数。

makefile 复制代码
总计使用的tokens: 1023

总结

通过callback, 我们可以去处理一些token开销,或LLM 任务log等的工作,收获还是可以的。

相关推荐
苏苏susuus2 小时前
机器学习:load_predict_project
人工智能·机器学习
科技小E2 小时前
打手机检测算法AI智能分析网关V4守护公共/工业/医疗等多场景安全应用
人工智能·安全·智能手机
猿饵块3 小时前
视觉slam--框架
人工智能
yvestine4 小时前
自然语言处理——Transformer
人工智能·深度学习·自然语言处理·transformer
SuperW5 小时前
OPENCV图形计算面积、弧长API讲解(1)
人工智能·opencv·计算机视觉
山海不说话5 小时前
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
人工智能·python·计算机视觉·视觉检测
虹科数字化与AR6 小时前
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
人工智能·ar·ar眼镜·船舶智造·数字工作流·智能装配
Georgewu7 小时前
【ModelArts】ModelArts一站式AI开发平台详解(一)
aigc·openai·ai编程
飞哥数智坊7 小时前
Coze实战第13讲:飞书多维表格读取+豆包生图模型,轻松批量生成短剧封面
人工智能
newxtc8 小时前
【配置 YOLOX 用于按目录分类的图片数据集】
人工智能·目标跟踪·分类