From 11b7b82b2192d0d752bcdb4a858aafcc20b74cf5 Mon Sep 17 00:00:00 2001 From: jacoblee93 Date: Wed, 10 Apr 2024 16:14:47 -0700 Subject: [PATCH] Only populate tool params if sensible --- libs/langchain-anthropic/src/chat_models.ts | 45 +++++++++++-------- .../src/tests/chat_models-tools.int.test.ts | 20 +++++---- 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/libs/langchain-anthropic/src/chat_models.ts b/libs/langchain-anthropic/src/chat_models.ts index ae8db9c80b80..6a8253b51593 100644 --- a/libs/langchain-anthropic/src/chat_models.ts +++ b/libs/langchain-anthropic/src/chat_models.ts @@ -331,29 +331,35 @@ function _formatMessagesForAnthropic(messages: BaseMessage[]): { throw new Error(`Message type "${message._getType()}" is not supported.`); } if (isAIMessage(message) && !!message.tool_calls?.length) { - const rawContent = _formatContent(message.content); - if (typeof rawContent === "string") { + if (message.content === "") { return { role, - content: [ - { type: "text", text: rawContent }, - ...message.tool_calls.map(_convertLangChainToolCallToAnthropic), - ], + content: message.tool_calls.map(_convertLangChainToolCallToAnthropic), + }; + } else if (typeof message.content === "string") { + console.warn( + `The "tool_calls" field on a message is only respected if content is an empty string.` + ); + return { + role, + content: _formatContent(message.content), }; } else { - const missingToolCallBlocks = message.tool_calls.filter( - (toolCall) => - !!rawContent.find( - (contentPart) => - contentPart === "tool_use" && toolCall.id === contentPart.id - ) + const { content } = message; + const hasMismatchedToolCalls = !message.tool_calls.every((toolCall) => + content.find( + (contentPart) => + contentPart.type === "tool_use" && contentPart.id === toolCall.id + ) ); + if (hasMismatchedToolCalls) { + console.warn( + `The "tool_calls" field on a message is only respected if content is an empty string.` + ); + } return { role, - content: [ - ...rawContent, - ...missingToolCallBlocks.map(_convertLangChainToolCallToAnthropic), - ], + content: _formatContent(message.content), }; } } else { @@ -601,11 +607,12 @@ export class ChatAnthropicMessages< runManager?: CallbackManagerForLLMRun ): AsyncGenerator { const params = this.invocationParams(options); + const formattedMessages = _formatMessagesForAnthropic(messages); const requestOptions = this.invocationOptions( { ...params, stream: false, - ..._formatMessagesForAnthropic(messages), + ...formattedMessages, }, options ); @@ -614,7 +621,7 @@ export class ChatAnthropicMessages< { ...params, stream: false, - ..._formatMessagesForAnthropic(messages), + ...formattedMessages, }, options ); @@ -644,7 +651,7 @@ export class ChatAnthropicMessages< const stream = await this.createStreamWithRetry( { ...params, - ..._formatMessagesForAnthropic(messages), + ...formattedMessages, stream: true, }, requestOptions diff --git a/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts b/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts index 87447b1e681d..b5be633974e0 100644 --- a/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts +++ b/libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts @@ -58,11 +58,11 @@ test("Few shotting with tool calls", async () => { const res = await chat.invoke([ new HumanMessage("What is the weather in SF?"), new AIMessage({ - content: "Let me look that up!", + content: "", tool_calls: [ { id: "toolu_feiwjf9u98r389u498", - name: "get_current_weather", + name: "get_weather", args: { location: "SF", }, @@ -88,7 +88,7 @@ test("Can bind & invoke StructuredTools", async () => { const modelWithTools = model.bindTools(tools); const result = await modelWithTools.invoke( - "What is the weather in London today?" + "What is the weather in SF today?" ); console.log( { @@ -116,17 +116,21 @@ test("Can bind & invoke StructuredTools", async () => { expect(input).toBeTruthy(); expect(input.location).toBeTruthy(); const result2 = await modelWithTools.invoke([ - new HumanMessage("What is the weather in London today?"), + new HumanMessage("What is the weather in SF today?"), result, new ToolMessage({ tool_call_id: result.tool_calls?.[0].id ?? "", - content: "The weather in London is currently 98 degrees and sunny.", + content: + "The weather in San Francisco is currently 59 degrees and sunny.", }), - new AIMessage("The weather in London is currently 98 degrees and sunny."), - new HumanMessage("What did you just say the weather was?"), + new AIMessage( + "The weather in San Francisco is currently 59 degrees and sunny." + ), + new HumanMessage("What did you say the weather was?"), ]); console.log(result2); - expect(result2.content).toContain("98"); + // This should work, but Anthorpic is too skeptical + expect(result2.content).toContain("59"); }); test("Can bind & invoke AnthropicTools", async () => {