检查其他资源
- 为这个问题添加了一个非常描述性的标题。
- 使用集成搜索在LangChain文档中进行了搜索。
- 使用GitHub搜索查找类似的问题,但没有找到。
- 我确信这是LangChain中的一个bug,而不是我的代码。
- 通过更新到LangChain的最新稳定版本(或特定集成包)无法解决此bug。
示例代码
设置:
from typing import Any, Dict, List, Optional
from langchain.chat_models import ChatOpenA
from langchain_core.callbacks.base import BaseCallbackHandler, BaseCallbackManager
from langchain_core.output_parsers import StrOutputParser
from langchain.prompts import PromptTemplate
prompt = PromptTemplate(
input_variables=["question"],
template="Answer this question: {question}",
)
model = prompt | ChatOpenAI(temperature=0) | StrOutputParser()
from typing import Any, Dict, List, Optional
from langchain_core.callbacks.base import (
AsyncCallbackHandler,
BaseCallbackHandler,
BaseCallbackManager,
)
class CustomCallbackHandler(BaseCallbackHandler):
def on_chain_start(self, serialized: Dict[str, Any], inputs: Dict[str, Any], **kwargs: Any) -> None:
print("chain_start")
def on_chain_end(self, outputs: Dict[str, Any], **kwargs: Any) -> None:
print("chain_end")
通过回调列表调用 => 每条链事件打印三次。
model.invoke("Hi", config={"callbacks": [CustomCallbackHandler()]})
# > Output:
# chain_start
# chain_start
# chain_end
# chain_start
# chain_end
# chain_end
# 'Hello! How can I assist you today?'
通过回调管理器调用 => 仅打印一次链事件
model.invoke("Hi", config={"callbacks": BaseCallbackManager([CustomCallbackHandler()])})
# > Output:
# chain_start
# chain_end
# 'Hello! How can I assist you today?'
错误信息和堆栈跟踪(如有)
NA
描述
当将回调传递给可运行对象的 .invoke
方法时,有两种方法可以这样做:
- 作为列表传递:
model.invoke("Hi", config={"callbacks": [CustomCallbackHandler()]})
- 作为回调管理器传递:
model.invoke("Hi", config={"callbacks": BaseCallbackManager([CustomCallbackHandler()])})
然而,两者的行为是不同的。前者触发处理程序的次数比后者多。
系统信息
系统信息
操作系统:Linux
操作系统版本: #70 ~20.04.1-Ubuntu SMP Fri Jun 14 15:42:13 UTC 2024
Python版本:3.11.0rc1(主版本,8月12日2022,10:02:14) [GCC 11.2.0]
软件包信息
langchain_core: 0.2.23
langchain: 0.2.10
langchain_community: 0.0.38
langsmith: 0.1.93
langchain_openai: 0.1.17
langchain_text_splitters: 0.2.2
没有安装的软件包(不一定是个问题)
以下软件包未找到:
langgraph
langserve
7条答案
按热度按时间voj3qocg1#
我明白差异的原因
分支用于处理程序列表,这里的处理程序和可继承的处理程序都设置为处理程序列表。
分支用于回调管理器,这里的可继承的处理程序设置为回调管理器的可继承处理程序,这没什么意义。
步骤调用当步骤(提示、llm等)被调用时,只有可继承的处理程序传递给它们。
话虽如此,我不知道如何正确修复它
nkkqxpd92#
实际上,这里可能没有什么需要修复的。guide 在这里接收一个处理器列表,并在每次调用步骤(提示、llm 等)时输出 "chain start"。
zujrkrfu3#
感谢你的调查,@wulifu2hao。
是的,处理程序列表可以正常工作,但我不明白为什么回调管理器分支是这样实现的。逻辑完全忽略了传递给
_configure
函数的inheritable_callbacks
参数,这似乎不正确,因为那时它已经不再是“可继承”的了。L2149应该合并inheritable_callbacks
和callback_manager.inheritable_callbacks
。或者有其他特定原因没有这样做吗?ffvjumwh4#
我不确定我是否理解得正确...
我的理解是,CallbackManager的构造函数接收参数
inheritable_callbacks
,这似乎意味着"在构造这个新的回调管理器时要继承的回调管理器或回调列表"。从这个意义上说,第2148行和第2149行似乎是正确的:在构造新的回调管理器时,它会复制
handlers
以及inheritable_handlers
。bhmjp9jg5#
对不起,似乎我误解了一点。所以现在
_configure
正在做的事情是:inheritable_callbacks
传递的处理程序列表 => 继承inheritable_callbacks
传递的callback_manager.inheritable_handlers
=> 继承inheritable_callbacks
传递的callback_manager.handlers
=> 不继承我觉得最让我困惑的是第三种情况。guide 提到通过
callbacks
kwargs 传递的回调将传播到所有嵌套对象。它没有解释回调管理器handlers
和inheritable_handlers
字段之间的区别。但在将其归咎于文档问题之前,我很好奇
BaseCallbackManager
是否不是为用户传递他们的回调而设计的?换句话说,它只是用于在内部传递回调,用户应该只在他们的代码中传递回调列表吗?如果是这样,我同意我们不需要任何修复。我只是使用了
BaseCallbackManager
遵循一些互联网示例,但这可能不是预期的使用方式。xtupzzrd6#
我怀疑BaseCallbackManager仅供内部使用,因为RunnableConfig中的回调被定义为处理器列表和BaseCallbackManager的联合体,因此用户将其用作RunnableConfig的回调应该是合理的。
也许文档中缺少对这些字段含义的明确解释?
fquxozlt7#
有道理。那么在这里的行动是为the callback guide中的行为的添加一个备注。我可以在几天内进行更新。听起来怎么样?@wulifu2hao