@langchain/anthropic 0.3.11 → 0.3.13

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.
package/README.md CHANGED
@@ -49,24 +49,30 @@ export ANTHROPIC_API_KEY=your-api-key
49
49
  Then initialize
50
50
 
51
51
  ```typescript
52
- import { ChatAnthropicMessages } from "@langchain/anthropic";
52
+ import { ChatAnthropic } from "@langchain/anthropic";
53
53
 
54
54
  const model = new ChatAnthropic({
55
55
  apiKey: process.env.ANTHROPIC_API_KEY,
56
56
  });
57
- const response = await model.invoke(new HumanMessage("Hello world!"));
57
+ const response = await model.invoke({
58
+ role: "user",
59
+ content: "Hello world!",
60
+ });
58
61
  ```
59
62
 
60
63
  ### Streaming
61
64
 
62
65
  ```typescript
63
- import { ChatAnthropicMessages } from "@langchain/anthropic";
66
+ import { ChatAnthropic } from "@langchain/anthropic";
64
67
 
65
68
  const model = new ChatAnthropic({
66
69
  apiKey: process.env.ANTHROPIC_API_KEY,
67
70
  model: "claude-3-sonnet-20240229",
68
71
  });
69
- const response = await model.stream(new HumanMessage("Hello world!"));
72
+ const response = await model.stream({
73
+ role: "user",
74
+ content: "Hello world!",
75
+ });
70
76
  ```
71
77
 
72
78
  ## Development
@@ -119,4 +125,4 @@ After running `yarn build`, publish a new version with:
119
125
 
120
126
  ```bash
121
127
  $ npm publish
122
- ```
128
+ ```
@@ -19,6 +19,23 @@ const errors_js_1 = require("./utils/errors.cjs");
19
19
  function _toolsInParams(params) {
20
20
  return !!(params.tools && params.tools.length > 0);
21
21
  }
22
+ function _documentsInParams(params) {
23
+ for (const message of params.messages ?? []) {
24
+ if (typeof message.content === "string") {
25
+ continue;
26
+ }
27
+ for (const block of message.content ?? []) {
28
+ if (typeof block === "object" &&
29
+ block != null &&
30
+ block.type === "document" &&
31
+ typeof block.citations === "object" &&
32
+ block.citations.enabled) {
33
+ return true;
34
+ }
35
+ }
36
+ }
37
+ return false;
38
+ }
22
39
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
40
  function isAnthropicTool(tool) {
24
41
  return "input_schema" in tool;
@@ -607,7 +624,8 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
607
624
  return {
608
625
  name: tool.function.name,
609
626
  description: tool.function.description,
610
- input_schema: tool.function.parameters,
627
+ input_schema: tool.function
628
+ .parameters,
611
629
  };
612
630
  }
613
631
  if ((0, function_calling_1.isLangChainTool)(tool)) {
@@ -663,16 +681,13 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
663
681
  async *_streamResponseChunks(messages, options, runManager) {
664
682
  const params = this.invocationParams(options);
665
683
  const formattedMessages = (0, message_inputs_js_1._convertMessagesToAnthropicPayload)(messages);
666
- const coerceContentToString = !_toolsInParams({
667
- ...params,
668
- ...formattedMessages,
669
- stream: false,
670
- });
671
- const stream = await this.createStreamWithRetry({
684
+ const payload = {
672
685
  ...params,
673
686
  ...formattedMessages,
674
687
  stream: true,
675
- }, {
688
+ };
689
+ const coerceContentToString = !_toolsInParams(payload) && !_documentsInParams(payload);
690
+ const stream = await this.createStreamWithRetry(payload, {
676
691
  headers: options.headers,
677
692
  });
678
693
  for await (const data of stream) {
@@ -7,7 +7,6 @@ import { BaseChatModel, BaseChatModelCallOptions, LangSmithParams, type BaseChat
7
7
  import { type StructuredOutputMethodOptions, type BaseLanguageModelInput } from "@langchain/core/language_models/base";
8
8
  import { Runnable } from "@langchain/core/runnables";
9
9
  import { z } from "zod";
10
- import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/messages";
11
10
  import { AnthropicMessageCreateParams, AnthropicMessageStreamEvent, AnthropicRequestOptions, AnthropicStreamingMessageCreateParams, AnthropicToolChoice, ChatAnthropicToolType } from "./types.js";
12
11
  export interface ChatAnthropicCallOptions extends BaseChatModelCallOptions, Pick<AnthropicInput, "streamUsage"> {
13
12
  tools?: ChatAnthropicToolType[];
@@ -508,7 +507,7 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
508
507
  * @param {ChatAnthropicCallOptions["tools"]} tools The tools to format
509
508
  * @returns {AnthropicTool[] | undefined} The formatted tools, or undefined if none are passed.
510
509
  */
511
- formatStructuredToolToAnthropic(tools: ChatAnthropicCallOptions["tools"]): AnthropicTool[] | undefined;
510
+ formatStructuredToolToAnthropic(tools: ChatAnthropicCallOptions["tools"]): Anthropic.Messages.Tool[] | undefined;
512
511
  bindTools(tools: ChatAnthropicToolType[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
513
512
  /**
514
513
  * Get the parameters used to invoke the model
@@ -16,6 +16,23 @@ import { wrapAnthropicClientError } from "./utils/errors.js";
16
16
  function _toolsInParams(params) {
17
17
  return !!(params.tools && params.tools.length > 0);
18
18
  }
19
+ function _documentsInParams(params) {
20
+ for (const message of params.messages ?? []) {
21
+ if (typeof message.content === "string") {
22
+ continue;
23
+ }
24
+ for (const block of message.content ?? []) {
25
+ if (typeof block === "object" &&
26
+ block != null &&
27
+ block.type === "document" &&
28
+ typeof block.citations === "object" &&
29
+ block.citations.enabled) {
30
+ return true;
31
+ }
32
+ }
33
+ }
34
+ return false;
35
+ }
19
36
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
37
  function isAnthropicTool(tool) {
21
38
  return "input_schema" in tool;
@@ -604,7 +621,8 @@ export class ChatAnthropicMessages extends BaseChatModel {
604
621
  return {
605
622
  name: tool.function.name,
606
623
  description: tool.function.description,
607
- input_schema: tool.function.parameters,
624
+ input_schema: tool.function
625
+ .parameters,
608
626
  };
609
627
  }
610
628
  if (isLangChainTool(tool)) {
@@ -660,16 +678,13 @@ export class ChatAnthropicMessages extends BaseChatModel {
660
678
  async *_streamResponseChunks(messages, options, runManager) {
661
679
  const params = this.invocationParams(options);
662
680
  const formattedMessages = _convertMessagesToAnthropicPayload(messages);
663
- const coerceContentToString = !_toolsInParams({
664
- ...params,
665
- ...formattedMessages,
666
- stream: false,
667
- });
668
- const stream = await this.createStreamWithRetry({
681
+ const payload = {
669
682
  ...params,
670
683
  ...formattedMessages,
671
684
  stream: true,
672
- }, {
685
+ };
686
+ const coerceContentToString = !_toolsInParams(payload) && !_documentsInParams(payload);
687
+ const stream = await this.createStreamWithRetry(payload, {
673
688
  headers: options.headers,
674
689
  });
675
690
  for await (const data of stream) {
package/dist/types.d.ts CHANGED
@@ -1,5 +1,4 @@
1
1
  import Anthropic from "@anthropic-ai/sdk";
2
- import type { Tool as AnthropicTool } from "@anthropic-ai/sdk/resources/messages";
3
2
  import { BindToolsInput } from "@langchain/core/language_models/chat_models";
4
3
  export type AnthropicToolResponse = {
5
4
  type: "tool_use";
@@ -17,8 +16,9 @@ export type AnthropicToolChoice = {
17
16
  type: "tool";
18
17
  name: string;
19
18
  } | "any" | "auto" | "none" | string;
20
- export type ChatAnthropicToolType = AnthropicTool | BindToolsInput;
19
+ export type ChatAnthropicToolType = Anthropic.Messages.Tool | BindToolsInput;
21
20
  export type AnthropicTextBlockParam = Anthropic.Messages.TextBlockParam;
22
21
  export type AnthropicImageBlockParam = Anthropic.Messages.ImageBlockParam;
23
22
  export type AnthropicToolUseBlockParam = Anthropic.Messages.ToolUseBlockParam;
24
23
  export type AnthropicToolResultBlockParam = Anthropic.Messages.ToolResultBlockParam;
24
+ export type AnthropicDocumentBlockParam = Anthropic.Messages.DocumentBlockParam;
@@ -105,6 +105,13 @@ function _formatContent(content) {
105
105
  ...(cacheControl ? { cache_control: cacheControl } : {}),
106
106
  };
107
107
  }
108
+ else if (contentPart.type === "document") {
109
+ // PDF
110
+ return {
111
+ ...contentPart,
112
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
113
+ };
114
+ }
108
115
  else if (textTypes.find((t) => t === contentPart.type) &&
109
116
  "text" in contentPart) {
110
117
  // Assuming contentPart is of type MessageContentText here
@@ -101,6 +101,13 @@ function _formatContent(content) {
101
101
  ...(cacheControl ? { cache_control: cacheControl } : {}),
102
102
  };
103
103
  }
104
+ else if (contentPart.type === "document") {
105
+ // PDF
106
+ return {
107
+ ...contentPart,
108
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
109
+ };
110
+ }
104
111
  else if (textTypes.find((t) => t === contentPart.type) &&
105
112
  "text" in contentPart) {
106
113
  // Assuming contentPart is of type MessageContentText here
@@ -60,8 +60,22 @@ function _makeMessageChunkFromAnthropicEvent(data, fields) {
60
60
  };
61
61
  }
62
62
  else if (data.type === "content_block_start" &&
63
- data.content_block.type === "tool_use") {
64
- const toolCallContentBlock = data.content_block;
63
+ ["tool_use", "document"].includes(data.content_block.type)) {
64
+ const contentBlock = data.content_block;
65
+ let toolCallChunks;
66
+ if (contentBlock.type === "tool_use") {
67
+ toolCallChunks = [
68
+ {
69
+ id: contentBlock.id,
70
+ index: data.index,
71
+ name: contentBlock.name,
72
+ args: "",
73
+ },
74
+ ];
75
+ }
76
+ else {
77
+ toolCallChunks = [];
78
+ }
65
79
  return {
66
80
  chunk: new messages_1.AIMessageChunk({
67
81
  content: fields.coerceContentToString
@@ -74,32 +88,29 @@ function _makeMessageChunkFromAnthropicEvent(data, fields) {
74
88
  },
75
89
  ],
76
90
  additional_kwargs: {},
77
- tool_call_chunks: [
78
- {
79
- id: toolCallContentBlock.id,
80
- index: data.index,
81
- name: toolCallContentBlock.name,
82
- args: "",
83
- },
84
- ],
91
+ tool_call_chunks: toolCallChunks,
85
92
  }),
86
93
  };
87
94
  }
88
95
  else if (data.type === "content_block_delta" &&
89
- data.delta.type === "text_delta") {
90
- const content = data.delta?.text;
91
- if (content !== undefined) {
96
+ ["text_delta", "citations_delta"].includes(data.delta.type)) {
97
+ if (fields.coerceContentToString && "text" in data.delta) {
92
98
  return {
93
99
  chunk: new messages_1.AIMessageChunk({
94
- content: fields.coerceContentToString
95
- ? content
96
- : [
97
- {
98
- index: data.index,
99
- ...data.delta,
100
- },
101
- ],
102
- additional_kwargs: {},
100
+ content: data.delta.text,
101
+ }),
102
+ };
103
+ }
104
+ else {
105
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
106
+ const contentBlock = data.delta;
107
+ if ("citation" in contentBlock) {
108
+ contentBlock.citations = [contentBlock.citation];
109
+ delete contentBlock.citation;
110
+ }
111
+ return {
112
+ chunk: new messages_1.AIMessageChunk({
113
+ content: [{ index: data.index, ...contentBlock, type: "text" }],
103
114
  }),
104
115
  };
105
116
  }
@@ -57,8 +57,22 @@ export function _makeMessageChunkFromAnthropicEvent(data, fields) {
57
57
  };
58
58
  }
59
59
  else if (data.type === "content_block_start" &&
60
- data.content_block.type === "tool_use") {
61
- const toolCallContentBlock = data.content_block;
60
+ ["tool_use", "document"].includes(data.content_block.type)) {
61
+ const contentBlock = data.content_block;
62
+ let toolCallChunks;
63
+ if (contentBlock.type === "tool_use") {
64
+ toolCallChunks = [
65
+ {
66
+ id: contentBlock.id,
67
+ index: data.index,
68
+ name: contentBlock.name,
69
+ args: "",
70
+ },
71
+ ];
72
+ }
73
+ else {
74
+ toolCallChunks = [];
75
+ }
62
76
  return {
63
77
  chunk: new AIMessageChunk({
64
78
  content: fields.coerceContentToString
@@ -71,32 +85,29 @@ export function _makeMessageChunkFromAnthropicEvent(data, fields) {
71
85
  },
72
86
  ],
73
87
  additional_kwargs: {},
74
- tool_call_chunks: [
75
- {
76
- id: toolCallContentBlock.id,
77
- index: data.index,
78
- name: toolCallContentBlock.name,
79
- args: "",
80
- },
81
- ],
88
+ tool_call_chunks: toolCallChunks,
82
89
  }),
83
90
  };
84
91
  }
85
92
  else if (data.type === "content_block_delta" &&
86
- data.delta.type === "text_delta") {
87
- const content = data.delta?.text;
88
- if (content !== undefined) {
93
+ ["text_delta", "citations_delta"].includes(data.delta.type)) {
94
+ if (fields.coerceContentToString && "text" in data.delta) {
89
95
  return {
90
96
  chunk: new AIMessageChunk({
91
- content: fields.coerceContentToString
92
- ? content
93
- : [
94
- {
95
- index: data.index,
96
- ...data.delta,
97
- },
98
- ],
99
- additional_kwargs: {},
97
+ content: data.delta.text,
98
+ }),
99
+ };
100
+ }
101
+ else {
102
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
103
+ const contentBlock = data.delta;
104
+ if ("citation" in contentBlock) {
105
+ contentBlock.citations = [contentBlock.citation];
106
+ delete contentBlock.citation;
107
+ }
108
+ return {
109
+ chunk: new AIMessageChunk({
110
+ content: [{ index: data.index, ...contentBlock, type: "text" }],
100
111
  }),
101
112
  };
102
113
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "0.3.11",
3
+ "version": "0.3.13",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -35,7 +35,7 @@
35
35
  "author": "LangChain",
36
36
  "license": "MIT",
37
37
  "dependencies": {
38
- "@anthropic-ai/sdk": "^0.32.1",
38
+ "@anthropic-ai/sdk": "^0.36.3",
39
39
  "fast-xml-parser": "^4.4.1",
40
40
  "zod": "^3.22.4",
41
41
  "zod-to-json-schema": "^3.22.4"