跳转到主要内容

category

TL;DR:我们宣布对我们的回调系统进行改进,该系统支持日志记录、跟踪、流输出和一些很棒的第三方集成。这将更好地支持具有独立回调的并发运行,跟踪深度嵌套的LangChain组件树,以及范围为单个请求的回调处理程序(这对于在服务器上部署LangChain非常有用)。

上下文

最初,我们在LangChain中设计了回调机制,用于非异步Python应用程序。现在,我们既支持异步Python的使用,也支持JavaScript/TypeScript中的LangChain,我们需要一些更好的本地抽象,在这个新世界中,许多并发LangChain运行可以在同一线程或多个线程中进行。此外,很明显,在web环境中使用LangChain的开发人员通常希望将回调范围定为单个请求(例如,这样他们就可以将特定的句柄传递给websocket)。

变化

为了解决这些问题,我们对回调机制进行了一些更改:

  • 现在,您可以在构造函数参数(应用于所有运行)中声明您想要的回调,或者将它们直接传递给启动运行的run/call/apply方法。构造函数回调将用于对该对象进行的所有调用,并且仅限于该对象,即,如果将处理程序传递给LLMChain构造函数,则连接到该链的模型将不会使用该处理程序。
  • 请求回调将仅用于该特定请求,以及它包含的所有子请求(例如,对LLMChain的调用会触发对Model的调用,Model使用在call()方法中传递的相同处理程序)。这些都是明确传递的。一个更具体的例子是:当处理程序通过运行传递给AgentExecutor时,它将用于与代理相关的所有回调以及代理执行中涉及的所有对象,在本例中是Tools、LLMChain和LLM。以前,要使用作用域为特定代理运行的回调,该回调管理器必须附加到所有嵌套对象上——这既乏味又丑陋,而且很难重用对象。请参阅下面的TypeScript示例:
// What had to be done before for run-scoped custom callbacks. Very tedious!
const executors = [];
for (let i = 0; i < 3; i += 1) {
  const callbackManager = new CallbackManager();
  callbackManager.addHandler(new ConsoleCallbackHandler());
  callbackManager.addHandler(new LangChainTracer());

  const model = new OpenAI({ temperature: 0, callbackManager });
  const tools = [new SerpAPI(), new Calculator()];
  for (const tool of tools) {
    tool.callbackManager = callbackManager;
  }
  const executor = await initializeAgentExecutor(
    tools,
    model,
    "zero-shot-react-description",
    true,
    callbackManager
  );
  executor.agent.llmChain.callbackManager = callbackManager;
  executors.push(executor);
}

const results = await Promise.all(
  executors.map((executor) => executor.call({ input }))
);
for (const result of results) {
  console.log(`Got output ${result.output}`);
}

 

  • _Chains/LLM/Chat Models/Agents/Tools上的call、_generate、_run和等效异步方法现在接收到第二个名为runManager的参数,该参数绑定到该运行,并包含该对象可以使用的日志记录方法(即handleLLMNewToken)。例如,这在构建自定义链时很有用,您可以在此处找到更多信息。
  • verbose参数现在只是作为在JS中添加ConsoleCallbackHandler和在python中添加StdOutCallbackHandler的快捷方式,后者将事件打印到stdout。它不控制其他回调。

现在,跟踪和其他回调只适用于并发。我们还添加了一个上下文管理器,使跟踪特定的运行更加容易。

中断性更改和弃用:

  • 任何依赖LangChain之外的全局回调或全局跟踪器(即SharedCallbackManager、SharedTracer)的代码都会在python包的0.0.153版本中中断。
  • 现在不赞成将回调管理器附加到对象,请使用回调参数传入处理程序列表。
  • verbose标志现在只控制stdout和控制台回调,而不控制其他回调。

灵感

当我们对回调进行这些改进时,我们研究了一些最终影响最终API的现有解决方案,值得一提:

  • Python日志记录模块(以及其他模块),它提供了一个getChild方法,该方法返回绑定到特定上下文的新记录器。这启发了新的runManager.getChild(),您可以在实现自定义链时使用它来确保正确跟踪子运行。
  • 像express这样的Web服务器框架,每个HTTP请求特定的所有上下文都作为函数参数显式传递,而不是作为某种全局变量提供。

我们还考虑了使用某种形式的异步上下文变量的替代方案,该变量的实现存在于Python和Node.js中(但不存在于其他js环境中)。最后,我们决定采用显式函数参数方法,因为它更容易调试,并且更兼容跨平台(函数参数几乎在任何地方都可以工作)。

如果您遇到任何问题,请告诉我们,因为这是一个巨大的变化!

 

文章链接