Callback 处理
回调概念
LangChain提供了一个回调系统,允许您连接到LLM应用程序的各个阶段。这对于日志记录、监控、流式处理和其他任务非常有用。 您可以通过使用API中的<font style="color:rgb(28, 30, 33);">callbacks</font>
参数订阅这些事件。这个参数是处理程序对象的列表,这些处理程序对象应该实现下面更详细描述的一个或多个方法。
回调事件(Callback Events)
Event | Event Trigger | Associated Method |
---|---|---|
Chat model start | When a chat model starts | on_chat_model_start |
LLM start | When a llm starts | on_llm_start |
LLM new token | When an llm OR chat model emits a new token | on_llm_new_token |
LLM ends | When an llm OR chat model ends | on_llm_end |
LLM errors | When an llm OR chat model errors | on_llm_error |
Chain start | When a chain starts running | on_chain_start |
Chain end | When a chain ends | on_chain_end |
Chain error | When a chain errors | on_chain_error |
Tool start | When a tool starts running | on_tool_start |
Tool end | When a tool ends | on_tool_end |
Tool error | When a tool errors | on_tool_error |
Agent action | When an agent takes an action | on_agent_action |
Agent finish | When an agent ends | on_agent_finish |
Retriever start | When a retriever starts | on_retriever_start |
Retriever end | When a retriever ends | on_retriever_end |
Retriever error | When a retriever errors | on_retriever_error |
Text | When arbitrary text is run | on_text |
Retry | When a retry event is run | on_retry |
回调处理程序
<font style="color:rgb(28, 30, 33);">CallbackHandlers</font>
是实现了CallbackHandler接口的对象,该接口对应于可以订阅的每个事件都有一个方法。 当事件触发时,<font style="color:rgb(28, 30, 33);">CallbackManager</font>
将在每个处理程序上调用适当的方法。
#示例:callback_run.py
class BaseCallbackHandler:
"""可以用来处理langchain回调的基本回调处理程序。"""
def on_llm_start(
self, serialized: Dict[str, Any], prompts: List[str], **kwargs: Any
) -> Any:
"""LLM开始运行时运行。"""
def on_chat_model_start(
self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs: Any
) -> Any:
"""聊天模型开始运行时运行。"""
# 其他方法省略...
传递回调函数
<font style="color:rgb(28, 30, 33);">callbacks</font>
属性在 API 的大多数对象(模型、工具、代理等)中都可用,在两个不同的位置上:
- 构造函数回调:在构造函数中定义,例如
<font style="color:#080808;background-color:#ffffff;">ChatOpenAI</font><font style="color:rgb(28, 30, 33);">(callbacks=[handler], tags=['a-tag'])</font>
。在这种情况下,回调函数将用于该对象上的所有调用,并且仅限于该对象。 例如,如果你使用构造函数回调初始化了一个聊天模型,然后在链式调用中使用它,那么回调函数只会在对该模型的调用中被调用。 - 请求回调:传递给用于发出请求的
<font style="color:rgb(28, 30, 33);">invoke</font>
方法。在这种情况下,回调函数仅用于该特定请求,以及它包含的所有子请求(例如,调用触发对模型的调用的序列的调用,该模型使用在<font style="color:rgb(28, 30, 33);">invoke()</font>
方法中传递的相同处理程序)。 在<font style="color:rgb(28, 30, 33);">invoke()</font>
方法中,通过<font style="color:rgb(28, 30, 33);">config</font>
参数传递回调函数。
在运行时传递回调函数
许多情况下,当运行对象时,传递处理程序而不是回调函数会更有优势。当我们在执行运行时使用 <font style="color:rgb(28, 30, 33);">callbacks</font>
关键字参数传递 CallbackHandlers 时,这些回调函数将由执行中涉及的所有嵌套对象发出。例如,当通过一个处理程序传递给一个代理时,它将用于与代理相关的所有回调以及代理执行中涉及的所有对象,即工具和LLM。
这样可以避免我们手动将处理程序附加到每个单独的嵌套对象上。以下是一个示例:
#示例:callback_run.py
from typing import Any, Dict, List
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.messages import BaseMessage
from langchain_core.outputs import LLMResult
from langchain_core.prompts import ChatPromptTemplate
from langchain_openai import ChatOpenAI
class LoggingHandler(BaseCallbackHandler):
def on_chat_model_start(
self, serialized: Dict[str, Any], messages: List[List[BaseMessage]], **kwargs
) -> None:
print("Chat model started")
def on_llm_end(self, response: LLMResult, **kwargs) -> None:
print(f"Chat model ended, response: {
response}")
def on_chain_start(
self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs
) -> None:
print(f"Chain {
serialized.get('name')} started")
def on_chain_end(self, outputs: Dict[str, Any], **kwargs) -> None:
print(f"Chain ended, outputs: {
outputs}")
callbacks = [LoggingHandler()]
llm = ChatOpenAI(model="gpt-4")
prompt = ChatPromptTemplate.from_template("What is 1 + {number}?")
chain = prompt | llm
chain.invoke({
"number": "2"}, config={
"callbacks": callbacks})
Chain RunnableSequence started
Chain ChatPromptTemplate started
Chain ended, outputs: messages=[HumanMessage(content='What is 1 + 2?')]
Chat model started
Chat model ended, response: generations=[[ChatGeneration(text='3', generation_info={'finish_reason': 'stop', 'logprobs': None}, message=AIMessage(content='3', response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 15, 'total_tokens': 16}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None}, id='run-ef28eacd-3f1c-4d6e-80da-63453a207efe-0'))]] llm_output={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 15, 'total_tokens': 16}, 'model_name': 'gpt-4', 'system_fingerprint': None} run=None
Chain ended, outputs: content='3' response_metadata={'token_usage': {'completion_tokens': 1, 'prompt_tokens': 15, 'total_tokens': 16}, 'model_name': 'gpt-4', 'system_fingerprint': None, 'finish_reason': 'stop', 'logprobs': None} id='run-ef28eacd-3f1c-4d6e-80da-63453a207efe-0'
自定义 callback handlers自定义 Chat model
LangChain具有一些内置的回调处理程序,但通常您会希望创建具有自定义逻辑的自定义处理程序。
要创建自定义回调处理程序,我们需要确定我们希望处理的event(s),以及在触发事件时我们希望回调处理程序执行的操作。然后,我们只需将回调处理程序附加到对象上,例如通过构造函数或运行时。
在下面的示例中,我们将使用自定义处理程序实现流式处理。
在我们的自定义回调处理程序<font style="color:rgb(28, 30, 33);">MyCustomHandler</font>
中,我们实现了<font style="color:rgb(28, 30, 33);">on_llm_new_token</font>
处理程序,以打印我们刚收到的令牌。然后,我们将自定义处理程序作为构造函数回调附加到模型对象上。
#示例:callback_process.py
from langchain_openai import ChatOpenAI
from langchain_core.callbacks import BaseCallbackHandler
from langchain_core.prompts import ChatPromptTemplate
class MyCustomHandler(BaseCallbackHandler):
def on_llm_new_token(self, token: str, **kwargs) -> None:
print(f"My custom handler, token: {
token}")
prompt = ChatPromptTemplate.from_messages(["给我讲个关于{animal}的笑话,限制20个字"])
# 为启用流式处理,我们在ChatModel构造函数中传入`streaming=True`
# 另外,我们将自定义处理程序作为回调参数的列表传入
model = ChatOpenAI(
model="gpt-4", streaming=True, callbacks=[MyCustomHandler()]
)
chain = prompt | model
response = chain.invoke({
"animal": "猫"})
print(response.content)
My custom handler, token:
My custom handler, token: 猫
My custom handler, token: 对
My custo