langchain callback学习

一.quickstart

  • 官方文档在此:https://python.langchain.com/docs/modules/callbacks/

  • 发现自己之前用langchain都是纯纯只是跑通,要能灵活使用还是得深入研究一下框架的,还有仔细看文档的…

  • callback其实就是当时刚开始用langchain感觉神奇的地方,就是各种行为都能看到输出

  • 跑一下官方的demo
    在这里插入图片描述

  • LangChain 的回调系统允许开发者在 LLM 应用程序的各个阶段设置hook。这意味着,无论是日志记录、监控、数据流处理还是其他任何任务,开发者都可以精确地控制和管理。

    开发者可以通过使用 API 中的回调参数来订阅不同的事件。这些事件对应于处理器对象的列表,它们是预定义的并期望按照特定方式实现。

  • 回调处理程序

    在 LangChain 中,CallbackHandlers 是实现 CallbackHandler 接口的对象。这个接口为开发者提供了一系列方法,每个方法对应于可以被订阅的事件。

    LangChain 中定义了一个 BaseCallbackHandler 类,这是一个基本的回调处理程序,它提供了处理来自 LangChain 的回调的功能。
    在这里插入图片描述

  • 在 LangChain 的 API 中,几乎所有的对象(例如 Chains、Models、Tools、Agents 等)都支持回调参数。可以在两个主要位置使用它:

  • 构造函数回调:这些是在对象创建时定义的,并且对于该对象上的所有调用都是通用的。

  • 请求回调:这些是在执行方法(如 run() 或 apply())时定义的,并且仅适用于特定的请求。

    此外,API 的大多数对象都支持 verbose 参数。这是一个非常有用的工具,特别是在调试过程中,因为它会将所有事件记录到控制台。

二.Async callbacks

import asyncio
from typing import Any, Dict, List

from langchain.chat_models import ChatOpenAI
from langchain.schema import LLMResult, HumanMessage
from langchain.callbacks.base import AsyncCallbackHandler, BaseCallbackHandler


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")


# To enable streaming, we pass in `streaming=True` to the ChatModel constructor
# Additionally, we pass in a list with our custom handler
chat = ChatOpenAI(
    max_tokens=25,
    streaming=True,
    callbacks=[MyCustomSyncHandler(), MyCustomAsyncHandler()],
)

await chat.agenerate([[HumanMessage(content="Tell me a joke")]])

在这里插入图片描述
注意 await chat.agenerate([[HumanMessage(content="Tell me a joke")]]) 这个写法在jupyternotebook中可以,.py文件不行
.py文件中可以像下面这样

if __name__ == "__main__":
    loop = asyncio.get_event_loop()
    result = loop.run_until_complete(chat.agenerate([[HumanMessage(content="Tell me a joke")]]))
    loop.close()

在这里插入图片描述

三.把回调消息写入文件

  • https://python.langchain.com/docs/modules/callbacks/filecallbackhandler
    在这里插入图片描述

  • 跑一下它的demo

    from loguru import logger
    
    from langchain.callbacks import FileCallbackHandler
    from langchain.chains import LLMChain
    from langchain.llms import OpenAI
    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} = ")
    
    # this chain will both print to stdout (because verbose=True) and write to 'output.log'
    # if verbose=False, the FileCallbackHandler will still write to 'output.log'
    chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler], verbose=True)
    answer = chain.run(number=2)
    logger.info(answer)
    

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

如何提取出来

正则表达式

  • chatgpt教我的
    在这里插入图片描述
  • 试了下有点问题
    在这里插入图片描述
    第一步没提取干净,然后最后1+2=3的3也没写出来

官方的方法

在这里插入图片描述
在这里插入图片描述

跑一下试试
在这里插入图片描述

  • 不过注意到这个html,那就简单了,用爬虫库就行

    from bs4 import BeautifulSoup
    soup = BeautifulSoup(html, 'html.parser')
    
    # 提取<pre>标签中的内容
    pre_content = soup.find('pre', class_='ansi2html-content')
    
    # 获取所有的文本内容
    texts = pre_content.get_text().split('n')
    
    # 过滤掉空行
    filtered_texts = [text.strip() for text in texts if text.strip()]
    
    print('n'.join(filtered_texts))
    

    在这里插入图片描述
    之后可以把这个转换和提取流程加入到LLM chain运行过程中,就可以把东西提取出来了 ~