Skip to content

Commit

Permalink
fix(anthropic): Pass back full Anthropic content for stream events (#…
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoblee93 authored Oct 17, 2024
1 parent 9c5c7e9 commit 9678c8a
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 5 deletions.
16 changes: 11 additions & 5 deletions libs/langchain-anthropic/src/chat_models.ts
Original file line number Diff line number Diff line change
Expand Up @@ -818,7 +818,7 @@ export class ChatAnthropicMessages<

// Extract the text content token for text field and runManager.
const token = extractToken(chunk);
yield new ChatGenerationChunk({
const generationChunk = new ChatGenerationChunk({
message: new AIMessageChunk({
// Just yield chunk as it is and tool_use will be concat by BaseChatModel._generateUncached().
content: chunk.content,
Expand All @@ -830,10 +830,16 @@ export class ChatAnthropicMessages<
}),
text: token ?? "",
});

if (token) {
await runManager?.handleLLMNewToken(token);
}
yield generationChunk;

await runManager?.handleLLMNewToken(
token ?? "",
undefined,
undefined,
undefined,
undefined,
{ chunk: generationChunk }
);
}
}

Expand Down
68 changes: 68 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 @@ -11,6 +11,7 @@ import { StructuredTool, tool } from "@langchain/core/tools";
import { concat } from "@langchain/core/utils/stream";
import { z } from "zod";
import { zodToJsonSchema } from "zod-to-json-schema";
import { RunnableLambda } from "@langchain/core/runnables";
import { ChatAnthropic } from "../chat_models.js";
import { AnthropicToolResponse } from "../types.js";

Expand Down Expand Up @@ -202,6 +203,73 @@ test("Can bind & stream AnthropicTools", async () => {
expect(args.location).toBeTruthy();
});

test("stream events with no tool calls has string message content", async () => {
const wrapper = RunnableLambda.from(async (_, config) => {
const res = await model.invoke(
"What is the weather in London today?",
config
);
return res;
});
const eventStream = await wrapper.streamEvents(
"What is the weather in London today?",
{
version: "v2",
}
);

const chatModelStreamEvents = [];
for await (const event of eventStream) {
if (event.event === "on_chat_model_stream") {
chatModelStreamEvents.push(event);
}
}
expect(chatModelStreamEvents.length).toBeGreaterThan(0);
expect(
chatModelStreamEvents.every(
(event) => typeof event.data.chunk.content === "string"
)
).toBe(true);
});

test("stream events with tool calls has raw message content", async () => {
const modelWithTools = model.bind({
tools: [anthropicTool],
tool_choice: {
type: "tool",
name: "get_weather",
},
});

const wrapper = RunnableLambda.from(async (_, config) => {
const res = await modelWithTools.invoke(
"What is the weather in London today?",
config
);
return res;
});
const eventStream = await wrapper.streamEvents(
"What is the weather in London today?",
{
version: "v2",
}
);

const chatModelStreamEvents = [];
for await (const event of eventStream) {
if (event.event === "on_chat_model_stream") {
console.log(event);
chatModelStreamEvents.push(event);
}
}
expect(chatModelStreamEvents.length).toBeGreaterThan(0);
expect(
chatModelStreamEvents.every((event) =>
Array.isArray(event.data.chunk.content)
)
).toBe(true);
});

test("withStructuredOutput with zod schema", async () => {
const modelWithTools = model.withStructuredOutput<{ location: string }>(
zodSchema,
Expand Down

0 comments on commit 9678c8a

Please sign in to comment.