Skip to content

Commit

Permalink
anthropic[patch]: ensure content exists when parsing tool tokens (#6183)
Browse files Browse the repository at this point in the history
* ensure content exists

* format and add test

* greater than or equal

---------

Co-authored-by: Shmuel Lamm <shmuellamm@gmail.com>
Co-authored-by: bracesproul <braceasproul@gmail.com>
  • Loading branch information
3 people authored Jul 23, 2024
1 parent aa49f8f commit 4bd708f
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 1 deletion.
6 changes: 5 additions & 1 deletion libs/langchain-anthropic/src/chat_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,11 @@ function extractToolCallChunk(
function extractToken(chunk: AIMessageChunk): string | undefined {
if (typeof chunk.content === "string") {
return chunk.content;
} else if (Array.isArray(chunk.content) && "input" in chunk.content[0]) {
} else if (
Array.isArray(chunk.content) &&
chunk.content.length >= 1 &&
"input" in chunk.content[0]
) {
return typeof chunk.content[0].input === "string"
? chunk.content[0].input
: JSON.stringify(chunk.content[0].input);
Expand Down
38 changes: 38 additions & 0 deletions libs/langchain-anthropic/src/tests/chat_models-tools.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -402,3 +402,41 @@ test("Can stream tool calls", async () => {
expect(finalChunk?.tool_calls?.[0].args.location).toBeDefined();
expect(realToolCallChunkStreams).toBeGreaterThan(1);
});

test("llm token callbacks can handle tool calls", async () => {
const weatherTool = tool((_) => "no-op", {
name: "get_weather",
description: zodSchema.description,
schema: zodSchema,
});

const modelWithTools = model.bindTools([weatherTool], {
tool_choice: {
type: "tool",
name: "get_weather",
},
});

let tokens = "";
const stream = await modelWithTools.stream("What is the weather in SF?", {
callbacks: [
{
handleLLMNewToken: (tok) => {
tokens += tok;
},
},
],
});

let finalChunk: AIMessageChunk | undefined;
for await (const chunk of stream) {
finalChunk = !finalChunk ? chunk : concat(finalChunk, chunk);
}

expect(finalChunk?.tool_calls?.[0]).toBeDefined();
expect(finalChunk?.tool_calls?.[0].name).toBe("get_weather");
expect(finalChunk?.tool_calls?.[0].args).toBeDefined();
const args = finalChunk?.tool_calls?.[0].args;
if (!args) return;
expect(args).toEqual(JSON.parse(tokens));
});

0 comments on commit 4bd708f

Please sign in to comment.