@langchain/anthropic 0.1.13 → 0.1.15
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/dist/chat_models.cjs +216 -130
- package/dist/chat_models.d.ts +8 -15
- package/dist/chat_models.js +216 -131
- package/dist/output_parsers.cjs +14 -7
- package/dist/output_parsers.d.ts +2 -0
- package/dist/output_parsers.js +12 -6
- package/dist/tests/agent.int.test.d.ts +1 -0
- package/dist/tests/agent.int.test.js +39 -0
- package/dist/tests/chat_models-tools.int.test.d.ts +1 -0
- package/dist/tests/chat_models-tools.int.test.js +218 -0
- package/dist/tests/chat_models.int.test.js +0 -178
- package/package.json +2 -2
|
@@ -0,0 +1,218 @@
|
|
|
1
|
+
/* eslint-disable no-process-env */
|
|
2
|
+
import { expect, test } from "@jest/globals";
|
|
3
|
+
import { AIMessage, HumanMessage, ToolMessage } from "@langchain/core/messages";
|
|
4
|
+
import { StructuredTool } from "@langchain/core/tools";
|
|
5
|
+
import { z } from "zod";
|
|
6
|
+
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
7
|
+
import { ChatAnthropic } from "../chat_models.js";
|
|
8
|
+
const zodSchema = z
|
|
9
|
+
.object({
|
|
10
|
+
location: z.string().describe("The name of city to get the weather for."),
|
|
11
|
+
})
|
|
12
|
+
.describe("Get the weather of a specific location and return the temperature in Celsius.");
|
|
13
|
+
class WeatherTool extends StructuredTool {
|
|
14
|
+
constructor() {
|
|
15
|
+
super(...arguments);
|
|
16
|
+
Object.defineProperty(this, "schema", {
|
|
17
|
+
enumerable: true,
|
|
18
|
+
configurable: true,
|
|
19
|
+
writable: true,
|
|
20
|
+
value: z.object({
|
|
21
|
+
location: z.string().describe("The name of city to get the weather for."),
|
|
22
|
+
})
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "description", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: "Get the weather of a specific location and return the temperature in Celsius."
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "name", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: "get_weather"
|
|
35
|
+
});
|
|
36
|
+
}
|
|
37
|
+
async _call(input) {
|
|
38
|
+
console.log(`WeatherTool called with input: ${input}`);
|
|
39
|
+
return `The weather in ${input.location} is 25°C`;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const model = new ChatAnthropic({
|
|
43
|
+
modelName: "claude-3-sonnet-20240229",
|
|
44
|
+
temperature: 0,
|
|
45
|
+
});
|
|
46
|
+
const anthropicTool = {
|
|
47
|
+
name: "get_weather",
|
|
48
|
+
description: "Get the weather of a specific location and return the temperature in Celsius.",
|
|
49
|
+
input_schema: {
|
|
50
|
+
type: "object",
|
|
51
|
+
properties: {
|
|
52
|
+
location: {
|
|
53
|
+
type: "string",
|
|
54
|
+
description: "The name of city to get the weather for.",
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
required: ["location"],
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
test("Few shotting with tool calls", async () => {
|
|
61
|
+
const chat = model.bindTools([new WeatherTool()]);
|
|
62
|
+
const res = await chat.invoke([
|
|
63
|
+
new HumanMessage("What is the weather in SF?"),
|
|
64
|
+
new AIMessage({
|
|
65
|
+
content: "Let me look up the current weather.",
|
|
66
|
+
tool_calls: [
|
|
67
|
+
{
|
|
68
|
+
id: "toolu_feiwjf9u98r389u498",
|
|
69
|
+
name: "get_weather",
|
|
70
|
+
args: {
|
|
71
|
+
location: "SF",
|
|
72
|
+
},
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
}),
|
|
76
|
+
new ToolMessage({
|
|
77
|
+
tool_call_id: "toolu_feiwjf9u98r389u498",
|
|
78
|
+
content: "It is currently 24 degrees with hail in San Francisco.",
|
|
79
|
+
}),
|
|
80
|
+
new AIMessage("It is currently 24 degrees in San Francisco with hail in San Francisco."),
|
|
81
|
+
new HumanMessage("What did you say the weather was?"),
|
|
82
|
+
]);
|
|
83
|
+
console.log(res);
|
|
84
|
+
expect(res.content).toContain("24");
|
|
85
|
+
});
|
|
86
|
+
test("Can bind & invoke StructuredTools", async () => {
|
|
87
|
+
const tools = [new WeatherTool()];
|
|
88
|
+
const modelWithTools = model.bindTools(tools);
|
|
89
|
+
const result = await modelWithTools.invoke("What is the weather in SF today?");
|
|
90
|
+
console.log({
|
|
91
|
+
tool_calls: JSON.stringify(result.content, null, 2),
|
|
92
|
+
}, "Can bind & invoke StructuredTools");
|
|
93
|
+
expect(Array.isArray(result.content)).toBeTruthy();
|
|
94
|
+
if (!Array.isArray(result.content)) {
|
|
95
|
+
throw new Error("Content is not an array");
|
|
96
|
+
}
|
|
97
|
+
let toolCall;
|
|
98
|
+
result.content.forEach((item) => {
|
|
99
|
+
if (item.type === "tool_use") {
|
|
100
|
+
toolCall = item;
|
|
101
|
+
}
|
|
102
|
+
});
|
|
103
|
+
if (!toolCall) {
|
|
104
|
+
throw new Error("No tool call found");
|
|
105
|
+
}
|
|
106
|
+
expect(toolCall).toBeTruthy();
|
|
107
|
+
const { name, input } = toolCall;
|
|
108
|
+
expect(toolCall.input).toEqual(result.tool_calls?.[0].args);
|
|
109
|
+
expect(name).toBe("get_weather");
|
|
110
|
+
expect(input).toBeTruthy();
|
|
111
|
+
expect(input.location).toBeTruthy();
|
|
112
|
+
const result2 = await modelWithTools.invoke([
|
|
113
|
+
new HumanMessage("What is the weather in SF today?"),
|
|
114
|
+
result,
|
|
115
|
+
new ToolMessage({
|
|
116
|
+
tool_call_id: result.tool_calls?.[0].id ?? "",
|
|
117
|
+
content: "The weather in San Francisco is currently 59 degrees and sunny.",
|
|
118
|
+
}),
|
|
119
|
+
new AIMessage("The weather in San Francisco is currently 59 degrees and sunny."),
|
|
120
|
+
new HumanMessage("What did you say the weather was?"),
|
|
121
|
+
]);
|
|
122
|
+
console.log(result2);
|
|
123
|
+
// This should work, but Anthorpic is too skeptical
|
|
124
|
+
expect(result2.content).toContain("59");
|
|
125
|
+
});
|
|
126
|
+
test("Can bind & invoke AnthropicTools", async () => {
|
|
127
|
+
const modelWithTools = model.bind({
|
|
128
|
+
tools: [anthropicTool],
|
|
129
|
+
});
|
|
130
|
+
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
131
|
+
console.log({
|
|
132
|
+
tool_calls: JSON.stringify(result.content, null, 2),
|
|
133
|
+
}, "Can bind & invoke StructuredTools");
|
|
134
|
+
expect(Array.isArray(result.content)).toBeTruthy();
|
|
135
|
+
if (!Array.isArray(result.content)) {
|
|
136
|
+
throw new Error("Content is not an array");
|
|
137
|
+
}
|
|
138
|
+
let toolCall;
|
|
139
|
+
result.content.forEach((item) => {
|
|
140
|
+
if (item.type === "tool_use") {
|
|
141
|
+
toolCall = item;
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
if (!toolCall) {
|
|
145
|
+
throw new Error("No tool call found");
|
|
146
|
+
}
|
|
147
|
+
expect(toolCall).toBeTruthy();
|
|
148
|
+
const { name, input } = toolCall;
|
|
149
|
+
expect(name).toBe("get_weather");
|
|
150
|
+
expect(input).toBeTruthy();
|
|
151
|
+
expect(input.location).toBeTruthy();
|
|
152
|
+
});
|
|
153
|
+
test("Can bind & stream AnthropicTools", async () => {
|
|
154
|
+
const modelWithTools = model.bind({
|
|
155
|
+
tools: [anthropicTool],
|
|
156
|
+
});
|
|
157
|
+
const result = await modelWithTools.stream("What is the weather in London today?");
|
|
158
|
+
let finalMessage;
|
|
159
|
+
for await (const item of result) {
|
|
160
|
+
console.log("item", JSON.stringify(item, null, 2));
|
|
161
|
+
finalMessage = item;
|
|
162
|
+
}
|
|
163
|
+
if (!finalMessage) {
|
|
164
|
+
throw new Error("No final message returned");
|
|
165
|
+
}
|
|
166
|
+
console.log({
|
|
167
|
+
tool_calls: JSON.stringify(finalMessage.content, null, 2),
|
|
168
|
+
}, "Can bind & invoke StructuredTools");
|
|
169
|
+
expect(Array.isArray(finalMessage.content)).toBeTruthy();
|
|
170
|
+
if (!Array.isArray(finalMessage.content)) {
|
|
171
|
+
throw new Error("Content is not an array");
|
|
172
|
+
}
|
|
173
|
+
let toolCall;
|
|
174
|
+
finalMessage.content.forEach((item) => {
|
|
175
|
+
if (item.type === "tool_use") {
|
|
176
|
+
toolCall = item;
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
if (!toolCall) {
|
|
180
|
+
throw new Error("No tool call found");
|
|
181
|
+
}
|
|
182
|
+
expect(toolCall).toBeTruthy();
|
|
183
|
+
const { name, input } = toolCall;
|
|
184
|
+
expect(name).toBe("get_weather");
|
|
185
|
+
expect(input).toBeTruthy();
|
|
186
|
+
expect(input.location).toBeTruthy();
|
|
187
|
+
});
|
|
188
|
+
test("withStructuredOutput with zod schema", async () => {
|
|
189
|
+
const modelWithTools = model.withStructuredOutput(zodSchema, {
|
|
190
|
+
name: "get_weather",
|
|
191
|
+
});
|
|
192
|
+
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
193
|
+
console.log({
|
|
194
|
+
result,
|
|
195
|
+
}, "withStructuredOutput with zod schema");
|
|
196
|
+
expect(typeof result.location).toBe("string");
|
|
197
|
+
});
|
|
198
|
+
test("withStructuredOutput with AnthropicTool", async () => {
|
|
199
|
+
const modelWithTools = model.withStructuredOutput(anthropicTool, {
|
|
200
|
+
name: anthropicTool.name,
|
|
201
|
+
});
|
|
202
|
+
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
203
|
+
console.log({
|
|
204
|
+
result,
|
|
205
|
+
}, "withStructuredOutput with AnthropicTool");
|
|
206
|
+
expect(typeof result.location).toBe("string");
|
|
207
|
+
});
|
|
208
|
+
test("withStructuredOutput JSON Schema only", async () => {
|
|
209
|
+
const jsonSchema = zodToJsonSchema(zodSchema);
|
|
210
|
+
const modelWithTools = model.withStructuredOutput(jsonSchema, {
|
|
211
|
+
name: "get_weather",
|
|
212
|
+
});
|
|
213
|
+
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
214
|
+
console.log({
|
|
215
|
+
result,
|
|
216
|
+
}, "withStructuredOutput JSON Schema only");
|
|
217
|
+
expect(typeof result.location).toBe("string");
|
|
218
|
+
});
|
|
@@ -4,9 +4,6 @@ import { HumanMessage } from "@langchain/core/messages";
|
|
|
4
4
|
import { ChatPromptValue } from "@langchain/core/prompt_values";
|
|
5
5
|
import { PromptTemplate, ChatPromptTemplate, AIMessagePromptTemplate, HumanMessagePromptTemplate, SystemMessagePromptTemplate, } from "@langchain/core/prompts";
|
|
6
6
|
import { CallbackManager } from "@langchain/core/callbacks/manager";
|
|
7
|
-
import { StructuredTool } from "@langchain/core/tools";
|
|
8
|
-
import { z } from "zod";
|
|
9
|
-
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
10
7
|
import { ChatAnthropic } from "../chat_models.js";
|
|
11
8
|
test.skip("Test ChatAnthropic", async () => {
|
|
12
9
|
const chat = new ChatAnthropic({
|
|
@@ -275,178 +272,3 @@ test("Test ChatAnthropic multimodal", async () => {
|
|
|
275
272
|
]);
|
|
276
273
|
console.log(res);
|
|
277
274
|
});
|
|
278
|
-
describe("Tool calling", () => {
|
|
279
|
-
const zodSchema = z
|
|
280
|
-
.object({
|
|
281
|
-
location: z.string().describe("The name of city to get the weather for."),
|
|
282
|
-
})
|
|
283
|
-
.describe("Get the weather of a specific location and return the temperature in Celsius.");
|
|
284
|
-
class WeatherTool extends StructuredTool {
|
|
285
|
-
constructor() {
|
|
286
|
-
super(...arguments);
|
|
287
|
-
Object.defineProperty(this, "schema", {
|
|
288
|
-
enumerable: true,
|
|
289
|
-
configurable: true,
|
|
290
|
-
writable: true,
|
|
291
|
-
value: z.object({
|
|
292
|
-
location: z.string().describe("The name of city to get the weather for."),
|
|
293
|
-
})
|
|
294
|
-
});
|
|
295
|
-
Object.defineProperty(this, "description", {
|
|
296
|
-
enumerable: true,
|
|
297
|
-
configurable: true,
|
|
298
|
-
writable: true,
|
|
299
|
-
value: "Get the weather of a specific location and return the temperature in Celsius."
|
|
300
|
-
});
|
|
301
|
-
Object.defineProperty(this, "name", {
|
|
302
|
-
enumerable: true,
|
|
303
|
-
configurable: true,
|
|
304
|
-
writable: true,
|
|
305
|
-
value: "get_weather"
|
|
306
|
-
});
|
|
307
|
-
}
|
|
308
|
-
async _call(input) {
|
|
309
|
-
console.log(`WeatherTool called with input: ${input}`);
|
|
310
|
-
return `The weather in ${input.location} is 25°C`;
|
|
311
|
-
}
|
|
312
|
-
}
|
|
313
|
-
const model = new ChatAnthropic({
|
|
314
|
-
modelName: "claude-3-sonnet-20240229",
|
|
315
|
-
temperature: 0,
|
|
316
|
-
});
|
|
317
|
-
const anthropicTool = {
|
|
318
|
-
name: "get_weather",
|
|
319
|
-
description: "Get the weather of a specific location and return the temperature in Celsius.",
|
|
320
|
-
input_schema: {
|
|
321
|
-
type: "object",
|
|
322
|
-
properties: {
|
|
323
|
-
location: {
|
|
324
|
-
type: "string",
|
|
325
|
-
description: "The name of city to get the weather for.",
|
|
326
|
-
},
|
|
327
|
-
},
|
|
328
|
-
required: ["location"],
|
|
329
|
-
},
|
|
330
|
-
};
|
|
331
|
-
test("Can bind & invoke StructuredTools", async () => {
|
|
332
|
-
const tools = [new WeatherTool()];
|
|
333
|
-
const modelWithTools = model.bind({
|
|
334
|
-
tools,
|
|
335
|
-
});
|
|
336
|
-
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
337
|
-
console.log({
|
|
338
|
-
tool_calls: JSON.stringify(result.content, null, 2),
|
|
339
|
-
}, "Can bind & invoke StructuredTools");
|
|
340
|
-
expect(Array.isArray(result.content)).toBeTruthy();
|
|
341
|
-
if (!Array.isArray(result.content)) {
|
|
342
|
-
throw new Error("Content is not an array");
|
|
343
|
-
}
|
|
344
|
-
let toolCall;
|
|
345
|
-
result.content.forEach((item) => {
|
|
346
|
-
if (item.type === "tool_use") {
|
|
347
|
-
toolCall = item;
|
|
348
|
-
}
|
|
349
|
-
});
|
|
350
|
-
if (!toolCall) {
|
|
351
|
-
throw new Error("No tool call found");
|
|
352
|
-
}
|
|
353
|
-
expect(toolCall).toBeTruthy();
|
|
354
|
-
const { name, input } = toolCall;
|
|
355
|
-
expect(name).toBe("get_weather");
|
|
356
|
-
expect(input).toBeTruthy();
|
|
357
|
-
expect(input.location).toBeTruthy();
|
|
358
|
-
});
|
|
359
|
-
test("Can bind & invoke AnthropicTools", async () => {
|
|
360
|
-
const modelWithTools = model.bind({
|
|
361
|
-
tools: [anthropicTool],
|
|
362
|
-
});
|
|
363
|
-
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
364
|
-
console.log({
|
|
365
|
-
tool_calls: JSON.stringify(result.content, null, 2),
|
|
366
|
-
}, "Can bind & invoke StructuredTools");
|
|
367
|
-
expect(Array.isArray(result.content)).toBeTruthy();
|
|
368
|
-
if (!Array.isArray(result.content)) {
|
|
369
|
-
throw new Error("Content is not an array");
|
|
370
|
-
}
|
|
371
|
-
let toolCall;
|
|
372
|
-
result.content.forEach((item) => {
|
|
373
|
-
if (item.type === "tool_use") {
|
|
374
|
-
toolCall = item;
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
|
-
if (!toolCall) {
|
|
378
|
-
throw new Error("No tool call found");
|
|
379
|
-
}
|
|
380
|
-
expect(toolCall).toBeTruthy();
|
|
381
|
-
const { name, input } = toolCall;
|
|
382
|
-
expect(name).toBe("get_weather");
|
|
383
|
-
expect(input).toBeTruthy();
|
|
384
|
-
expect(input.location).toBeTruthy();
|
|
385
|
-
});
|
|
386
|
-
test("Can bind & stream AnthropicTools", async () => {
|
|
387
|
-
const modelWithTools = model.bind({
|
|
388
|
-
tools: [anthropicTool],
|
|
389
|
-
});
|
|
390
|
-
const result = await modelWithTools.stream("What is the weather in London today?");
|
|
391
|
-
let finalMessage;
|
|
392
|
-
for await (const item of result) {
|
|
393
|
-
console.log("item", JSON.stringify(item, null, 2));
|
|
394
|
-
finalMessage = item;
|
|
395
|
-
}
|
|
396
|
-
if (!finalMessage) {
|
|
397
|
-
throw new Error("No final message returned");
|
|
398
|
-
}
|
|
399
|
-
console.log({
|
|
400
|
-
tool_calls: JSON.stringify(finalMessage.content, null, 2),
|
|
401
|
-
}, "Can bind & invoke StructuredTools");
|
|
402
|
-
expect(Array.isArray(finalMessage.content)).toBeTruthy();
|
|
403
|
-
if (!Array.isArray(finalMessage.content)) {
|
|
404
|
-
throw new Error("Content is not an array");
|
|
405
|
-
}
|
|
406
|
-
let toolCall;
|
|
407
|
-
finalMessage.content.forEach((item) => {
|
|
408
|
-
if (item.type === "tool_use") {
|
|
409
|
-
toolCall = item;
|
|
410
|
-
}
|
|
411
|
-
});
|
|
412
|
-
if (!toolCall) {
|
|
413
|
-
throw new Error("No tool call found");
|
|
414
|
-
}
|
|
415
|
-
expect(toolCall).toBeTruthy();
|
|
416
|
-
const { name, input } = toolCall;
|
|
417
|
-
expect(name).toBe("get_weather");
|
|
418
|
-
expect(input).toBeTruthy();
|
|
419
|
-
expect(input.location).toBeTruthy();
|
|
420
|
-
});
|
|
421
|
-
test("withStructuredOutput with zod schema", async () => {
|
|
422
|
-
const modelWithTools = model.withStructuredOutput(zodSchema, {
|
|
423
|
-
name: "get_weather",
|
|
424
|
-
});
|
|
425
|
-
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
426
|
-
console.log({
|
|
427
|
-
result,
|
|
428
|
-
}, "withStructuredOutput with zod schema");
|
|
429
|
-
expect(typeof result.location).toBe("string");
|
|
430
|
-
});
|
|
431
|
-
test("withStructuredOutput with AnthropicTool", async () => {
|
|
432
|
-
const modelWithTools = model.withStructuredOutput(anthropicTool, {
|
|
433
|
-
name: anthropicTool.name,
|
|
434
|
-
});
|
|
435
|
-
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
436
|
-
console.log({
|
|
437
|
-
result,
|
|
438
|
-
}, "withStructuredOutput with AnthropicTool");
|
|
439
|
-
expect(typeof result.location).toBe("string");
|
|
440
|
-
});
|
|
441
|
-
test("withStructuredOutput JSON Schema only", async () => {
|
|
442
|
-
const jsonSchema = zodToJsonSchema(zodSchema);
|
|
443
|
-
const modelWithTools = model.withStructuredOutput(jsonSchema, {
|
|
444
|
-
name: "get_weather",
|
|
445
|
-
});
|
|
446
|
-
const result = await modelWithTools.invoke("What is the weather in London today?");
|
|
447
|
-
console.log({
|
|
448
|
-
result,
|
|
449
|
-
}, "withStructuredOutput JSON Schema only");
|
|
450
|
-
expect(typeof result.location).toBe("string");
|
|
451
|
-
});
|
|
452
|
-
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@langchain/anthropic",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.15",
|
|
4
4
|
"description": "Anthropic integrations for LangChain.js",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"engines": {
|
|
@@ -40,7 +40,7 @@
|
|
|
40
40
|
"license": "MIT",
|
|
41
41
|
"dependencies": {
|
|
42
42
|
"@anthropic-ai/sdk": "^0.20.1",
|
|
43
|
-
"@langchain/core": "~0.1.
|
|
43
|
+
"@langchain/core": "~0.1.56",
|
|
44
44
|
"fast-xml-parser": "^4.3.5",
|
|
45
45
|
"zod": "^3.22.4",
|
|
46
46
|
"zod-to-json-schema": "^3.22.4"
|