@langchain/anthropic 0.3.0-rc.0 → 0.3.0

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
@@ -5,7 +5,7 @@ This package contains the LangChain.js integrations for Anthropic through their
5
5
  ## Installation
6
6
 
7
7
  ```bash npm2yarn
8
- npm install @langchain/anthropic
8
+ npm install @langchain/anthropic @langchain/core
9
9
  ```
10
10
 
11
11
  This package, along with the main LangChain package, depends on [`@langchain/core`](https://npmjs.com/package/@langchain/core/).
@@ -553,7 +553,7 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
553
553
  fields?.apiKey ??
554
554
  fields?.anthropicApiKey ??
555
555
  (0, env_1.getEnvironmentVariable)("ANTHROPIC_API_KEY");
556
- if (!this.anthropicApiKey) {
556
+ if (!this.anthropicApiKey && !fields?.createClient) {
557
557
  throw new Error("Anthropic API key not found");
558
558
  }
559
559
  this.clientOptions = fields?.clientOptions ?? {};
@@ -593,38 +593,31 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
593
593
  *
594
594
  * @param {ChatAnthropicCallOptions["tools"]} tools The tools to format
595
595
  * @returns {AnthropicTool[] | undefined} The formatted tools, or undefined if none are passed.
596
- * @throws {Error} If a mix of AnthropicTools and StructuredTools are passed.
597
596
  */
598
597
  formatStructuredToolToAnthropic(tools) {
599
598
  if (!tools || !tools.length) {
600
599
  return undefined;
601
600
  }
602
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
603
- if (tools.every((tool) => isAnthropicTool(tool))) {
604
- // If the tool is already an anthropic tool, return it
605
- return tools;
606
- }
607
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
608
- if (tools.every((tool) => (0, base_1.isOpenAITool)(tool))) {
609
- // Formatted as OpenAI tool, convert to Anthropic tool
610
- return tools.map((tc) => ({
611
- name: tc.function.name,
612
- description: tc.function.description,
613
- input_schema: tc.function.parameters,
614
- }));
615
- }
616
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
617
- if (tools.some((tool) => isAnthropicTool(tool))) {
618
- throw new Error(`Can not pass in a mix of tool schemas to ChatAnthropic`);
619
- }
620
- if (tools.every(function_calling_1.isLangChainTool)) {
621
- return tools.map((t) => ({
622
- name: t.name,
623
- description: t.description,
624
- input_schema: (0, zod_to_json_schema_1.zodToJsonSchema)(t.schema),
625
- }));
626
- }
627
- throw new Error("Unsupported tool type passed to ChatAnthropic");
601
+ return tools.map((tool) => {
602
+ if (isAnthropicTool(tool)) {
603
+ return tool;
604
+ }
605
+ if ((0, base_1.isOpenAITool)(tool)) {
606
+ return {
607
+ name: tool.function.name,
608
+ description: tool.function.description,
609
+ input_schema: tool.function.parameters,
610
+ };
611
+ }
612
+ if ((0, function_calling_1.isLangChainTool)(tool)) {
613
+ return {
614
+ name: tool.name,
615
+ description: tool.description,
616
+ input_schema: (0, zod_to_json_schema_1.zodToJsonSchema)(tool.schema),
617
+ };
618
+ }
619
+ throw new Error(`Unknown tool type passed to ChatAnthropic: ${JSON.stringify(tool, null, 2)}`);
620
+ });
628
621
  }
629
622
  bindTools(tools, kwargs) {
630
623
  return this.bind({
@@ -791,9 +784,6 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
791
784
  async completionWithRetry(request, options) {
792
785
  if (!this.batchClient) {
793
786
  const options = this.apiUrl ? { baseURL: this.apiUrl } : undefined;
794
- if (!this.apiKey) {
795
- throw new Error("Missing Anthropic API key.");
796
- }
797
787
  this.batchClient = this.createClient({
798
788
  ...this.clientOptions,
799
789
  ...options,
@@ -507,7 +507,6 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
507
507
  *
508
508
  * @param {ChatAnthropicCallOptions["tools"]} tools The tools to format
509
509
  * @returns {AnthropicTool[] | undefined} The formatted tools, or undefined if none are passed.
510
- * @throws {Error} If a mix of AnthropicTools and StructuredTools are passed.
511
510
  */
512
511
  formatStructuredToolToAnthropic(tools: ChatAnthropicCallOptions["tools"]): AnthropicTool[] | undefined;
513
512
  bindTools(tools: ChatAnthropicToolType[], kwargs?: Partial<CallOptions>): Runnable<BaseLanguageModelInput, AIMessageChunk, CallOptions>;
@@ -553,8 +552,17 @@ export declare class ChatAnthropicMessages<CallOptions extends ChatAnthropicCall
553
552
  generations: import("@langchain/core/outputs").ChatGeneration[];
554
553
  llmOutput: {
555
554
  id: string;
555
+ /** Does nucleus sampling, in which we compute the
556
+ * cumulative distribution over all the options for each
557
+ * subsequent token in decreasing probability order and
558
+ * cut it off once it reaches a particular probability
559
+ * specified by top_p. Defaults to -1, which disables it.
560
+ * Note that you should either alter temperature or top_p,
561
+ * but not both.
562
+ */
556
563
  model: Anthropic.Messages.Model;
557
564
  stop_reason: "tool_use" | "stop_sequence" | "end_turn" | "max_tokens" | null;
565
+ /** Anthropic API URL */
558
566
  stop_sequence: string | null;
559
567
  usage: Anthropic.Messages.Usage;
560
568
  };
@@ -550,7 +550,7 @@ export class ChatAnthropicMessages extends BaseChatModel {
550
550
  fields?.apiKey ??
551
551
  fields?.anthropicApiKey ??
552
552
  getEnvironmentVariable("ANTHROPIC_API_KEY");
553
- if (!this.anthropicApiKey) {
553
+ if (!this.anthropicApiKey && !fields?.createClient) {
554
554
  throw new Error("Anthropic API key not found");
555
555
  }
556
556
  this.clientOptions = fields?.clientOptions ?? {};
@@ -590,38 +590,31 @@ export class ChatAnthropicMessages extends BaseChatModel {
590
590
  *
591
591
  * @param {ChatAnthropicCallOptions["tools"]} tools The tools to format
592
592
  * @returns {AnthropicTool[] | undefined} The formatted tools, or undefined if none are passed.
593
- * @throws {Error} If a mix of AnthropicTools and StructuredTools are passed.
594
593
  */
595
594
  formatStructuredToolToAnthropic(tools) {
596
595
  if (!tools || !tools.length) {
597
596
  return undefined;
598
597
  }
599
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
600
- if (tools.every((tool) => isAnthropicTool(tool))) {
601
- // If the tool is already an anthropic tool, return it
602
- return tools;
603
- }
604
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
605
- if (tools.every((tool) => isOpenAITool(tool))) {
606
- // Formatted as OpenAI tool, convert to Anthropic tool
607
- return tools.map((tc) => ({
608
- name: tc.function.name,
609
- description: tc.function.description,
610
- input_schema: tc.function.parameters,
611
- }));
612
- }
613
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
614
- if (tools.some((tool) => isAnthropicTool(tool))) {
615
- throw new Error(`Can not pass in a mix of tool schemas to ChatAnthropic`);
616
- }
617
- if (tools.every(isLangChainTool)) {
618
- return tools.map((t) => ({
619
- name: t.name,
620
- description: t.description,
621
- input_schema: zodToJsonSchema(t.schema),
622
- }));
623
- }
624
- throw new Error("Unsupported tool type passed to ChatAnthropic");
598
+ return tools.map((tool) => {
599
+ if (isAnthropicTool(tool)) {
600
+ return tool;
601
+ }
602
+ if (isOpenAITool(tool)) {
603
+ return {
604
+ name: tool.function.name,
605
+ description: tool.function.description,
606
+ input_schema: tool.function.parameters,
607
+ };
608
+ }
609
+ if (isLangChainTool(tool)) {
610
+ return {
611
+ name: tool.name,
612
+ description: tool.description,
613
+ input_schema: zodToJsonSchema(tool.schema),
614
+ };
615
+ }
616
+ throw new Error(`Unknown tool type passed to ChatAnthropic: ${JSON.stringify(tool, null, 2)}`);
617
+ });
625
618
  }
626
619
  bindTools(tools, kwargs) {
627
620
  return this.bind({
@@ -788,9 +781,6 @@ export class ChatAnthropicMessages extends BaseChatModel {
788
781
  async completionWithRetry(request, options) {
789
782
  if (!this.batchClient) {
790
783
  const options = this.apiUrl ? { baseURL: this.apiUrl } : undefined;
791
- if (!this.apiKey) {
792
- throw new Error("Missing Anthropic API key.");
793
- }
794
784
  this.batchClient = this.createClient({
795
785
  ...this.clientOptions,
796
786
  ...options,
@@ -103,6 +103,7 @@ function _formatContent(content) {
103
103
  }
104
104
  else {
105
105
  const contentBlocks = content.map((contentPart) => {
106
+ const cacheControl = "cache_control" in contentPart ? contentPart.cache_control : undefined;
106
107
  if (contentPart.type === "image_url") {
107
108
  let source;
108
109
  if (typeof contentPart.image_url === "string") {
@@ -114,6 +115,7 @@ function _formatContent(content) {
114
115
  return {
115
116
  type: "image",
116
117
  source,
118
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
117
119
  };
118
120
  }
119
121
  else if (textTypes.find((t) => t === contentPart.type) &&
@@ -122,6 +124,7 @@ function _formatContent(content) {
122
124
  return {
123
125
  type: "text",
124
126
  text: contentPart.text,
127
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
125
128
  };
126
129
  }
127
130
  else if (toolTypes.find((t) => t === contentPart.type)) {
@@ -147,6 +150,7 @@ function _formatContent(content) {
147
150
  // TODO: Fix when SDK types are fixed
148
151
  return {
149
152
  ...contentPartCopy,
153
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
150
154
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
151
155
  };
152
156
  }
@@ -99,6 +99,7 @@ function _formatContent(content) {
99
99
  }
100
100
  else {
101
101
  const contentBlocks = content.map((contentPart) => {
102
+ const cacheControl = "cache_control" in contentPart ? contentPart.cache_control : undefined;
102
103
  if (contentPart.type === "image_url") {
103
104
  let source;
104
105
  if (typeof contentPart.image_url === "string") {
@@ -110,6 +111,7 @@ function _formatContent(content) {
110
111
  return {
111
112
  type: "image",
112
113
  source,
114
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
113
115
  };
114
116
  }
115
117
  else if (textTypes.find((t) => t === contentPart.type) &&
@@ -118,6 +120,7 @@ function _formatContent(content) {
118
120
  return {
119
121
  type: "text",
120
122
  text: contentPart.text,
123
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
121
124
  };
122
125
  }
123
126
  else if (toolTypes.find((t) => t === contentPart.type)) {
@@ -143,6 +146,7 @@ function _formatContent(content) {
143
146
  // TODO: Fix when SDK types are fixed
144
147
  return {
145
148
  ...contentPartCopy,
149
+ ...(cacheControl ? { cache_control: cacheControl } : {}),
146
150
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
147
151
  };
148
152
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "0.3.0-rc.0",
3
+ "version": "0.3.0",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -41,7 +41,7 @@
41
41
  "zod-to-json-schema": "^3.22.4"
42
42
  },
43
43
  "peerDependencies": {
44
- "@langchain/core": ">=0.2.21 <0.4.0 || 0.3.0-rc.0"
44
+ "@langchain/core": ">=0.2.21 <0.4.0"
45
45
  },
46
46
  "devDependencies": {
47
47
  "@anthropic-ai/vertex-sdk": "^0.4.1",