@langchain/anthropic 0.2.1 → 0.2.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,6 +6,7 @@ const messages_1 = require("@langchain/core/messages");
6
6
  const outputs_1 = require("@langchain/core/outputs");
7
7
  const env_1 = require("@langchain/core/utils/env");
8
8
  const chat_models_1 = require("@langchain/core/language_models/chat_models");
9
+ const base_1 = require("@langchain/core/language_models/base");
9
10
  const zod_to_json_schema_1 = require("zod-to-json-schema");
10
11
  const runnables_1 = require("@langchain/core/runnables");
11
12
  const types_1 = require("@langchain/core/utils/types");
@@ -380,6 +381,12 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
380
381
  writable: true,
381
382
  value: void 0
382
383
  });
384
+ Object.defineProperty(this, "streamUsage", {
385
+ enumerable: true,
386
+ configurable: true,
387
+ writable: true,
388
+ value: true
389
+ });
383
390
  this.anthropicApiKey =
384
391
  fields?.apiKey ??
385
392
  fields?.anthropicApiKey ??
@@ -403,11 +410,12 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
403
410
  this.stopSequences = fields?.stopSequences ?? this.stopSequences;
404
411
  this.streaming = fields?.streaming ?? false;
405
412
  this.clientOptions = fields?.clientOptions ?? {};
413
+ this.streamUsage = fields?.streamUsage ?? this.streamUsage;
406
414
  }
407
415
  getLsParams(options) {
408
416
  const params = this.invocationParams(options);
409
417
  return {
410
- ls_provider: "openai",
418
+ ls_provider: "anthropic",
411
419
  ls_model_name: this.model,
412
420
  ls_model_type: "chat",
413
421
  ls_temperature: params.temperature ?? undefined,
@@ -432,8 +440,17 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
432
440
  return tools;
433
441
  }
434
442
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
443
+ if (tools.every((tool) => (0, base_1.isOpenAITool)(tool))) {
444
+ // Formatted as OpenAI tool, convert to Anthropic tool
445
+ return tools.map((tc) => ({
446
+ name: tc.function.name,
447
+ description: tc.function.description,
448
+ input_schema: tc.function.parameters,
449
+ }));
450
+ }
451
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
435
452
  if (tools.some((tool) => isAnthropicTool(tool))) {
436
- throw new Error(`Can not pass in a mix of AnthropicTools and StructuredTools`);
453
+ throw new Error(`Can not pass in a mix of tool schemas to ChatAnthropic`);
437
454
  }
438
455
  return tools.map((tool) => ({
439
456
  name: tool.name,
@@ -542,19 +559,37 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
542
559
  }
543
560
  }
544
561
  usageData = usage;
562
+ let usageMetadata;
563
+ if (this.streamUsage || options.streamUsage) {
564
+ usageMetadata = {
565
+ input_tokens: usage.input_tokens,
566
+ output_tokens: usage.output_tokens,
567
+ total_tokens: usage.input_tokens + usage.output_tokens,
568
+ };
569
+ }
545
570
  yield new outputs_1.ChatGenerationChunk({
546
571
  message: new messages_1.AIMessageChunk({
547
572
  content: "",
548
573
  additional_kwargs: filteredAdditionalKwargs,
574
+ usage_metadata: usageMetadata,
549
575
  }),
550
576
  text: "",
551
577
  });
552
578
  }
553
579
  else if (data.type === "message_delta") {
580
+ let usageMetadata;
581
+ if (this.streamUsage || options.streamUsage) {
582
+ usageMetadata = {
583
+ input_tokens: data.usage.output_tokens,
584
+ output_tokens: 0,
585
+ total_tokens: data.usage.output_tokens,
586
+ };
587
+ }
554
588
  yield new outputs_1.ChatGenerationChunk({
555
589
  message: new messages_1.AIMessageChunk({
556
590
  content: "",
557
591
  additional_kwargs: { ...data.delta },
592
+ usage_metadata: usageMetadata,
558
593
  }),
559
594
  text: "",
560
595
  });
@@ -562,7 +597,8 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
562
597
  usageData.output_tokens += data.usage.output_tokens;
563
598
  }
564
599
  }
565
- else if (data.type === "content_block_delta") {
600
+ else if (data.type === "content_block_delta" &&
601
+ data.delta.type === "text_delta") {
566
602
  const content = data.delta?.text;
567
603
  if (content !== undefined) {
568
604
  yield new outputs_1.ChatGenerationChunk({
@@ -576,10 +612,19 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
576
612
  }
577
613
  }
578
614
  }
615
+ let usageMetadata;
616
+ if (this.streamUsage || options.streamUsage) {
617
+ usageMetadata = {
618
+ input_tokens: usageData.input_tokens,
619
+ output_tokens: usageData.output_tokens,
620
+ total_tokens: usageData.input_tokens + usageData.output_tokens,
621
+ };
622
+ }
579
623
  yield new outputs_1.ChatGenerationChunk({
580
624
  message: new messages_1.AIMessageChunk({
581
625
  content: "",
582
626
  additional_kwargs: { usage: usageData },
627
+ usage_metadata: usageMetadata,
583
628
  }),
584
629
  text: "",
585
630
  });
@@ -4,20 +4,13 @@ import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
4
4
  import { AIMessageChunk, type BaseMessage } from "@langchain/core/messages";
5
5
  import { ChatGeneration, ChatGenerationChunk, type ChatResult } from "@langchain/core/outputs";
6
6
  import { BaseChatModel, LangSmithParams, type BaseChatModelParams } from "@langchain/core/language_models/chat_models";
7
- import { StructuredOutputMethodOptions, type BaseLanguageModelCallOptions, BaseLanguageModelInput } from "@langchain/core/language_models/base";
7
+ import { type StructuredOutputMethodOptions, type BaseLanguageModelCallOptions, type BaseLanguageModelInput, type ToolDefinition } from "@langchain/core/language_models/base";
8
8
  import { StructuredToolInterface } from "@langchain/core/tools";
9
9
  import { Runnable } from "@langchain/core/runnables";
10
10
  import { ToolCall } from "@langchain/core/messages/tool";
11
11
  import { z } from "zod";
12
+ import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/index.mjs";
12
13
  import { AnthropicToolResponse } from "./types.js";
13
- type AnthropicTool = {
14
- name: string;
15
- description: string;
16
- /**
17
- * JSON schema.
18
- */
19
- input_schema: Record<string, unknown>;
20
- };
21
14
  type AnthropicMessageCreateParams = Anthropic.MessageCreateParamsNonStreaming;
22
15
  type AnthropicStreamingMessageCreateParams = Anthropic.MessageCreateParamsStreaming;
23
16
  type AnthropicMessageStreamEvent = Anthropic.MessageStreamEvent;
@@ -26,8 +19,8 @@ type AnthropicToolChoice = {
26
19
  type: "tool";
27
20
  name: string;
28
21
  } | "any" | "auto";
29
- export interface ChatAnthropicCallOptions extends BaseLanguageModelCallOptions {
30
- tools?: (StructuredToolInterface | AnthropicTool)[];
22
+ export interface ChatAnthropicCallOptions extends BaseLanguageModelCallOptions, Pick<AnthropicInput, "streamUsage"> {
23
+ tools?: (StructuredToolInterface | AnthropicTool | Record<string, unknown> | ToolDefinition)[];
31
24
  /**
32
25
  * Whether or not to specify what tool the model should use
33
26
  * @default "auto"
@@ -89,6 +82,11 @@ export interface AnthropicInput {
89
82
  * `anthropic.messages`} that are not explicitly specified on this class.
90
83
  */
91
84
  invocationKwargs?: Kwargs;
85
+ /**
86
+ * Whether or not to include token usage data in streamed chunks.
87
+ * @default true
88
+ */
89
+ streamUsage?: boolean;
92
90
  }
93
91
  /**
94
92
  * A type representing additional parameters that can be passed to the
@@ -141,6 +139,7 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
141
139
  clientOptions: ClientOptions;
142
140
  protected batchClient: Anthropic;
143
141
  protected streamingClient: Anthropic;
142
+ streamUsage: boolean;
144
143
  constructor(fields?: Partial<AnthropicInput> & BaseChatModelParams);
145
144
  getLsParams(options: this["ParsedCallOptions"]): LangSmithParams;
146
145
  /**
@@ -151,20 +150,22 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
151
150
  * @throws {Error} If a mix of AnthropicTools and StructuredTools are passed.
152
151
  */
153
152
  formatStructuredToolToAnthropic(tools: ChatAnthropicCallOptions["tools"]): AnthropicTool[] | undefined;
154
- bindTools(tools: (AnthropicTool | StructuredToolInterface)[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
153
+ bindTools(tools: (AnthropicTool | Record<string, unknown> | StructuredToolInterface | ToolDefinition)[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
155
154
  /**
156
155
  * Get the parameters used to invoke the model
157
156
  */
158
157
  invocationParams(options?: this["ParsedCallOptions"]): Omit<AnthropicMessageCreateParams | AnthropicStreamingMessageCreateParams, "messages"> & Kwargs;
159
158
  /** @ignore */
160
159
  _identifyingParams(): {
161
- system?: string | undefined;
160
+ tools?: Anthropic.Messages.Tool[] | undefined;
161
+ tool_choice?: Anthropic.Messages.MessageCreateParams.ToolChoiceAuto | Anthropic.Messages.MessageCreateParams.ToolChoiceAny | Anthropic.Messages.MessageCreateParams.ToolChoiceTool | undefined;
162
162
  metadata?: Anthropic.Messages.MessageCreateParams.Metadata | undefined;
163
+ temperature?: number | undefined;
164
+ model: "claude-2.1" | (string & {}) | "claude-3-opus-20240229" | "claude-3-sonnet-20240229" | "claude-3-haiku-20240307" | "claude-2.0" | "claude-instant-1.2";
165
+ system?: string | undefined;
163
166
  stream?: boolean | undefined;
164
167
  max_tokens: number;
165
- model: "claude-2.1" | (string & {}) | "claude-3-opus-20240229" | "claude-3-sonnet-20240229" | "claude-3-haiku-20240307" | "claude-2.0" | "claude-instant-1.2";
166
168
  stop_sequences?: string[] | undefined;
167
- temperature?: number | undefined;
168
169
  top_k?: number | undefined;
169
170
  top_p?: number | undefined;
170
171
  model_name: string;
@@ -173,13 +174,15 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
173
174
  * Get the identifying parameters for the model
174
175
  */
175
176
  identifyingParams(): {
176
- system?: string | undefined;
177
+ tools?: Anthropic.Messages.Tool[] | undefined;
178
+ tool_choice?: Anthropic.Messages.MessageCreateParams.ToolChoiceAuto | Anthropic.Messages.MessageCreateParams.ToolChoiceAny | Anthropic.Messages.MessageCreateParams.ToolChoiceTool | undefined;
177
179
  metadata?: Anthropic.Messages.MessageCreateParams.Metadata | undefined;
180
+ temperature?: number | undefined;
181
+ model: "claude-2.1" | (string & {}) | "claude-3-opus-20240229" | "claude-3-sonnet-20240229" | "claude-3-haiku-20240307" | "claude-2.0" | "claude-instant-1.2";
182
+ system?: string | undefined;
178
183
  stream?: boolean | undefined;
179
184
  max_tokens: number;
180
- model: "claude-2.1" | (string & {}) | "claude-3-opus-20240229" | "claude-3-sonnet-20240229" | "claude-3-haiku-20240307" | "claude-2.0" | "claude-instant-1.2";
181
185
  stop_sequences?: string[] | undefined;
182
- temperature?: number | undefined;
183
186
  top_k?: number | undefined;
184
187
  top_p?: number | undefined;
185
188
  model_name: string;
@@ -191,7 +194,7 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
191
194
  llmOutput: {
192
195
  id: string;
193
196
  model: string;
194
- stop_reason: "max_tokens" | "stop_sequence" | "end_turn" | null;
197
+ stop_reason: "tool_use" | "max_tokens" | "stop_sequence" | "end_turn" | null;
195
198
  stop_sequence: string | null;
196
199
  usage: Anthropic.Messages.Usage;
197
200
  };
@@ -3,6 +3,7 @@ import { AIMessage, AIMessageChunk, HumanMessage, isAIMessage, } from "@langchai
3
3
  import { ChatGenerationChunk, } from "@langchain/core/outputs";
4
4
  import { getEnvironmentVariable } from "@langchain/core/utils/env";
5
5
  import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
6
+ import { isOpenAITool, } from "@langchain/core/language_models/base";
6
7
  import { zodToJsonSchema } from "zod-to-json-schema";
7
8
  import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
8
9
  import { isZodSchema } from "@langchain/core/utils/types";
@@ -376,6 +377,12 @@ export class ChatAnthropicMessages extends BaseChatModel {
376
377
  writable: true,
377
378
  value: void 0
378
379
  });
380
+ Object.defineProperty(this, "streamUsage", {
381
+ enumerable: true,
382
+ configurable: true,
383
+ writable: true,
384
+ value: true
385
+ });
379
386
  this.anthropicApiKey =
380
387
  fields?.apiKey ??
381
388
  fields?.anthropicApiKey ??
@@ -399,11 +406,12 @@ export class ChatAnthropicMessages extends BaseChatModel {
399
406
  this.stopSequences = fields?.stopSequences ?? this.stopSequences;
400
407
  this.streaming = fields?.streaming ?? false;
401
408
  this.clientOptions = fields?.clientOptions ?? {};
409
+ this.streamUsage = fields?.streamUsage ?? this.streamUsage;
402
410
  }
403
411
  getLsParams(options) {
404
412
  const params = this.invocationParams(options);
405
413
  return {
406
- ls_provider: "openai",
414
+ ls_provider: "anthropic",
407
415
  ls_model_name: this.model,
408
416
  ls_model_type: "chat",
409
417
  ls_temperature: params.temperature ?? undefined,
@@ -428,8 +436,17 @@ export class ChatAnthropicMessages extends BaseChatModel {
428
436
  return tools;
429
437
  }
430
438
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
439
+ if (tools.every((tool) => isOpenAITool(tool))) {
440
+ // Formatted as OpenAI tool, convert to Anthropic tool
441
+ return tools.map((tc) => ({
442
+ name: tc.function.name,
443
+ description: tc.function.description,
444
+ input_schema: tc.function.parameters,
445
+ }));
446
+ }
447
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
431
448
  if (tools.some((tool) => isAnthropicTool(tool))) {
432
- throw new Error(`Can not pass in a mix of AnthropicTools and StructuredTools`);
449
+ throw new Error(`Can not pass in a mix of tool schemas to ChatAnthropic`);
433
450
  }
434
451
  return tools.map((tool) => ({
435
452
  name: tool.name,
@@ -538,19 +555,37 @@ export class ChatAnthropicMessages extends BaseChatModel {
538
555
  }
539
556
  }
540
557
  usageData = usage;
558
+ let usageMetadata;
559
+ if (this.streamUsage || options.streamUsage) {
560
+ usageMetadata = {
561
+ input_tokens: usage.input_tokens,
562
+ output_tokens: usage.output_tokens,
563
+ total_tokens: usage.input_tokens + usage.output_tokens,
564
+ };
565
+ }
541
566
  yield new ChatGenerationChunk({
542
567
  message: new AIMessageChunk({
543
568
  content: "",
544
569
  additional_kwargs: filteredAdditionalKwargs,
570
+ usage_metadata: usageMetadata,
545
571
  }),
546
572
  text: "",
547
573
  });
548
574
  }
549
575
  else if (data.type === "message_delta") {
576
+ let usageMetadata;
577
+ if (this.streamUsage || options.streamUsage) {
578
+ usageMetadata = {
579
+ input_tokens: data.usage.output_tokens,
580
+ output_tokens: 0,
581
+ total_tokens: data.usage.output_tokens,
582
+ };
583
+ }
550
584
  yield new ChatGenerationChunk({
551
585
  message: new AIMessageChunk({
552
586
  content: "",
553
587
  additional_kwargs: { ...data.delta },
588
+ usage_metadata: usageMetadata,
554
589
  }),
555
590
  text: "",
556
591
  });
@@ -558,7 +593,8 @@ export class ChatAnthropicMessages extends BaseChatModel {
558
593
  usageData.output_tokens += data.usage.output_tokens;
559
594
  }
560
595
  }
561
- else if (data.type === "content_block_delta") {
596
+ else if (data.type === "content_block_delta" &&
597
+ data.delta.type === "text_delta") {
562
598
  const content = data.delta?.text;
563
599
  if (content !== undefined) {
564
600
  yield new ChatGenerationChunk({
@@ -572,10 +608,19 @@ export class ChatAnthropicMessages extends BaseChatModel {
572
608
  }
573
609
  }
574
610
  }
611
+ let usageMetadata;
612
+ if (this.streamUsage || options.streamUsage) {
613
+ usageMetadata = {
614
+ input_tokens: usageData.input_tokens,
615
+ output_tokens: usageData.output_tokens,
616
+ total_tokens: usageData.input_tokens + usageData.output_tokens,
617
+ };
618
+ }
575
619
  yield new ChatGenerationChunk({
576
620
  message: new AIMessageChunk({
577
621
  content: "",
578
622
  additional_kwargs: { usage: usageData },
623
+ usage_metadata: usageMetadata,
579
624
  }),
580
625
  text: "",
581
626
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -35,8 +35,8 @@
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@anthropic-ai/sdk": "^0.21.0",
39
- "@langchain/core": ">=0.2.5 <0.3.0",
38
+ "@anthropic-ai/sdk": "^0.22.0",
39
+ "@langchain/core": ">=0.2.9 <0.3.0",
40
40
  "fast-xml-parser": "^4.3.5",
41
41
  "zod": "^3.22.4",
42
42
  "zod-to-json-schema": "^3.22.4"
@@ -45,7 +45,7 @@
45
45
  "@jest/globals": "^29.5.0",
46
46
  "@langchain/community": "workspace:*",
47
47
  "@langchain/scripts": "~0.0.14",
48
- "@langchain/standard-tests": "workspace:*",
48
+ "@langchain/standard-tests": "0.0.0",
49
49
  "@swc/core": "^1.3.90",
50
50
  "@swc/jest": "^0.2.29",
51
51
  "dpdm": "^3.12.0",
@@ -61,6 +61,7 @@
61
61
  "prettier": "^2.8.3",
62
62
  "release-it": "^15.10.1",
63
63
  "rimraf": "^5.0.1",
64
+ "ts-jest": "^29.1.0",
64
65
  "typescript": "~5.1.6"
65
66
  },
66
67
  "publishConfig": {