@langchain/anthropic 0.1.1 → 0.1.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,22 @@ 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
+ function _formatImage(imageUrl) {
10
+ const regex = /^data:(image\/.+);base64,(.+)$/;
11
+ const match = imageUrl.match(regex);
12
+ if (match === null) {
13
+ throw new Error([
14
+ "Anthropic only supports base64-encoded images currently.",
15
+ "Example: data:image/png;base64,/9j/4AAQSk...",
16
+ ].join("\n\n"));
17
+ }
18
+ return {
19
+ type: "base64",
20
+ media_type: match[1] ?? "",
21
+ data: match[2] ?? "",
22
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ };
24
+ }
9
25
  /**
10
26
  * Wrapper around Anthropic large language models.
11
27
  *
@@ -243,16 +259,13 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
243
259
  let system;
244
260
  if (messages.length > 0 && messages[0]._getType() === "system") {
245
261
  if (typeof messages[0].content !== "string") {
246
- throw new Error("Currently only string content messages are supported.");
262
+ throw new Error("System message content must be a string.");
247
263
  }
248
264
  system = messages[0].content;
249
265
  }
250
266
  const conversationMessages = system !== undefined ? messages.slice(1) : messages;
251
267
  const formattedMessages = conversationMessages.map((message) => {
252
268
  let role;
253
- if (typeof message.content !== "string") {
254
- throw new Error("Currently only string content messages are supported.");
255
- }
256
269
  if (message._getType() === "human") {
257
270
  role = "user";
258
271
  }
@@ -265,10 +278,35 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
265
278
  else {
266
279
  throw new Error(`Message type "${message._getType()}" is not supported.`);
267
280
  }
268
- return {
269
- role,
270
- content: message.content,
271
- };
281
+ if (typeof message.content === "string") {
282
+ return {
283
+ role,
284
+ content: message.content,
285
+ };
286
+ }
287
+ else {
288
+ return {
289
+ role,
290
+ content: message.content.map((contentPart) => {
291
+ if (contentPart.type === "image_url") {
292
+ let source;
293
+ if (typeof contentPart.image_url === "string") {
294
+ source = _formatImage(contentPart.image_url);
295
+ }
296
+ else {
297
+ source = _formatImage(contentPart.image_url.url);
298
+ }
299
+ return {
300
+ type: "image",
301
+ source,
302
+ };
303
+ }
304
+ else {
305
+ return contentPart;
306
+ }
307
+ }),
308
+ };
309
+ }
272
310
  });
273
311
  return {
274
312
  messages: formattedMessages,
@@ -374,10 +412,6 @@ class ChatAnthropicMessages extends chat_models_1.BaseChatModel {
374
412
  _llmType() {
375
413
  return "anthropic";
376
414
  }
377
- /** @ignore */
378
- _combineLLMOutput() {
379
- return [];
380
- }
381
415
  }
382
416
  exports.ChatAnthropicMessages = ChatAnthropicMessages;
383
417
  class ChatAnthropic extends ChatAnthropicMessages {
@@ -165,8 +165,6 @@ export declare class ChatAnthropicMessages<CallOptions extends BaseLanguageModel
165
165
  signal?: AbortSignal;
166
166
  }): Promise<Anthropic.Message>;
167
167
  _llmType(): string;
168
- /** @ignore */
169
- _combineLLMOutput(): never[];
170
168
  }
171
169
  export declare class ChatAnthropic extends ChatAnthropicMessages {
172
170
  }
@@ -3,6 +3,22 @@ import { AIMessage, AIMessageChunk, } from "@langchain/core/messages";
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
+ function _formatImage(imageUrl) {
7
+ const regex = /^data:(image\/.+);base64,(.+)$/;
8
+ const match = imageUrl.match(regex);
9
+ if (match === null) {
10
+ throw new Error([
11
+ "Anthropic only supports base64-encoded images currently.",
12
+ "Example: data:image/png;base64,/9j/4AAQSk...",
13
+ ].join("\n\n"));
14
+ }
15
+ return {
16
+ type: "base64",
17
+ media_type: match[1] ?? "",
18
+ data: match[2] ?? "",
19
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
20
+ };
21
+ }
6
22
  /**
7
23
  * Wrapper around Anthropic large language models.
8
24
  *
@@ -240,16 +256,13 @@ export class ChatAnthropicMessages extends BaseChatModel {
240
256
  let system;
241
257
  if (messages.length > 0 && messages[0]._getType() === "system") {
242
258
  if (typeof messages[0].content !== "string") {
243
- throw new Error("Currently only string content messages are supported.");
259
+ throw new Error("System message content must be a string.");
244
260
  }
245
261
  system = messages[0].content;
246
262
  }
247
263
  const conversationMessages = system !== undefined ? messages.slice(1) : messages;
248
264
  const formattedMessages = conversationMessages.map((message) => {
249
265
  let role;
250
- if (typeof message.content !== "string") {
251
- throw new Error("Currently only string content messages are supported.");
252
- }
253
266
  if (message._getType() === "human") {
254
267
  role = "user";
255
268
  }
@@ -262,10 +275,35 @@ export class ChatAnthropicMessages extends BaseChatModel {
262
275
  else {
263
276
  throw new Error(`Message type "${message._getType()}" is not supported.`);
264
277
  }
265
- return {
266
- role,
267
- content: message.content,
268
- };
278
+ if (typeof message.content === "string") {
279
+ return {
280
+ role,
281
+ content: message.content,
282
+ };
283
+ }
284
+ else {
285
+ return {
286
+ role,
287
+ content: message.content.map((contentPart) => {
288
+ if (contentPart.type === "image_url") {
289
+ let source;
290
+ if (typeof contentPart.image_url === "string") {
291
+ source = _formatImage(contentPart.image_url);
292
+ }
293
+ else {
294
+ source = _formatImage(contentPart.image_url.url);
295
+ }
296
+ return {
297
+ type: "image",
298
+ source,
299
+ };
300
+ }
301
+ else {
302
+ return contentPart;
303
+ }
304
+ }),
305
+ };
306
+ }
269
307
  });
270
308
  return {
271
309
  messages: formattedMessages,
@@ -371,10 +409,6 @@ export class ChatAnthropicMessages extends BaseChatModel {
371
409
  _llmType() {
372
410
  return "anthropic";
373
411
  }
374
- /** @ignore */
375
- _combineLLMOutput() {
376
- return [];
377
- }
378
412
  }
379
413
  export class ChatAnthropic extends ChatAnthropicMessages {
380
414
  }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./tool_calling.cjs"), exports);
@@ -0,0 +1 @@
1
+ export * from "./tool_calling.js";
@@ -0,0 +1 @@
1
+ export * from "./tool_calling.js";
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,204 @@
1
+ /* eslint-disable no-process-env */
2
+ /* eslint-disable @typescript-eslint/no-non-null-assertion */
3
+ import { test } from "@jest/globals";
4
+ import { z } from "zod";
5
+ import { zodToJsonSchema } from "zod-to-json-schema";
6
+ import { HumanMessage } from "@langchain/core/messages";
7
+ import { ChatAnthropicTools } from "../tool_calling.js";
8
+ test("Test ChatAnthropicTools", async () => {
9
+ const chat = new ChatAnthropicTools({
10
+ modelName: "claude-3-sonnet-20240229",
11
+ maxRetries: 0,
12
+ });
13
+ const message = new HumanMessage("Hello!");
14
+ const res = await chat.invoke([message]);
15
+ console.log(JSON.stringify(res));
16
+ });
17
+ test("Test ChatAnthropicTools streaming", async () => {
18
+ const chat = new ChatAnthropicTools({
19
+ modelName: "claude-3-sonnet-20240229",
20
+ maxRetries: 0,
21
+ });
22
+ const message = new HumanMessage("Hello!");
23
+ const stream = await chat.stream([message]);
24
+ const chunks = [];
25
+ for await (const chunk of stream) {
26
+ console.log(chunk);
27
+ chunks.push(chunk);
28
+ }
29
+ expect(chunks.length).toBeGreaterThan(1);
30
+ });
31
+ test("Test ChatAnthropicTools with tools", async () => {
32
+ const chat = new ChatAnthropicTools({
33
+ modelName: "claude-3-sonnet-20240229",
34
+ temperature: 0.1,
35
+ maxRetries: 0,
36
+ }).bind({
37
+ tools: [
38
+ {
39
+ type: "function",
40
+ function: {
41
+ name: "get_current_weather",
42
+ description: "Get the current weather in a given location",
43
+ parameters: {
44
+ type: "object",
45
+ properties: {
46
+ location: {
47
+ type: "string",
48
+ description: "The city and state, e.g. San Francisco, CA",
49
+ },
50
+ unit: {
51
+ type: "string",
52
+ enum: ["celsius", "fahrenheit"],
53
+ },
54
+ },
55
+ required: ["location"],
56
+ },
57
+ },
58
+ },
59
+ ],
60
+ });
61
+ const message = new HumanMessage("What is the weather in San Francisco?");
62
+ const res = await chat.invoke([message]);
63
+ console.log(JSON.stringify(res));
64
+ expect(res.additional_kwargs.tool_calls).toBeDefined();
65
+ expect(res.additional_kwargs.tool_calls?.[0].function.name).toEqual("get_current_weather");
66
+ });
67
+ test("Test ChatAnthropicTools with a forced function call", async () => {
68
+ const chat = new ChatAnthropicTools({
69
+ modelName: "claude-3-sonnet-20240229",
70
+ temperature: 0.1,
71
+ maxRetries: 0,
72
+ }).bind({
73
+ tools: [
74
+ {
75
+ type: "function",
76
+ function: {
77
+ name: "extract_data",
78
+ description: "Return information about the input",
79
+ parameters: {
80
+ type: "object",
81
+ properties: {
82
+ sentiment: {
83
+ type: "string",
84
+ description: "The city and state, e.g. San Francisco, CA",
85
+ },
86
+ aggressiveness: {
87
+ type: "integer",
88
+ description: "How aggressive the input is from 1 to 10",
89
+ },
90
+ language: {
91
+ type: "string",
92
+ description: "The language the input is in",
93
+ },
94
+ },
95
+ required: ["sentiment", "aggressiveness"],
96
+ },
97
+ },
98
+ },
99
+ ],
100
+ tool_choice: { type: "function", function: { name: "extract_data" } },
101
+ });
102
+ const message = new HumanMessage("Extract the desired information from the following passage:\n\nthis is really cool");
103
+ const res = await chat.invoke([message]);
104
+ console.log(JSON.stringify(res));
105
+ expect(res.additional_kwargs.tool_calls).toBeDefined();
106
+ expect(res.additional_kwargs.tool_calls?.[0]?.function.name).toEqual("extract_data");
107
+ });
108
+ test("ChatAnthropicTools with Zod schema", async () => {
109
+ const schema = z.object({
110
+ people: z.array(z.object({
111
+ name: z.string().describe("The name of a person"),
112
+ height: z.number().describe("The person's height"),
113
+ hairColor: z.optional(z.string()).describe("The person's hair color"),
114
+ })),
115
+ });
116
+ const chat = new ChatAnthropicTools({
117
+ modelName: "claude-3-sonnet-20240229",
118
+ temperature: 0.1,
119
+ maxRetries: 0,
120
+ }).bind({
121
+ tools: [
122
+ {
123
+ type: "function",
124
+ function: {
125
+ name: "information_extraction",
126
+ description: "Extracts the relevant information from the passage.",
127
+ parameters: zodToJsonSchema(schema),
128
+ },
129
+ },
130
+ ],
131
+ tool_choice: {
132
+ type: "function",
133
+ function: {
134
+ name: "information_extraction",
135
+ },
136
+ },
137
+ });
138
+ const message = new HumanMessage("Alex is 5 feet tall. Claudia is 1 foot taller than Alex and jumps higher than him. Claudia is a brunette and Alex is blonde.");
139
+ const res = await chat.invoke([message]);
140
+ console.log(JSON.stringify(res));
141
+ expect(res.additional_kwargs.tool_calls).toBeDefined();
142
+ expect(res.additional_kwargs.tool_calls?.[0]?.function.name).toEqual("information_extraction");
143
+ expect(JSON.parse(res.additional_kwargs.tool_calls?.[0]?.function.arguments ?? "")).toEqual({
144
+ people: expect.arrayContaining([
145
+ { name: "Alex", height: 5, hairColor: "blonde" },
146
+ { name: "Claudia", height: 6, hairColor: "brunette" },
147
+ ]),
148
+ });
149
+ });
150
+ test("ChatAnthropicTools with parallel tool calling", async () => {
151
+ const schema = z.object({
152
+ name: z.string().describe("The name of a person"),
153
+ height: z.number().describe("The person's height"),
154
+ hairColor: z.optional(z.string()).describe("The person's hair color"),
155
+ });
156
+ const chat = new ChatAnthropicTools({
157
+ modelName: "claude-3-sonnet-20240229",
158
+ temperature: 0.1,
159
+ maxRetries: 0,
160
+ }).bind({
161
+ tools: [
162
+ {
163
+ type: "function",
164
+ function: {
165
+ name: "person",
166
+ description: "A person mentioned in the passage.",
167
+ parameters: zodToJsonSchema(schema),
168
+ },
169
+ },
170
+ ],
171
+ tool_choice: {
172
+ type: "function",
173
+ function: {
174
+ name: "person",
175
+ },
176
+ },
177
+ });
178
+ console.log(zodToJsonSchema(schema));
179
+ const message = new HumanMessage("Alex is 5 feet tall. Claudia is 1 foot taller than Alex and jumps higher than him. Claudia is a brunette and Alex is blonde.");
180
+ const res = await chat.invoke([message]);
181
+ console.log(JSON.stringify(res));
182
+ expect(res.additional_kwargs.tool_calls).toBeDefined();
183
+ expect(res.additional_kwargs.tool_calls?.map((toolCall) => JSON.parse(toolCall.function.arguments ?? ""))).toEqual(expect.arrayContaining([
184
+ { name: "Alex", height: 5, hairColor: "blonde" },
185
+ { name: "Claudia", height: 6, hairColor: "brunette" },
186
+ ]));
187
+ });
188
+ test("Test ChatAnthropic withStructuredOutput", async () => {
189
+ const runnable = new ChatAnthropicTools({
190
+ modelName: "claude-3-sonnet-20240229",
191
+ maxRetries: 0,
192
+ }).withStructuredOutput({
193
+ schema: z.object({
194
+ name: z.string().describe("The name of a person"),
195
+ height: z.number().describe("The person's height"),
196
+ hairColor: z.optional(z.string()).describe("The person's hair color"),
197
+ }),
198
+ name: "person",
199
+ });
200
+ const message = new HumanMessage("Alex is 5 feet tall. Alex is blonde.");
201
+ const res = await runnable.invoke([message]);
202
+ console.log(JSON.stringify(res, null, 2));
203
+ expect(res).toEqual({ name: "Alex", height: 5, hairColor: "blonde" });
204
+ });
@@ -0,0 +1,247 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ChatAnthropicTools = void 0;
4
+ const fast_xml_parser_1 = require("fast-xml-parser");
5
+ const messages_1 = require("@langchain/core/messages");
6
+ const chat_models_1 = require("@langchain/core/language_models/chat_models");
7
+ const runnables_1 = require("@langchain/core/runnables");
8
+ const openai_tools_1 = require("@langchain/core/output_parsers/openai_tools");
9
+ const zod_to_json_schema_1 = require("zod-to-json-schema");
10
+ const chat_models_js_1 = require("../chat_models.cjs");
11
+ const tool_calling_js_1 = require("./utils/tool_calling.cjs");
12
+ /**
13
+ * Experimental wrapper over Anthropic chat models that adds support for
14
+ * a function calling interface.
15
+ */
16
+ class ChatAnthropicTools extends chat_models_1.BaseChatModel {
17
+ static lc_name() {
18
+ return "ChatAnthropicTools";
19
+ }
20
+ constructor(fields) {
21
+ super(fields ?? {});
22
+ Object.defineProperty(this, "llm", {
23
+ enumerable: true,
24
+ configurable: true,
25
+ writable: true,
26
+ value: void 0
27
+ });
28
+ Object.defineProperty(this, "stopSequences", {
29
+ enumerable: true,
30
+ configurable: true,
31
+ writable: true,
32
+ value: void 0
33
+ });
34
+ Object.defineProperty(this, "systemPromptTemplate", {
35
+ enumerable: true,
36
+ configurable: true,
37
+ writable: true,
38
+ value: void 0
39
+ });
40
+ Object.defineProperty(this, "lc_namespace", {
41
+ enumerable: true,
42
+ configurable: true,
43
+ writable: true,
44
+ value: ["langchain", "experimental", "chat_models"]
45
+ });
46
+ this.llm = fields?.llm ?? new chat_models_js_1.ChatAnthropic(fields);
47
+ this.systemPromptTemplate =
48
+ fields?.systemPromptTemplate ?? tool_calling_js_1.DEFAULT_TOOL_SYSTEM_PROMPT;
49
+ this.stopSequences =
50
+ fields?.stopSequences ?? this.llm.stopSequences;
51
+ }
52
+ invocationParams() {
53
+ return this.llm.invocationParams();
54
+ }
55
+ /** @ignore */
56
+ _identifyingParams() {
57
+ return this.llm._identifyingParams();
58
+ }
59
+ async *_streamResponseChunks(messages, options, runManager) {
60
+ yield* this.llm._streamResponseChunks(messages, options, runManager);
61
+ }
62
+ async _prepareAndParseToolCall({ messages, options, runManager, systemPromptTemplate = tool_calling_js_1.DEFAULT_TOOL_SYSTEM_PROMPT, stopSequences, }) {
63
+ let promptMessages = messages;
64
+ let forced = false;
65
+ let toolCall;
66
+ if (options.tools !== undefined && options.tools.length > 0) {
67
+ const content = await systemPromptTemplate.format({
68
+ tools: `<tools>\n${options.tools
69
+ .map(tool_calling_js_1.formatAsXMLRepresentation)
70
+ .join("\n\n")}</tools>`,
71
+ });
72
+ if (promptMessages.length && promptMessages[0]._getType() !== "system") {
73
+ const systemMessage = new messages_1.SystemMessage({ content });
74
+ promptMessages = [systemMessage].concat(promptMessages);
75
+ }
76
+ else {
77
+ const systemMessage = new messages_1.SystemMessage({
78
+ content: `${content}\n\n${promptMessages[0].content}`,
79
+ });
80
+ promptMessages = [systemMessage].concat(promptMessages.slice(1));
81
+ }
82
+ // eslint-disable-next-line no-param-reassign
83
+ options.stop = stopSequences.concat(["</function_calls>"]);
84
+ if (options.tool_choice && options.tool_choice !== "auto") {
85
+ toolCall = options.tool_choice.function.name;
86
+ forced = true;
87
+ const matchingFunction = options.tools.find(
88
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
89
+ (tool) => tool.function.name === toolCall);
90
+ if (!matchingFunction) {
91
+ throw new Error(`No matching function found for passed "tool_choice"`);
92
+ }
93
+ promptMessages = promptMessages.concat([
94
+ new messages_1.AIMessage({
95
+ content: `<function_calls>\n<invoke><tool_name>${toolCall}</tool_name>`,
96
+ }),
97
+ ]);
98
+ // eslint-disable-next-line no-param-reassign
99
+ delete options.tool_choice;
100
+ }
101
+ // eslint-disable-next-line no-param-reassign
102
+ delete options.tools;
103
+ }
104
+ else if (options.tool_choice !== undefined) {
105
+ throw new Error(`If "tool_choice" is provided, "tools" must also be.`);
106
+ }
107
+ const chatResult = await this.llm._generate(promptMessages, options, runManager);
108
+ const chatGenerationContent = chatResult.generations[0].message.content;
109
+ if (typeof chatGenerationContent !== "string") {
110
+ throw new Error("AnthropicFunctions does not support non-string output.");
111
+ }
112
+ if (forced) {
113
+ const parser = new fast_xml_parser_1.XMLParser();
114
+ const result = parser.parse(`<function_calls>\n<invoke><tool_name>${toolCall}</tool_name>${chatGenerationContent}</function_calls>`);
115
+ if (toolCall === undefined) {
116
+ throw new Error(`Could not parse called function from model output.`);
117
+ }
118
+ const invocations = Array.isArray(result.function_calls?.invoke ?? [])
119
+ ? result.function_calls.invoke
120
+ : [result.function_calls.invoke];
121
+ const responseMessageWithFunctions = new messages_1.AIMessage({
122
+ content: "",
123
+ additional_kwargs: {
124
+ tool_calls: invocations.map((toolInvocation, i) => ({
125
+ id: i.toString(),
126
+ type: "function",
127
+ function: {
128
+ name: toolInvocation.tool_name,
129
+ arguments: JSON.stringify(toolInvocation.parameters),
130
+ },
131
+ })),
132
+ },
133
+ });
134
+ return {
135
+ generations: [{ message: responseMessageWithFunctions, text: "" }],
136
+ };
137
+ }
138
+ else if (chatGenerationContent.includes("<function_calls>")) {
139
+ const parser = new fast_xml_parser_1.XMLParser();
140
+ const result = parser.parse(`${chatGenerationContent}</function_calls>`);
141
+ const invocations = Array.isArray(result.function_calls?.invoke ?? [])
142
+ ? result.function_calls.invoke
143
+ : [result.function_calls.invoke];
144
+ const responseMessageWithFunctions = new messages_1.AIMessage({
145
+ content: chatGenerationContent.split("<function_calls>")[0],
146
+ additional_kwargs: {
147
+ tool_calls: invocations.map((toolInvocation, i) => ({
148
+ id: i.toString(),
149
+ type: "function",
150
+ function: {
151
+ name: toolInvocation.tool_name,
152
+ arguments: JSON.stringify(toolInvocation.parameters),
153
+ },
154
+ })),
155
+ },
156
+ });
157
+ return {
158
+ generations: [{ message: responseMessageWithFunctions, text: "" }],
159
+ };
160
+ }
161
+ return chatResult;
162
+ }
163
+ async _generate(messages, options, _runManager) {
164
+ return this._prepareAndParseToolCall({
165
+ messages,
166
+ options,
167
+ systemPromptTemplate: this.systemPromptTemplate,
168
+ stopSequences: this.stopSequences ?? [],
169
+ });
170
+ }
171
+ _llmType() {
172
+ return "anthropic_tool_calling";
173
+ }
174
+ withStructuredOutput({ schema, name, method, includeRaw, }) {
175
+ if (method === "jsonMode") {
176
+ throw new Error(`Anthropic only supports "functionCalling" as a method.`);
177
+ }
178
+ const functionName = name ?? "extract";
179
+ const outputParser = new openai_tools_1.JsonOutputKeyToolsParser({
180
+ returnSingle: true,
181
+ keyName: functionName,
182
+ });
183
+ let tools;
184
+ if (isZodSchema(schema)) {
185
+ const jsonSchema = (0, zod_to_json_schema_1.zodToJsonSchema)(schema);
186
+ tools = [
187
+ {
188
+ type: "function",
189
+ function: {
190
+ name: functionName,
191
+ description: jsonSchema.description,
192
+ parameters: jsonSchema,
193
+ },
194
+ },
195
+ ];
196
+ }
197
+ else {
198
+ tools = [
199
+ {
200
+ type: "function",
201
+ function: {
202
+ name: functionName,
203
+ description: schema.description,
204
+ parameters: schema,
205
+ },
206
+ },
207
+ ];
208
+ }
209
+ const llm = this.bind({
210
+ tools,
211
+ tool_choice: {
212
+ type: "function",
213
+ function: {
214
+ name: functionName,
215
+ },
216
+ },
217
+ });
218
+ if (!includeRaw) {
219
+ return llm.pipe(outputParser).withConfig({
220
+ runName: "ChatAnthropicStructuredOutput",
221
+ });
222
+ }
223
+ const parserAssign = runnables_1.RunnablePassthrough.assign({
224
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
225
+ parsed: (input, config) => outputParser.invoke(input.raw, config),
226
+ });
227
+ const parserNone = runnables_1.RunnablePassthrough.assign({
228
+ parsed: () => null,
229
+ });
230
+ const parsedWithFallback = parserAssign.withFallbacks({
231
+ fallbacks: [parserNone],
232
+ });
233
+ return runnables_1.RunnableSequence.from([
234
+ {
235
+ raw: llm,
236
+ },
237
+ parsedWithFallback,
238
+ ]).withConfig({
239
+ runName: "StructuredOutputRunnable",
240
+ });
241
+ }
242
+ }
243
+ exports.ChatAnthropicTools = ChatAnthropicTools;
244
+ function isZodSchema(input) {
245
+ // Check for a characteristic method of Zod schemas
246
+ return typeof input?.parse === "function";
247
+ }
@@ -0,0 +1,51 @@
1
+ import { BaseMessage } from "@langchain/core/messages";
2
+ import { ChatGenerationChunk, ChatResult } from "@langchain/core/outputs";
3
+ import { BaseChatModel, BaseChatModelParams } from "@langchain/core/language_models/chat_models";
4
+ import { CallbackManagerForLLMRun } from "@langchain/core/callbacks/manager";
5
+ import { BasePromptTemplate } from "@langchain/core/prompts";
6
+ import { BaseLanguageModelCallOptions, BaseLanguageModelInput, StructuredOutputMethodParams, ToolDefinition } from "@langchain/core/language_models/base";
7
+ import { Runnable } from "@langchain/core/runnables";
8
+ import { type AnthropicInput } from "../chat_models.js";
9
+ export interface ChatAnthropicToolsCallOptions extends BaseLanguageModelCallOptions {
10
+ tools?: ToolDefinition[];
11
+ tool_choice?: "auto" | {
12
+ function: {
13
+ name: string;
14
+ };
15
+ type: "function";
16
+ };
17
+ }
18
+ export type ChatAnthropicToolsInput = Partial<AnthropicInput> & BaseChatModelParams & {
19
+ llm?: BaseChatModel;
20
+ systemPromptTemplate?: BasePromptTemplate;
21
+ };
22
+ /**
23
+ * Experimental wrapper over Anthropic chat models that adds support for
24
+ * a function calling interface.
25
+ */
26
+ export declare class ChatAnthropicTools extends BaseChatModel<ChatAnthropicToolsCallOptions> {
27
+ llm: BaseChatModel;
28
+ stopSequences?: string[];
29
+ systemPromptTemplate: BasePromptTemplate;
30
+ lc_namespace: string[];
31
+ static lc_name(): string;
32
+ constructor(fields?: ChatAnthropicToolsInput);
33
+ invocationParams(): any;
34
+ /** @ignore */
35
+ _identifyingParams(): Record<string, any>;
36
+ _streamResponseChunks(messages: BaseMessage[], options: this["ParsedCallOptions"], runManager?: CallbackManagerForLLMRun): AsyncGenerator<ChatGenerationChunk>;
37
+ _prepareAndParseToolCall({ messages, options, runManager, systemPromptTemplate, stopSequences, }: {
38
+ messages: BaseMessage[];
39
+ options: ChatAnthropicToolsCallOptions;
40
+ runManager?: CallbackManagerForLLMRun;
41
+ systemPromptTemplate?: BasePromptTemplate;
42
+ stopSequences: string[];
43
+ }): Promise<ChatResult>;
44
+ _generate(messages: BaseMessage[], options: this["ParsedCallOptions"], _runManager?: CallbackManagerForLLMRun | undefined): Promise<ChatResult>;
45
+ _llmType(): string;
46
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>({ schema, name, method, includeRaw, }: StructuredOutputMethodParams<RunOutput, false>): Runnable<BaseLanguageModelInput, RunOutput>;
47
+ withStructuredOutput<RunOutput extends Record<string, any> = Record<string, any>>({ schema, name, method, includeRaw, }: StructuredOutputMethodParams<RunOutput, true>): Runnable<BaseLanguageModelInput, {
48
+ raw: BaseMessage;
49
+ parsed: RunOutput;
50
+ }>;
51
+ }
@@ -0,0 +1,243 @@
1
+ import { XMLParser } from "fast-xml-parser";
2
+ import { AIMessage, SystemMessage, } from "@langchain/core/messages";
3
+ import { BaseChatModel, } from "@langchain/core/language_models/chat_models";
4
+ import { RunnablePassthrough, RunnableSequence, } from "@langchain/core/runnables";
5
+ import { JsonOutputKeyToolsParser } from "@langchain/core/output_parsers/openai_tools";
6
+ import { zodToJsonSchema } from "zod-to-json-schema";
7
+ import { ChatAnthropic } from "../chat_models.js";
8
+ import { DEFAULT_TOOL_SYSTEM_PROMPT, formatAsXMLRepresentation, } from "./utils/tool_calling.js";
9
+ /**
10
+ * Experimental wrapper over Anthropic chat models that adds support for
11
+ * a function calling interface.
12
+ */
13
+ export class ChatAnthropicTools extends BaseChatModel {
14
+ static lc_name() {
15
+ return "ChatAnthropicTools";
16
+ }
17
+ constructor(fields) {
18
+ super(fields ?? {});
19
+ Object.defineProperty(this, "llm", {
20
+ enumerable: true,
21
+ configurable: true,
22
+ writable: true,
23
+ value: void 0
24
+ });
25
+ Object.defineProperty(this, "stopSequences", {
26
+ enumerable: true,
27
+ configurable: true,
28
+ writable: true,
29
+ value: void 0
30
+ });
31
+ Object.defineProperty(this, "systemPromptTemplate", {
32
+ enumerable: true,
33
+ configurable: true,
34
+ writable: true,
35
+ value: void 0
36
+ });
37
+ Object.defineProperty(this, "lc_namespace", {
38
+ enumerable: true,
39
+ configurable: true,
40
+ writable: true,
41
+ value: ["langchain", "experimental", "chat_models"]
42
+ });
43
+ this.llm = fields?.llm ?? new ChatAnthropic(fields);
44
+ this.systemPromptTemplate =
45
+ fields?.systemPromptTemplate ?? DEFAULT_TOOL_SYSTEM_PROMPT;
46
+ this.stopSequences =
47
+ fields?.stopSequences ?? this.llm.stopSequences;
48
+ }
49
+ invocationParams() {
50
+ return this.llm.invocationParams();
51
+ }
52
+ /** @ignore */
53
+ _identifyingParams() {
54
+ return this.llm._identifyingParams();
55
+ }
56
+ async *_streamResponseChunks(messages, options, runManager) {
57
+ yield* this.llm._streamResponseChunks(messages, options, runManager);
58
+ }
59
+ async _prepareAndParseToolCall({ messages, options, runManager, systemPromptTemplate = DEFAULT_TOOL_SYSTEM_PROMPT, stopSequences, }) {
60
+ let promptMessages = messages;
61
+ let forced = false;
62
+ let toolCall;
63
+ if (options.tools !== undefined && options.tools.length > 0) {
64
+ const content = await systemPromptTemplate.format({
65
+ tools: `<tools>\n${options.tools
66
+ .map(formatAsXMLRepresentation)
67
+ .join("\n\n")}</tools>`,
68
+ });
69
+ if (promptMessages.length && promptMessages[0]._getType() !== "system") {
70
+ const systemMessage = new SystemMessage({ content });
71
+ promptMessages = [systemMessage].concat(promptMessages);
72
+ }
73
+ else {
74
+ const systemMessage = new SystemMessage({
75
+ content: `${content}\n\n${promptMessages[0].content}`,
76
+ });
77
+ promptMessages = [systemMessage].concat(promptMessages.slice(1));
78
+ }
79
+ // eslint-disable-next-line no-param-reassign
80
+ options.stop = stopSequences.concat(["</function_calls>"]);
81
+ if (options.tool_choice && options.tool_choice !== "auto") {
82
+ toolCall = options.tool_choice.function.name;
83
+ forced = true;
84
+ const matchingFunction = options.tools.find(
85
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
86
+ (tool) => tool.function.name === toolCall);
87
+ if (!matchingFunction) {
88
+ throw new Error(`No matching function found for passed "tool_choice"`);
89
+ }
90
+ promptMessages = promptMessages.concat([
91
+ new AIMessage({
92
+ content: `<function_calls>\n<invoke><tool_name>${toolCall}</tool_name>`,
93
+ }),
94
+ ]);
95
+ // eslint-disable-next-line no-param-reassign
96
+ delete options.tool_choice;
97
+ }
98
+ // eslint-disable-next-line no-param-reassign
99
+ delete options.tools;
100
+ }
101
+ else if (options.tool_choice !== undefined) {
102
+ throw new Error(`If "tool_choice" is provided, "tools" must also be.`);
103
+ }
104
+ const chatResult = await this.llm._generate(promptMessages, options, runManager);
105
+ const chatGenerationContent = chatResult.generations[0].message.content;
106
+ if (typeof chatGenerationContent !== "string") {
107
+ throw new Error("AnthropicFunctions does not support non-string output.");
108
+ }
109
+ if (forced) {
110
+ const parser = new XMLParser();
111
+ const result = parser.parse(`<function_calls>\n<invoke><tool_name>${toolCall}</tool_name>${chatGenerationContent}</function_calls>`);
112
+ if (toolCall === undefined) {
113
+ throw new Error(`Could not parse called function from model output.`);
114
+ }
115
+ const invocations = Array.isArray(result.function_calls?.invoke ?? [])
116
+ ? result.function_calls.invoke
117
+ : [result.function_calls.invoke];
118
+ const responseMessageWithFunctions = new AIMessage({
119
+ content: "",
120
+ additional_kwargs: {
121
+ tool_calls: invocations.map((toolInvocation, i) => ({
122
+ id: i.toString(),
123
+ type: "function",
124
+ function: {
125
+ name: toolInvocation.tool_name,
126
+ arguments: JSON.stringify(toolInvocation.parameters),
127
+ },
128
+ })),
129
+ },
130
+ });
131
+ return {
132
+ generations: [{ message: responseMessageWithFunctions, text: "" }],
133
+ };
134
+ }
135
+ else if (chatGenerationContent.includes("<function_calls>")) {
136
+ const parser = new XMLParser();
137
+ const result = parser.parse(`${chatGenerationContent}</function_calls>`);
138
+ const invocations = Array.isArray(result.function_calls?.invoke ?? [])
139
+ ? result.function_calls.invoke
140
+ : [result.function_calls.invoke];
141
+ const responseMessageWithFunctions = new AIMessage({
142
+ content: chatGenerationContent.split("<function_calls>")[0],
143
+ additional_kwargs: {
144
+ tool_calls: invocations.map((toolInvocation, i) => ({
145
+ id: i.toString(),
146
+ type: "function",
147
+ function: {
148
+ name: toolInvocation.tool_name,
149
+ arguments: JSON.stringify(toolInvocation.parameters),
150
+ },
151
+ })),
152
+ },
153
+ });
154
+ return {
155
+ generations: [{ message: responseMessageWithFunctions, text: "" }],
156
+ };
157
+ }
158
+ return chatResult;
159
+ }
160
+ async _generate(messages, options, _runManager) {
161
+ return this._prepareAndParseToolCall({
162
+ messages,
163
+ options,
164
+ systemPromptTemplate: this.systemPromptTemplate,
165
+ stopSequences: this.stopSequences ?? [],
166
+ });
167
+ }
168
+ _llmType() {
169
+ return "anthropic_tool_calling";
170
+ }
171
+ withStructuredOutput({ schema, name, method, includeRaw, }) {
172
+ if (method === "jsonMode") {
173
+ throw new Error(`Anthropic only supports "functionCalling" as a method.`);
174
+ }
175
+ const functionName = name ?? "extract";
176
+ const outputParser = new JsonOutputKeyToolsParser({
177
+ returnSingle: true,
178
+ keyName: functionName,
179
+ });
180
+ let tools;
181
+ if (isZodSchema(schema)) {
182
+ const jsonSchema = zodToJsonSchema(schema);
183
+ tools = [
184
+ {
185
+ type: "function",
186
+ function: {
187
+ name: functionName,
188
+ description: jsonSchema.description,
189
+ parameters: jsonSchema,
190
+ },
191
+ },
192
+ ];
193
+ }
194
+ else {
195
+ tools = [
196
+ {
197
+ type: "function",
198
+ function: {
199
+ name: functionName,
200
+ description: schema.description,
201
+ parameters: schema,
202
+ },
203
+ },
204
+ ];
205
+ }
206
+ const llm = this.bind({
207
+ tools,
208
+ tool_choice: {
209
+ type: "function",
210
+ function: {
211
+ name: functionName,
212
+ },
213
+ },
214
+ });
215
+ if (!includeRaw) {
216
+ return llm.pipe(outputParser).withConfig({
217
+ runName: "ChatAnthropicStructuredOutput",
218
+ });
219
+ }
220
+ const parserAssign = RunnablePassthrough.assign({
221
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
222
+ parsed: (input, config) => outputParser.invoke(input.raw, config),
223
+ });
224
+ const parserNone = RunnablePassthrough.assign({
225
+ parsed: () => null,
226
+ });
227
+ const parsedWithFallback = parserAssign.withFallbacks({
228
+ fallbacks: [parserNone],
229
+ });
230
+ return RunnableSequence.from([
231
+ {
232
+ raw: llm,
233
+ },
234
+ parsedWithFallback,
235
+ ]).withConfig({
236
+ runName: "StructuredOutputRunnable",
237
+ });
238
+ }
239
+ }
240
+ function isZodSchema(input) {
241
+ // Check for a characteristic method of Zod schemas
242
+ return typeof input?.parse === "function";
243
+ }
@@ -0,0 +1,52 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.formatAsXMLRepresentation = exports.DEFAULT_TOOL_SYSTEM_PROMPT = void 0;
4
+ const fast_xml_parser_1 = require("fast-xml-parser");
5
+ const prompts_1 = require("@langchain/core/prompts");
6
+ exports.DEFAULT_TOOL_SYSTEM_PROMPT =
7
+ /* #__PURE__ */ prompts_1.PromptTemplate.fromTemplate(`In this environment you have access to a set of tools you can use to answer the user's question.
8
+
9
+ You may call them like this:
10
+ <function_calls>
11
+ <invoke>
12
+ <tool_name>$TOOL_NAME</tool_name>
13
+ <parameters>
14
+ <$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>
15
+ ...
16
+ </parameters>
17
+ </invoke>
18
+ </function_calls>
19
+
20
+ Here are the tools available:
21
+ {tools}`);
22
+ function formatAsXMLRepresentation(tool) {
23
+ const builder = new fast_xml_parser_1.XMLBuilder();
24
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
25
+ const toolParamProps = tool.function.parameters?.properties;
26
+ const parameterXml = Object.keys(toolParamProps)
27
+ .map((key) => {
28
+ const parameterData = toolParamProps[key];
29
+ let xml = `<parameter>
30
+ <name>${key}</name>
31
+ <type>${parameterData.type}</type>`;
32
+ if (parameterData.description) {
33
+ xml += `\n<description>${parameterData.description}</description>`;
34
+ }
35
+ if (parameterData.type === "array" && parameterData.items) {
36
+ xml += `\n<items>${builder.build(parameterData.items.properties)}</items>`;
37
+ }
38
+ if (parameterData.properties) {
39
+ xml += `\n<properties>\n${builder.build(parameterData.properties)}\n</properties>`;
40
+ }
41
+ return `${xml}\n</parameter>`;
42
+ })
43
+ .join("\n");
44
+ return `<tool_description>
45
+ <tool_name>${tool.function.name}</tool_name>
46
+ <description>${tool.function.description}</description>
47
+ <parameters>
48
+ ${parameterXml}
49
+ </parameters>
50
+ </tool_description>`;
51
+ }
52
+ exports.formatAsXMLRepresentation = formatAsXMLRepresentation;
@@ -0,0 +1,8 @@
1
+ import { PromptTemplate } from "@langchain/core/prompts";
2
+ import { ToolDefinition } from "@langchain/core/language_models/base";
3
+ export declare const DEFAULT_TOOL_SYSTEM_PROMPT: PromptTemplate<import("@langchain/core/prompts").ParamsFromFString<"In this environment you have access to a set of tools you can use to answer the user's question.\n\nYou may call them like this:\n<function_calls>\n<invoke>\n<tool_name>$TOOL_NAME</tool_name>\n<parameters>\n<$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>\n...\n</parameters>\n</invoke>\n</function_calls>\n\nHere are the tools available:\n{tools}">, any>;
4
+ export type ToolInvocation = {
5
+ tool_name: string;
6
+ parameters: Record<string, unknown>;
7
+ };
8
+ export declare function formatAsXMLRepresentation(tool: ToolDefinition): string;
@@ -0,0 +1,48 @@
1
+ import { XMLBuilder } from "fast-xml-parser";
2
+ import { PromptTemplate } from "@langchain/core/prompts";
3
+ export const DEFAULT_TOOL_SYSTEM_PROMPT =
4
+ /* #__PURE__ */ PromptTemplate.fromTemplate(`In this environment you have access to a set of tools you can use to answer the user's question.
5
+
6
+ You may call them like this:
7
+ <function_calls>
8
+ <invoke>
9
+ <tool_name>$TOOL_NAME</tool_name>
10
+ <parameters>
11
+ <$PARAMETER_NAME>$PARAMETER_VALUE</$PARAMETER_NAME>
12
+ ...
13
+ </parameters>
14
+ </invoke>
15
+ </function_calls>
16
+
17
+ Here are the tools available:
18
+ {tools}`);
19
+ export function formatAsXMLRepresentation(tool) {
20
+ const builder = new XMLBuilder();
21
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
22
+ const toolParamProps = tool.function.parameters?.properties;
23
+ const parameterXml = Object.keys(toolParamProps)
24
+ .map((key) => {
25
+ const parameterData = toolParamProps[key];
26
+ let xml = `<parameter>
27
+ <name>${key}</name>
28
+ <type>${parameterData.type}</type>`;
29
+ if (parameterData.description) {
30
+ xml += `\n<description>${parameterData.description}</description>`;
31
+ }
32
+ if (parameterData.type === "array" && parameterData.items) {
33
+ xml += `\n<items>${builder.build(parameterData.items.properties)}</items>`;
34
+ }
35
+ if (parameterData.properties) {
36
+ xml += `\n<properties>\n${builder.build(parameterData.properties)}\n</properties>`;
37
+ }
38
+ return `${xml}\n</parameter>`;
39
+ })
40
+ .join("\n");
41
+ return `<tool_description>
42
+ <tool_name>${tool.function.name}</tool_name>
43
+ <description>${tool.function.description}</description>
44
+ <parameters>
45
+ ${parameterXml}
46
+ </parameters>
47
+ </tool_description>`;
48
+ }
@@ -30,7 +30,7 @@ test("Test ChatAnthropic Generate", async () => {
30
30
  }
31
31
  console.log({ res });
32
32
  });
33
- test("Test ChatAnthropic Generate w/ ClientOptions", async () => {
33
+ test.skip("Test ChatAnthropic Generate w/ ClientOptions", async () => {
34
34
  const chat = new ChatAnthropic({
35
35
  modelName: "claude-3-sonnet-20240229",
36
36
  maxRetries: 0,
@@ -127,7 +127,7 @@ test("Test ChatAnthropic in streaming mode with a signal", async () => {
127
127
  }).rejects.toThrow();
128
128
  console.log({ nrNewTokens, streamedCompletion });
129
129
  }, 5000);
130
- test("Test ChatAnthropic prompt value", async () => {
130
+ test.skip("Test ChatAnthropic prompt value", async () => {
131
131
  const chat = new ChatAnthropic({
132
132
  modelName: "claude-3-sonnet-20240229",
133
133
  maxRetries: 0,
@@ -142,7 +142,7 @@ test("Test ChatAnthropic prompt value", async () => {
142
142
  }
143
143
  console.log({ res });
144
144
  });
145
- test("ChatAnthropic, docs, prompt templates", async () => {
145
+ test.skip("ChatAnthropic, docs, prompt templates", async () => {
146
146
  const chat = new ChatAnthropic({
147
147
  modelName: "claude-3-sonnet-20240229",
148
148
  maxRetries: 0,
@@ -162,7 +162,7 @@ test("ChatAnthropic, docs, prompt templates", async () => {
162
162
  ]);
163
163
  console.log(responseA.generations);
164
164
  });
165
- test("ChatAnthropic, longer chain of messages", async () => {
165
+ test.skip("ChatAnthropic, longer chain of messages", async () => {
166
166
  const chat = new ChatAnthropic({
167
167
  modelName: "claude-3-sonnet-20240229",
168
168
  maxRetries: 0,
@@ -180,7 +180,7 @@ test("ChatAnthropic, longer chain of messages", async () => {
180
180
  ]);
181
181
  console.log(responseA.generations);
182
182
  });
183
- test("ChatAnthropic, Anthropic apiUrl set manually via constructor", async () => {
183
+ test.skip("ChatAnthropic, Anthropic apiUrl set manually via constructor", async () => {
184
184
  // Pass the default URL through (should use this, and work as normal)
185
185
  const anthropicApiUrl = "https://api.anthropic.com";
186
186
  const chat = new ChatAnthropic({
@@ -249,6 +249,26 @@ test("Test ChatAnthropic headers passed through", async () => {
249
249
  },
250
250
  });
251
251
  const message = new HumanMessage("Hello!");
252
- const res = await chat.call([message]);
252
+ const res = await chat.invoke([message]);
253
253
  console.log({ res });
254
254
  });
255
+ test("Test ChatAnthropic multimodal", async () => {
256
+ const chat = new ChatAnthropic({
257
+ modelName: "claude-3-sonnet-20240229",
258
+ maxRetries: 0,
259
+ });
260
+ const res = await chat.invoke([
261
+ new HumanMessage({
262
+ content: [
263
+ {
264
+ type: "image_url",
265
+ image_url: {
266
+ url: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAMCAggHCQgGCQgICAcICAgICAgICAYICAgHDAgHCAgICAgIBggICAgICAgICBYICAgICwkKCAgNDQoIDggICQgBAwQEBgUGCgYGCBALCg0QCg0NEA0KCg8LDQoKCgoLDgoQDQoLDQoKCg4NDQ0NDgsQDw0OCg4NDQ4NDQoJDg8OCP/AABEIALAAsAMBEQACEQEDEQH/xAAdAAEAAgEFAQAAAAAAAAAAAAAABwgJAQIEBQYD/8QANBAAAgIBAwIDBwQCAgIDAAAAAQIAAwQFERIIEwYhMQcUFyJVldQjQVGBcZEJMzJiFRYk/8QAGwEBAAMAAwEAAAAAAAAAAAAAAAQFBgEDBwL/xAA5EQACAQIDBQQJBAIBBQAAAAAAAQIDEQQhMQVBUWGREhRxgRMVIjJSU8HR8CNyobFCguEGJGKi4v/aAAwDAQACEQMRAD8ApfJplBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBAEAQBANl16qOTEKB6kkAD+z5Tkcj0On+z7Ub1FlOmanejeavj6dqV6kfsQ1OK4IP8AIM6pVYR1kuqJdLCV6qvCnJ/6v66nL+Ems/RNc+y63+BOvvFL411O/wBW4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6D4Saz9E1z7Lrf4Ed4pfGuo9W4r5T6HE1D2e6lQpsu0zU6EXzZ8jTtSoUD9yWuxUAA/kmdkasJaSXVHRVwlekrzpyX+r+mh56m9WHJSGU+hUgg/wBjynaRORvnAEAQBAEAQBAEAQCbennpVzfER95LHE0tX4tlsnJr2B2srw6yQLCpBQ3Me1W+4/VZLKlh4jFRo5ay4cPH7f0XWA2XUxft37MONs34ffRcy/Xsu6bdG0UK2Nh1tkAbHMyAt+Wx2HIi11/SDcQe3jrTXv6IJRVcRUqe88uC0Nxhdn0MMv0458XnJ+e7wVlyJPJkYsTSAIAgCAIAgCAIBqDAIx9qHTbo2tBmycOtcgjYZmOBRlqdjxJtQDuhdye3ette/qhkmliKlP3XlwehXYrZ9DEr9SOfFZS6rXwd1yKCdQ3Srm+HT7yGOXpbPxXLVOLUMTtXXmVgkVliQgvU9qx9h+kz11Ne4fFRrZaS4cfD7f2YfH7LqYT279qHHevH76PlvhKTClEAQBAEAQBAJp6WOn0+I80i7mumYnF8x1LIbSSe3iV2DYq13ElnQ8q6gdijWUuIeKxHoY5e89PuXWy8D3qp7S9iOvN/D9+XiZRNN06uiuvHqrSqmpFrqqrVUrrrUBUREUBVVVAAUAAATNNtu7PR4xUUoxVkskloktxyCZwfRj26jetHPtzrMXSM4Uabj7Vrfj10O2ZdsDbb3bqrCKEYmpeyED8Hs53LZVwvsPg4qN6kbt+OS8t5hdobYqOo44edorK6SzfmtFpz14H16f8Arkz6cmrD1e9crBvsFZy3ropvxC2yo7NTXXXbjhtuXcTmisz91hX2yr4KLjemrNbuPXeMDtuoqihiGnF/5ZJx55ZNceF76GQSUJuhAEAQBAEAhb239WWl+H391s7mXnbAnExu2WqUjdWyLHda6Qw2IXdrCCGFZX5pMo4WdXNZLiyoxm1KOFfZl7UuCtdeN2kvzcRB4d/5JMV7OOVpWRRSWAFmPk1ZTKN9uT1PRi+QHnsj2H12DHYGXLZzS9mV3zVvuVFL/qGDlapSaXFST6qyfS/3tb4M8a4up49WoYlyZGLcCUsTf1B2ZGVgHrsRgVNbqrIwIYAjaVc4Sg+zJWZqaVWFWCnB3T0/PodnqOnV312Y9taW02o1dtViq9dlbAq6OjAqyspIKkEEGfKbTuj7lFSTjJXTyaejXAxd9U/T6fDmYBTzbTMvm+G7FnNRBHcxLLDuWankCrueVlRG5dq7nOlwuI9NHP3lr9zzjamA7rU9n3Jacn8P25eBC0mFKIAgCAIBtdwASfQDc/4nIbsZXulr2ZDR9HwsYpxybqxmZe4Xl71cquyMR69hO3jg+fy0r5n1OWxNX0lRvdovBflz1DZuG7vh4xtZtXl+55vpp5EsyKWZ5X2seH783TdRwsZgmVk4OVRQzMUUXPRYle7gEoCxA5gEqDvsdp2U5KM03omv7I+Ig6lKUIuzaaXmigPtb6HNQ0bEytTGXjZeLiKlhWuu6rINPMLbY1bFqkXHQ908b7CyK+wUqFe+pY2FSSjZpvnl+MwmJ2JVw9OVTtqUYq+Sadt+WaVtd9+W+uLLv5HzB8j/AIlgZ8yRdGfUXXq2JXpGTZtquFUE+cnfMxU2Wu9CzEvaicEsG+/MdzYLbsmexmHdOXaS9l/w+H2PQ9kY9V6apyftxVtdUtJc3x58iykrjQCAIAgFdurzqbPh+lMHFKHVspC6FuLLh427Icp0O4d2ZWREb5WZLGbktJrssMJhvSu8vdX8vh9zP7X2i8LBRp27b46Rj8Vt73JebyVnCfSz0jNqh/8AsGsrZZRcxuoxrms7ua7HmcvLYkOaXJ5Ctjvkb8n/AE+K3TcVi+x+nS6rdyX33eJTbL2S636+JTaeaTveTf8AlLlwjv35ZFmfHnSnoWo47Yo0/FxLOBWnJw8ejHuobb5GVqkUOqnY9qwOjDyI9CKyGKqwd+03ybdjS19mYarHs+jSe5pJNdP6KudBPiTIwNYz/D1jA1WJk91AWKLqGJctDWVg+QFlfdQtsGcVY+//AFgSzx0VKmqi5dJK/wCeZm9iVJ0sRPDye6WWdu1BpXWeV78M8uGd/wCURuCJuqX2YjWNHzMYJyyaKzmYm3Hl71SrOqKW8h307mOT5fLc3mPUSsNV9HUT3aPwf5crNpYbvGHlG2azj+5Zrrp5mKFHBAI9CNx/iak8vTubpwBAEAQDtPCekLk5WHiON0yczFx3H8pbkVVMP7VyJ8zfZi3wTfRHdRh26kI8ZRXk5IzREf6mPPXTSAIB1/iPQa8yjIwrVD05NFuPYrAFWrsrat1YHyIKsRsf2nMXZpo+ZR7UXF77rqYW2xHrJqsHG2smu1T6rapKWKf8OCP6mxvfNHj1nH2XqsnfW6yOVpGr241teVRY9ORS4sqtrPF67B6Mp/2NiCGBIIYMQeGlJWaujsp1JU5KcHZrQyZdK/U3X4ipONdwq1fGQNkVL5JkVbhfe8cE/wDgWKq1e5NFjKD8ttLPm8ThnSd17r0+35qej7N2hHFQs8prVfVcv6J4kIuBAKtdWnV8uj89I090fVeP/wCi8hXq05CvIcg26PmMpDCpgVqUrZaCGqrussLhPSe3P3f7/wCOf4s9tTaXd16On77/APXn48EU58OYl+RremrrRyHbJzdPbI9+LvZZjW21vUlgs5FMe4OqmshVrrscca9jtcSaVKXotydrcVr58zH04znioLFXd3G/a17L08E3u5vJEveGeobX/Cuq2YmttbbjX3NflUu7ZC1VW2OTlaZZuzDHrIbbGXZOFbV9qmwfLElh6Venelqsl4rc+fP6FtT2hicHiHDEu8W7u+ii8lKObtHL3fH/AC1tn1AdReJ4exVvJW/MyEJwcVWG9x2G1zkb8MVNwTbt83kqhmYCVVDDyqytot7/ADeanG46GFh2nm37q4/8c/qVr/4/fZ9k5Obm+J7+Xa430V2soVcrNuuW3LtT+RQUNZKjj3L2QHlRYqWOPqJRVJcvJJWRnth4epKpLE1FqnZ8XJ3b8MuG/LQvdKQ2ZqB/qAYXfFmkLjZWZiINkxszKx0H8JVkW1KP6VAJsIPtRT4pPqjyKtDsVJx4SkvJSdjq59HSIAgCAdp4T1dcbKw8tzsmNmYuQ5/hKsiq1j/SoTPma7UWuKa6o7qM+xUhLhKL8lJXM0RP+pjz100gCAIBjA6x/Y9ZpGq35KofcdSssy8ewA8Vvcl8rHJ3OzrazXAeQNVq8d+3Zx0mDrKpTS3rLy3P6HnG18I6FdzS9mWa/c9V9fPkQTJxRnf+AfHeRpOXj6pjHa/GsDhd+K2p6W0WHY/p31lqidiVDchsyqR8VIKpFxlo/wAv5EjD15UKiqw1X8revMy++DfFtOo4uNqNDcsfKprvrJ8iFZQeLD1Dod0KnzVlI/aZKcXCTi9UerUqkasFOLumk14M8T1L+0uzRdHzdRp8skKlGO2wPC+6xKUt2PkezzN3E7g8NtjvO7D01UqKL03+CzIe0MQ8Ph5VI66Lxbsv7Ks9D3ThTqG/iXOBvSvJsGHTae4L8lWDXZ2QzMzXMt7MoWzzNyW2PzPaYWeNxDj+nDLLPw4dPsZ7Y+CVb/ua3tO7tfitZPzyS5XJS6zOlu3XAmrYSh9Rpq7N2OzKozMYF3RUZyEXIqZ325lVtVyrMOFUjYPEql7MtP6f2J+1tmvE2qU/fWWusfo1/P8AVWfbjruoWabpFGrl/wD5Wq/UOyMhO3mV6QFxaU98BCuzW5dNxW2wcraqeZawku1pQjFVJOn7uWmna1y8uhmMdUqOhSjiPfTlr73o0rXfi1k96V7nq/YP0n6lr99OdqgysfS6qqKw2QbK8rKx6kWrHxcdG2toxlrUA3lU+Q71c3ta+rpr4qFJONOzlnpom9/N8vpkTMBsyriZKeITUEla+rSyUbapLyvzeZkT0fR6saqvFprSmilFrqqrUJXXWo2VEUABVUDbYSgbbd3qbyMVFWSskcucH0ag/wCoBhd8WauuTlZmWh3TIzMrIQ/yluRbap/tXBmwguzFLgkuiPIq0+3UnLjKT8nJ2Orn0dIgCAIBtdAQQfQjY/4nIauZXulr2nDWNHw8kvyyaKxh5e/Hl71SqozsF8h307eQB5fLcvkPQZbE0vR1Gt2q8H+WPUNm4nvGHjK92spfuWT66+ZLMilmIAgHm/aL4ExtVxL9PyaVvptRtkb1WwA9uyths1dqNsRYhDKf39Z905uElKLszor0YVoOE1dP86mH7R/DORdi5OeKz2sI4iZZIKtU+Q11dPJSvl+rS1ZBIKsyDY7krrXJKSjxvbyzPKY0ZuMprSNlLim21p4rPh1t6fA9ieq34Ka1RhW5OA7XKbMcC6ypq7DU/doT9cLyBPNK7ECglmT0nW60FLsN2fPnnroSI4KvKl6aMLxz0zeTavbW3hfy3Wq/4+fbVQKbPDd9wW7vWZGnK2wW2l17l9FTehsS0W5PA/M62uV5CqzhV4+i7+kS5Px4/T8z02wcXHsvDyed24+DzaXg7u3PLLSderP2f3arombi0KXyEFWVVWBu1jU2pc1SD93sqWxAP3dlkHC1FCqm9NOuRd7ToOvhpwjrk14xadv4K7dEPU5gYOI2iZ+RXiql1l2Hk2fJjtVae5ZVbaSUrsW42WB7O2jpYqg8k+exxuGnKXbgr8eOWXmUGxtpUqdP0FV9m12m9Gm72/8AFp8dfEmb22dZmlaXjv7nk42pag4K0U49q3U1t5fqZV1LFErTfl2g4st/8VCjnZXDo4Oc37ScVvv9L/iLXG7Xo0IfpyU57kndeLa0X8vRcq59OnsAzPFWY3iTVmezBa3uMbQOWo2qdhSibcUwa+IrPEBSq9pB/wBjV2GIrxoR9HT1/r/6M/s7A1MbU7ziHeN75/5tbuUF/Oml28h0oDfCAIBE/VL7TRo+j5uSr8cm6s4eJtx5e9XKyK6hvJuwncyCPP5aW8j6GVhqXpKiW7V+C/LFZtLE93w8pXzeUf3PJdNfIxQIgAAHoBsP8TUnl6VjdOAIAgCAIBNPSx1BHw5mE3c20zL4JmIoZjUQT28uusblmp5EMiDlZUTsHaulDDxWH9NHL3lp9i62Xj+61Pa9yWvJ/F9+XgZRNN1Ku+uvIqsS2m1FsqtrZXrsrYBkdHUlWVlIIYEggzNNNOzPR4yUkpRd081bRp7zkTg+jUQCH9Q8FeJjnNdVrmImmPx/QfTKXuqAVOXa2ZeTO5tAe29hWq1bpeS8lKdLs2cH2v3Zfn5kVjpYr0t1VXY4djNaaZ+OumWpGh9j2vaVi6pp+NVpep4+ouxQXY9ZzMnKybbGy8rVbNsHENdKMdiot2Raa0pbtjud/pac5RlK6a4PJJaJasivD4inCcIdmSle11m3JttyeStn/RJ/sG8A6no2LgaTaultiY+MwuuxmzUyDlFue4rek1XGxmd3yWspLvuwoTnskevONSTkr58bafm7dxJuDpVaNONOXZsln2b6+evjv4I6jVejTRLMp9TqTLw8xrRkV24eVZT7vkcuZtorKvUjM25KMj1+Z2RdzOxYuoo9l2a5rVcOJGnsnDubqxTjLVOMmrPilnG/k1yJxrXYAbkkADkdtyf5OwA3Pr5AD+APSQi5K7e1zod0nVrnzanu07KtZnuOMK3x7rWO7WPjuNlsY7sWoenmzMzB2YtLCljZ012XmuevUoMVsWhXk5puEnra1m+Nnl0tffmeY8Df8dum49iXZmZkZ4Q79gImJjv/AALQj23Mv/qt6BvRuQJU9lTaE5K0Vb+X9iNQ2BRg71JOfKyUemb/AJ/gtXhYSVIlNaLXVWqpXWiqqIigBURVACqoAAUAAASrbvmzTpJKy0PtByIBx9R1KuiuzItsSqmpGsttsZUrrrUFnd3YhVVVBJYkAATlJt2R8ykopyk7JZtvRJbzF31T9QR8R5gNPNdMxOSYaMGQ2kkdzLsrOxVruICo45V1AbhGsuQaXC4f0Mc/eev2PONqY7vVT2fcjpzfxfbl4kLSYUogCAIAgCAIBNvTz1VZvh0+7FTl6Wz8mxGfi1DE72WYdhBFZYkuaGHasfc/os9lrQ8RhY1s9JcePj9/7LrAbUnhPYt2ocN68Pto+W+/fsv6ktG1oKuNmVrkEbnDyCKMtTsOQFTkd0LuB3KGtr39HMoquHqU/eWXFaG4wu0KGJX6cs+DykvJ6+KuuZJxEjFiaQBAEAQBAEAQBANQIBGHtR6ktG0UMuTmVtkAbjDxyt+Wx2PEGpG/SDcSO5kNTXv6uJJpYepV91ZcXoV2K2hQwy/UlnwWcn5bvF2XMoL1DdVWb4iPuwU4mlq/JcRX5NewO9dmZYABYVIDilR2q32P6rJXat7h8LGjnrLjw8Pv/Rh8ftSpi/Yt2YcL5vx+2i5kJSYUogCAIAgCAIAgCAbLqFYcWAZT6hgCD/R8pyOZ6HT/AGg6lQorp1PU6EXyVMfUdSoUD9gFpykAA/gCdUqUJaxXREuli69JWhUkv9n9Tl/FvWfreufetb/PnX3el8C6Hf6yxXzX1Hxb1n63rn3rW/z47vS+BdB6yxXzX1Hxb1n63rn3rW/z47vS+BdB6yxXzX1Hxb1n63rn3rW/z47vS+BdB6yxXzX1Hxb1n63rn3rW/wA+O70vgXQessV819R8W9Z+t65961v8+O70vgXQessV819R8W9Z+t65961v8+O70vgXQessV819R8W9Z+t65961v8+O70vgXQessV819Tiah7QdRvU13anqd6N5MmRqOpXqR+4K3ZTgg/wROyNKEdIrojoqYuvVVp1JP/Z/TU89TQqjioCgegAAA/oeU7SJzN84AgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgCAIAgH/9k=",
267
+ },
268
+ },
269
+ { type: "text", text: "What is this a logo for?" },
270
+ ],
271
+ }),
272
+ ]);
273
+ console.log(res);
274
+ });
@@ -0,0 +1 @@
1
+ module.exports = require('./dist/experimental/index.cjs');
@@ -0,0 +1 @@
1
+ export * from './dist/experimental/index.js'
@@ -0,0 +1 @@
1
+ export * from './dist/experimental/index.js'
@@ -0,0 +1 @@
1
+ export * from './dist/experimental/index.js'
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@langchain/anthropic",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Anthropic integrations for LangChain.js",
5
5
  "type": "module",
6
6
  "engines": {
@@ -39,10 +39,14 @@
39
39
  "license": "MIT",
40
40
  "dependencies": {
41
41
  "@anthropic-ai/sdk": "^0.15.0",
42
- "@langchain/core": "~0.1"
42
+ "@langchain/core": "~0.1",
43
+ "fast-xml-parser": "^4.3.5",
44
+ "zod": "^3.22.4",
45
+ "zod-to-json-schema": "^3.22.4"
43
46
  },
44
47
  "devDependencies": {
45
48
  "@jest/globals": "^29.5.0",
49
+ "@langchain/community": "workspace:^",
46
50
  "@langchain/scripts": "~0.0",
47
51
  "@swc/core": "^1.3.90",
48
52
  "@swc/jest": "^0.2.29",
@@ -88,6 +92,15 @@
88
92
  "import": "./index.js",
89
93
  "require": "./index.cjs"
90
94
  },
95
+ "./experimental": {
96
+ "types": {
97
+ "import": "./experimental.d.ts",
98
+ "require": "./experimental.d.cts",
99
+ "default": "./experimental.d.ts"
100
+ },
101
+ "import": "./experimental.js",
102
+ "require": "./experimental.cjs"
103
+ },
91
104
  "./package.json": "./package.json"
92
105
  },
93
106
  "files": [
@@ -95,6 +108,10 @@
95
108
  "index.cjs",
96
109
  "index.js",
97
110
  "index.d.ts",
98
- "index.d.cts"
111
+ "index.d.cts",
112
+ "experimental.cjs",
113
+ "experimental.js",
114
+ "experimental.d.ts",
115
+ "experimental.d.cts"
99
116
  ]
100
117
  }