javascript LangChain在使用代理内存时丢失上下文和超时

vsaztqbk  于 2023-05-12  发布在  Java
关注(0)|答案(2)|浏览(259)

bounty已结束。回答此问题可获得+50声望奖励。赏金宽限期20小时后结束。jeznag希望引起更多关注这个问题。

我有一个函数,它初始化一个代理,并发出一个调用来获取生成的回复。它使用一个工具,从用户的输入创建结构化的输出。在没有任何内存上下文的情况下使用它可以很好地工作-在+- 4秒内以预期的格式返回响应。LangChain文档指出,我使用的代理默认使用BufferMemory,所以我创建了一个BufferMemory示例并将其分配给代理执行器示例,这导致响应超时,响应时间超过一分钟。默认情况下,LangChain会记录这个过程,我可以看到正确的输出记录在终端中,尽管它没有返回。在此之后,代理似乎丢失了问题的上下文,然后最终以错误的格式输出答案。只有当我删除了后端的超时限制时,它才最终返回输出。

const activityTextParser = StructuredOutputParser.fromNamesAndDescriptions({
      name: "name of user's activity",
      duration: "time duration in seconds of user's activity",
    });
    const activityFormatInstructions =
      activityTextParser.getFormatInstructions();
    const activityPrompt = new PromptTemplate({
      template:
        "Structure the output based on user's input.\n{format_instructions}\n{instruction}",
      inputVariables: ['instruction'],
      partialVariables: { format_instructions: activityFormatInstructions },
    });
    const model = new ChatOpenAI({
      openAIApiKey: process.env.OPENAI_API_KEY,
      temperature: 0,
    });
    const activityTool = new DynamicTool({
      name: 'Create activity tool',
      description: 'Uses user input to create activity JSON object',
      func: async (text: string) => {
        const input = await activityPrompt.format({
          instruction: text,
        });
        return input;
      },
    });
    const tools = [activityTool];
    const executor = await initializeAgentExecutorWithOptions(tools, model, {
      agentType: 'chat-conversational-react-description',
      verbose: true,
    });
    const chatHistory = [
      new AIChatMessage(
        'Hi there! I am your productivity assistant, how can I help you today?',
      ),
    ];
    const memory = new BufferMemory({
      chatHistory: new ChatMessageHistory(chatHistory),
      memoryKey: 'chat_history',
      returnMessages: true,
    });
    executor.memory = memory;
    const res = await executor.call({
      input: 'Create an activity named Reading that lasts for 10 minutes',
    });
    console.log({ res });
    return res;

注解掉executor.memory = memory行后,将按预期返回输出
这就是预期的输出:

"output": {
        "name": "Reading",
        "duration": "600"
    }

当代理丢失上下文并提醒自己问题时,输出的格式如下:

{
    "output": "The activity named Reading lasts for 10 minutes."
}

一个最小可重复的例子是here。请注意,需要Node版本18或更高版本
下面的屏幕截图是使用内存时记录的内容的示例,并且似乎在未返回预期值之后生成了预期值,但上下文丢失了x1c 0d1x
任何关于如何正确使用会话历史与输出解析工具相结合的建议都将受到欢迎。TIA

qxsslcnc

qxsslcnc1#

与直接从www.example.com()访问输出不同executor.call,您可以在进行呼叫后从聊天历史记录中检索它。下面是包含这种方法的代码的更新版本:

const res = await executor.call({
  input: 'Create an activity named Reading that lasts for 10 minutes',
});

// Get the response from chat history
const responseMessage = memory.chatHistory.lastAgentMessage();
const output = responseMessage.output;

console.log({ output });
return output;

通过访问聊天历史记录中的最后一条座席消息,可以检索生成的输出。这样,您就能够以所需的格式检索预期的响应。
给予这个修改,看看它是否解决了你面临的问题。

mtb9vblg

mtb9vblg2#

看起来问题可能与BufferMemory的使用方式有关。BufferMemory设计用于存储会话历史和会话中各轮之间的上下文,但在提供的代码中,它仅使用chatHistory中的单个消息进行初始化。当代理尝试使用内存来检索当前回合的上下文时,这可能会导致问题。
一个可能的解决方案是使用更完整的聊天历史来初始化BufferMemory,包括对话中的先前回合。这将允许智能体从较早的回合中检索上下文,并潜在地提高其响应的准确性。
另一种可能的解决方案是使用不同类型的存储器,例如RedisMemory或MongoDBMemory,它们旨在处理更大量的数据,并且可能更适合存储会话历史。
还值得注意的是,该问题可能与所使用的DynamicTool的特定实现有关,因此可能值得探索替代实现或调试工具代码以查看是否存在任何问题。
总的来说,如果没有关于特定用例和需求的更多信息,很难提供一个明确的解决方案,但希望这些建议可以帮助指出正确的方向。

相关问题