• 第九天!玩转langchain!回调处理器!一篇学会日志+监控+流式传输!9/10


    原文:第九天!玩转langchain!回调处理器!一篇学会日志+监控+流式传输!9/10 - 知乎

    在第九篇!跟着雄哥学langchain中的回调处理器!

    时间飞快呀~已经第九课了,在更新的这10天时间,雄哥公众号的阅读量也来到了历史新低!太干了,以至于只有星球花钱的小朋友在坚持打卡!

    雄哥每天都会看!你学习的有没有用心,有没有不懂的!越是认真的小朋友,进步越快!

    人的专注力只有10分钟,通篇言简意赅,一看就懂!

    ①什么是回调处理器?

    ②如何使用?

    ③适用哪些场景?

    langchain更新太快了,我们整个教程默认统一使用版本 0.0.235!

    雄哥一直都说,一口吃不成胖子!成功都是一步步走出来的!

    总共10篇,每篇都有任务,你只要跟着走!有条件的到星球打卡,你肯定有所获!那些只看不做的,最后也就一晃眼,啥都得不到!

    以后你想看想学了,不好意思,一天一个大版本,你已经跟不上了!


    第一部分:什么是回调处理器?

    Callback 是 LangChain 提供的回调机制,允许我们在 LLM 应用程序的各个阶段使用 Hook(钩子)。这对于记录日志、监控、流式传输等任务非常有用。这些任务的执行逻辑由回调处理器(CallbackHandler)定义的。

    Python 程序中, 回调处理器通过继承 BaseCallbackHandler 来实现。BaseCallbackHandler 接口对每一个可订阅的事件定义了一个回调函数。

    BaseCallbackHandler 的子类可以实现这些回调函数来处理事件,当事件触发时,LangChain 的回调管理器 CallbackManager 会调用相应的回调函数。

    以下是 BaseCallbackHandler 的源代码地址和定义:

    源代码地址:https://github.com/langchain-ai/langchain/blob/v0.0.235/langchain/callbacks/base.py#L225

    定义:

    1. class BaseCallbackHandler:
    2. """Base callback handler that can be used to handle callbacks from langchain."""
    3. def on_llm_start(
    4. self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
    5. )
    6. -> Any:
    7. """Run when LLM starts running."""
    8. def on_chat_model_start(
    9. self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs: Any
    10. )
    11. -> Any:
    12. """Run when Chat Model starts running."""
    13. def on_llm_new_token(self, token: str, **kwargs: Any) -> Any:
    14. """Run on new LLM token. Only available when streaming is enabled."""
    15. def on_llm_end(self, response: LLMResult, **kwargs: Any) -> Any:
    16. """Run when LLM ends running."""
    17. def on_llm_error(
    18. self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    19. )
    20. -> Any:
    21. """Run when LLM errors."""
    22. def on_chain_start(
    23. self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any
    24. )
    25. -> Any:
    26. """Run when chain starts running."""
    27. def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> Any:
    28. """Run when chain ends running."""
    29. def on_chain_error(
    30. self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    31. )
    32. -> Any:
    33. """Run when chain errors."""
    34. def on_tool_start(
    35. self, serialized: Dict[str, Any], input_str: str, **kwargs: Any
    36. )
    37. -> Any:
    38. """Run when tool starts running."""
    39. def on_tool_end(self, output: str, **kwargs: Any) -> Any:
    40. """Run when tool ends running."""
    41. def on_tool_error(
    42. self, error: Union[Exception, KeyboardInterrupt], **kwargs: Any
    43. )
    44. -> Any:
    45. """Run when tool errors."""
    46. def on_text(self, text: str, **kwargs: Any) -> Any:
    47. """Run on arbitrary text."""
    48. def on_agent_action(self, action: AgentAction, **kwargs: Any) -> Any:
    49. """Run on agent action."""
    50. def on_agent_finish(self, finish: AgentFinish, **kwargs: Any) -> Any:
    51. """Run on agent end."""


    第二部分:如何使用?

    LangChain 内置支持了一系列回调处理器,我们也可以按需求自定义处理器,以实现特定的业务。这里介绍两种:内置处理器、自定义处理器的用法!

    2.1 内置处理器

    StdOutCallbackHandler 是 LangChain 所支持的最基本的处理器。它将所有的回调信息打印到标准输出。这对于调是试非常有用。

    LangChain 链的基类 Chain 提供了一个 callbacks 参数来指定要使用的回调处理器。请参考Chain源码,其中代码片段为:

    1. class Chain(Serializable, ABC):
    2. """Abstract base class for creating structured sequences of calls to components.
    3. ...
    4. callbacks: Callbacks = Field(default=None, exclude=True)
    5. """Optional list of callback handlers (or callback manager). Defaults to None.
    6. Callback handlers are called throughout the lifecycle of a call to a chain,
    7. starting with on_chain_start, ending with on_chain_end or on_chain_error.
    8. Each custom chain can optionally call additional callback methods, see Callback docs
    9. for full details."""

    用法如下:

    1. from langchain.callbacks import StdOutCallbackHandler
    2. from langchain.chains import LLMChain
    3. from langchain.llms import OpenAI
    4. from langchain.prompts import PromptTemplate
    5. handler = StdOutCallbackHandler()
    6. llm = OpenAI()
    7. prompt = PromptTemplate.from_template("Who is {name}?")
    8. chain = LLMChain(llm=llm, prompt=prompt, callbacks=[handler])
    9. chain.run(name="Super Mario")

    你应该得到如下输出:

    1. > Entering new LLMChain chain...
    2. Prompt after formatting:
    3. Who is Super Mario?
    4. > Finished chain.
    5. \n\nSuper Mario is the protagonist of the popular video game franchise of the same name created by Nintendo. He is a fictional character who stars in video games, television shows, comic books, and films. He is a plumber who is usually portrayed as a portly Italian-American, who is often accompanied by his brother Luigi. He is well known for his catchphrase "It\'s-a me, Mario!"

    2.2 自定义处理器

    我们可以通过继承 BaseCallbackHandler 来实现自定义的回调处理器。下面是一个简单的例子,TimerHandler 将跟踪 Chain 或 LLM 交互的起止时间,并统计每次交互的处理耗时。

    1. from langchain.callbacks.base import BaseCallbackHandler
    2. import time
    3. class TimerHandler(BaseCallbackHandler):
    4. def __init__(self) -> None:
    5. super().__init__()
    6. self.previous_ms = None
    7. self.durations = []
    8. def current_ms(self):
    9. return int(time.time() * 1000 + time.perf_counter() % 1 * 1000)
    10. def on_chain_start(self, serialized, inputs, **kwargs) -> None:
    11. self.previous_ms = self.current_ms()
    12. def on_chain_end(self, outputs, **kwargs) -> None:
    13. if self.previous_ms:
    14. duration = self.current_ms() - self.previous_ms
    15. self.durations.append(duration)
    16. def on_llm_start(self, serialized, prompts, **kwargs) -> None:
    17. self.previous_ms = self.current_ms()
    18. def on_llm_end(self, response, **kwargs) -> None:
    19. if self.previous_ms:
    20. duration = self.current_ms() - self.previous_ms
    21. self.durations.append(duration)
    22. llm = OpenAI()
    23. timerHandler = TimerHandler()
    24. prompt = PromptTemplate.from_template("What is the HEX code of color {color_name}?")
    25. chain = LLMChain(llm=llm, prompt=prompt, callbacks=[timerHandler])
    26. response = chain.run(color_name="blue")
    27. print(response)
    28. response = chain.run(color_name="purple")
    29. print(response)
    30. timerHandler.durations

    你应该得到如下输出:

    1. The HEX code for blue is #0000FF.
    2. The HEX code of the color purple is #800080.
    3. [1589, 1097]

    第三部分:适用场景

    通过 LLMChain 的构造函数参数设置 callbacks 仅仅是众多适用场景之一。接下来我们简明地列出其他使用场景和示例代码。

    别走偏哦!前面我们介绍了回调处理器的场景,那我们对于 Model,Agent, Tool,以及 Chain 都可以通过以下方式设置回调处理器:

    3.1 构造函数参数 callbacks 设置

    关于 Chain,以 LLMChain 为例,请参考本讲上一部分内容。注意在 Chain 上的回调器监听的是 chain 相关的事件,因此回调器的如下函数会被调用:

    1)on_chain_start

    2)on_chain_end

    3)on_chain_error

    Agent, Tool,以及 Chain 上的回调器会分别被调用相应的回调函数。

    下面分享关于 Model 与 callbacks 的使用示例:

    1. timerHandler = TimerHandler()
    2. llm = OpenAI(callbacks=[timerHandler])
    3. response = llm.predict("What is the HEX code of color BLACK?")
    4. print(response)
    5. timerHandler.durations

    你应该看到类似如下的输出:

    1. ['What is the HEX code of color BLACK?']
    2. generations=[[Generation(text='\n\nThe hex code of black is #000000.', generation_info={'finish_reason': 'stop', 'logprobs': None})]] llm_output={'token_usage': {'prompt_tokens': 10, 'total_tokens': 21, 'completion_tokens': 11}, 'model_name': 'text-davinci-003'} run=None
    3. The hex code of black is #000000.
    4. ​[1223]

    3.2 通过运行时的函数调用

    Model,Agent, Tool,以及 Chain 的请求执行函数都接受 callbacks 参数,比如 LLMChain 的 run 函数,OpenAI 的 predict 函数,等都能接受 callbacks 参数,在运行时指定回调处理器。

    以 OpenAI 模型类为例:

    1. timerHandler = TimerHandler()
    2. llm = OpenAI()
    3. response = llm.predict("What is the HEX code of color BLACK?", callbacks=[timerHandler])
    4. print(response)
    5. timerHandler.durations

    你应该同样看到如下输出:

    1. ['What is the HEX code of color BLACK?']
    2. generations=[[Generation(text='\n\nThe hex code of black is #000000.', generation_info={'finish_reason': 'stop', 'logprobs': None})]] llm_output={'token_usage': {'prompt_tokens': 10, 'total_tokens': 21, 'completion_tokens': 11}, 'model_name': 'text-davinci-003'} run=None
    3. The hex code of black is #000000.
    4. [1138]

    关于 Agent,Tool 等的使用,请参考官方文档API。


    作业部分!

    跟着雄哥上面的代码,跑一个简单的实例,并且截图上来!

    这是雄哥的colab地址(跑这里不算完成作业):

    https://colab.research.google.com/drive/1ThngXhcwYlYeOlk8ausJNDyuyItFDlu_?usp=sharing

    雄哥之前都说过,大模型落地有四种主流方法,LangChain就是其中之一(其他三种看下面)!

    【先导篇】0基础大模型实战!开波!"这个老板真傻!吃饭的家伙都公开!

    今天我们围绕落地一个LangChain应用为目标,展开一个为期10期的精讲!带大家0基础入门LangChain!

    本篇是第八篇!整体内容框架和介绍如下:

    【学前必看】0基础入门LangChain框架!手把手带你搭建全功能LLM应用+知识库!0/10

    第一天:0基础学LangChain!价值20万!是什么?有什么用?1/10

    第二天:0基础学LangChain!价值20万!跟大模型什么联系?两者是如何工作的?2/10

    第三天:0基础学LangChain!价值20万!数据应该怎么处理?怎样做向量化?很干!很有用!3/10

    第四天:玩转langchain!0基础做提示词模板+选择器!呆呆老板都学会了!

    第五天:第五天!玩转langchain!0基础学输出解析器!

    第六天:玩转langchain!链!非常重要!核心!把大模型们串联起来!一起工作!6/10

    第七天:玩转langchain!记忆组件!如何将LLM中的历史对话组成链!如何查询?储存?7/10

    第八天!玩转LangChain!让大模型自动推理工作?Agent就能实现了!8/10

  • 相关阅读:
    【开发技术】2万字分析shiro、spring security两大安全框架,spring session,OAuth2 入门级教程
    HMS Core音频编辑服务音源分离与空间音频渲染,助力快速进入3D音频的世界
    【es6】解决箭头函数所有的问题,箭头函数的 this 指针,使用 new 操作符
    力扣203:移除链表元素
    《Redis系列教程》
    被迫开始学习Typescript —— class
    会议OA项目之我的审批&&签字功能
    Android WebView专题
    四个,Word提高效率小技巧
    Servlet | HttpServletRequest接口、通过request接口获取请求参数
  • 原文地址:https://blog.csdn.net/javastart/article/details/133753764