Skip to content

Commit

Permalink
Properly populate usage_metadata for Anthropic models
Browse files Browse the repository at this point in the history
  • Loading branch information
jacoblee93 committed Dec 16, 2024
1 parent 6975bcd commit fdff5b5
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 19 deletions.
2 changes: 1 addition & 1 deletion libs/langchain-anthropic/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
"author": "LangChain",
"license": "MIT",
"dependencies": {
"@anthropic-ai/sdk": "^0.27.3",
"@anthropic-ai/sdk": "^0.32.1",
"fast-xml-parser": "^4.4.1",
"zod": "^3.22.4",
"zod-to-json-schema": "^3.22.4"
Expand Down
31 changes: 15 additions & 16 deletions libs/langchain-anthropic/src/tests/chat_models.int.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ test("Test ChatAnthropic", async () => {
});
const message = new HumanMessage("Hello!");
const res = await chat.invoke([message]);
// console.log({ res });
expect(res.response_metadata.usage).toBeDefined();
});

Expand Down Expand Up @@ -713,12 +712,12 @@ test("system prompt caching", async () => {
];
const res = await model.invoke(messages);
expect(
res.response_metadata.usage.cache_creation_input_tokens
res.usage_metadata?.input_token_details?.cache_creation
).toBeGreaterThan(0);
expect(res.response_metadata.usage.cache_read_input_tokens).toBe(0);
expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
const res2 = await model.invoke(messages);
expect(res2.response_metadata.usage.cache_creation_input_tokens).toBe(0);
expect(res2.response_metadata.usage.cache_read_input_tokens).toBeGreaterThan(
expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
0
);
const stream = await model.stream(messages);
Expand All @@ -727,8 +726,8 @@ test("system prompt caching", async () => {
agg = agg === undefined ? chunk : concat(agg, chunk);
}
expect(agg).toBeDefined();
expect(agg!.response_metadata.usage.cache_creation_input_tokens).toBe(0);
expect(agg!.response_metadata.usage.cache_read_input_tokens).toBeGreaterThan(
expect(agg!.usage_metadata?.input_token_details?.cache_creation).toBe(0);
expect(agg!.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
0
);
});
Expand Down Expand Up @@ -771,12 +770,12 @@ test.skip("tool caching", async () => {
const res = await model.invoke(messages);
console.log(res);
expect(
res.response_metadata.usage.cache_creation_input_tokens
res.usage_metadata?.input_token_details?.cache_creation
).toBeGreaterThan(0);
expect(res.response_metadata.usage.cache_read_input_tokens).toBe(0);
expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
const res2 = await model.invoke(messages);
expect(res2.response_metadata.usage.cache_creation_input_tokens).toBe(0);
expect(res2.response_metadata.usage.cache_read_input_tokens).toBeGreaterThan(
expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
0
);
});
Expand All @@ -791,7 +790,7 @@ test.skip("Test ChatAnthropic with custom client", async () => {
const message = new HumanMessage("Hello!");
const res = await chat.invoke([message]);
// console.log({ res });
expect(res.response_metadata.usage).toBeDefined();
expect(res.usage_metadata?.input_token_details).toBeDefined();
});

test("human message caching", async () => {
Expand Down Expand Up @@ -826,12 +825,12 @@ test("human message caching", async () => {

const res = await model.invoke(messages);
expect(
res.response_metadata.usage.cache_creation_input_tokens
res.usage_metadata?.input_token_details?.cache_creation
).toBeGreaterThan(0);
expect(res.response_metadata.usage.cache_read_input_tokens).toBe(0);
expect(res.usage_metadata?.input_token_details?.cache_read).toBe(0);
const res2 = await model.invoke(messages);
expect(res2.response_metadata.usage.cache_creation_input_tokens).toBe(0);
expect(res2.response_metadata.usage.cache_read_input_tokens).toBeGreaterThan(
expect(res2.usage_metadata?.input_token_details?.cache_creation).toBe(0);
expect(res2.usage_metadata?.input_token_details?.cache_read).toBeGreaterThan(
0
);
});
18 changes: 17 additions & 1 deletion libs/langchain-anthropic/src/utils/message_outputs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,17 @@ export function _makeMessageChunkFromAnthropicEvent(
filteredAdditionalKwargs[key] = value;
}
}
const { input_tokens, output_tokens, ...rest } = usage ?? {};
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const { input_tokens, output_tokens, ...rest }: Record<string, any> =
usage ?? {};
const usageMetadata: UsageMetadata = {
input_tokens,
output_tokens,
total_tokens: input_tokens + output_tokens,
input_token_details: {
cache_creation: rest.cache_creation_input_tokens,
cache_read: rest.cache_read_input_tokens,
},
};
return {
chunk: new AIMessageChunk({
Expand All @@ -54,6 +60,12 @@ export function _makeMessageChunkFromAnthropicEvent(
input_tokens: 0,
output_tokens: data.usage.output_tokens,
total_tokens: data.usage.output_tokens,
input_token_details: {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cache_creation: (data.usage as any).cache_creation_input_tokens,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
cache_read: (data.usage as any).cache_read_input_tokens,
},
};
return {
chunk: new AIMessageChunk({
Expand Down Expand Up @@ -171,6 +183,10 @@ export function anthropicResponseToChatMessages(
input_tokens: usage.input_tokens ?? 0,
output_tokens: usage.output_tokens ?? 0,
total_tokens: (usage.input_tokens ?? 0) + (usage.output_tokens ?? 0),
input_token_details: {
cache_creation: usage.cache_creation_input_tokens,
cache_read: usage.cache_read_input_tokens,
},
}
: undefined;
if (messages.length === 1 && messages[0].type === "text") {
Expand Down
17 changes: 16 additions & 1 deletion yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,21 @@ __metadata:
languageName: node
linkType: hard

"@anthropic-ai/sdk@npm:^0.32.1":
version: 0.32.1
resolution: "@anthropic-ai/sdk@npm:0.32.1"
dependencies:
"@types/node": ^18.11.18
"@types/node-fetch": ^2.6.4
abort-controller: ^3.0.0
agentkeepalive: ^4.2.1
form-data-encoder: 1.7.2
formdata-node: ^4.3.2
node-fetch: ^2.6.7
checksum: b48982e0ce066c99afe19448c5d6b38916c2c8873fbdcd4e5116abc45bcf241359604684856bfbd20fcfe00bf544d6d6e7bcf2686a9eb198bd671839b5cd0a67
languageName: node
linkType: hard

"@anthropic-ai/vertex-sdk@npm:^0.4.1":
version: 0.4.1
resolution: "@anthropic-ai/vertex-sdk@npm:0.4.1"
Expand Down Expand Up @@ -11478,7 +11493,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "@langchain/anthropic@workspace:libs/langchain-anthropic"
dependencies:
"@anthropic-ai/sdk": ^0.27.3
"@anthropic-ai/sdk": ^0.32.1
"@anthropic-ai/vertex-sdk": ^0.4.1
"@jest/globals": ^29.5.0
"@langchain/core": "workspace:*"
Expand Down

0 comments on commit fdff5b5

Please sign in to comment.