@aigne/anthropic 0.7.2 → 0.8.1
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/CHANGELOG.md +33 -0
- package/README.md +0 -2
- package/lib/cjs/anthropic-chat-model.d.ts +2 -0
- package/lib/cjs/anthropic-chat-model.js +57 -15
- package/lib/dts/anthropic-chat-model.d.ts +2 -0
- package/lib/esm/anthropic-chat-model.d.ts +2 -0
- package/lib/esm/anthropic-chat-model.js +57 -15
- package/package.json +8 -6
- package/README.zh.md +0 -116
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,38 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.8.1](https://github.com/AIGNE-io/aigne-framework/compare/anthropic-v0.8.0...anthropic-v0.8.1) (2025-07-14)
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
### Bug Fixes
|
|
7
|
+
|
|
8
|
+
* **cli:** print pretty error message for cli ([#249](https://github.com/AIGNE-io/aigne-framework/issues/249)) ([d68e0f7](https://github.com/AIGNE-io/aigne-framework/commit/d68e0f7151259a05696de77d9f00793b6f5b36b2))
|
|
9
|
+
* **deps:** update deps to latest version ([#247](https://github.com/AIGNE-io/aigne-framework/issues/247)) ([3972f88](https://github.com/AIGNE-io/aigne-framework/commit/3972f887a9abff20c26da6b51c1071cbd54c0bf1))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
### Dependencies
|
|
13
|
+
|
|
14
|
+
* The following workspace dependencies were updated
|
|
15
|
+
* dependencies
|
|
16
|
+
* @aigne/core bumped to 1.33.1
|
|
17
|
+
* devDependencies
|
|
18
|
+
* @aigne/test-utils bumped to 0.5.6
|
|
19
|
+
|
|
20
|
+
## [0.8.0](https://github.com/AIGNE-io/aigne-framework/compare/anthropic-v0.7.2...anthropic-v0.8.0) (2025-07-10)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
|
|
25
|
+
* **model:** reduce unnecessary LLM requests for structured output ([#241](https://github.com/AIGNE-io/aigne-framework/issues/241)) ([e28813c](https://github.com/AIGNE-io/aigne-framework/commit/e28813c021ed35c0251e198e2e007e2d746ab3d8))
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
### Dependencies
|
|
29
|
+
|
|
30
|
+
* The following workspace dependencies were updated
|
|
31
|
+
* dependencies
|
|
32
|
+
* @aigne/core bumped to 1.33.0
|
|
33
|
+
* devDependencies
|
|
34
|
+
* @aigne/test-utils bumped to 0.5.5
|
|
35
|
+
|
|
3
36
|
## [0.7.2](https://github.com/AIGNE-io/aigne-framework/compare/anthropic-v0.7.1...anthropic-v0.7.2) (2025-07-09)
|
|
4
37
|
|
|
5
38
|
|
package/README.md
CHANGED
|
@@ -6,8 +6,6 @@
|
|
|
6
6
|
[](https://www.npmjs.com/package/@aigne/anthropic)
|
|
7
7
|
[](https://github.com/AIGNE-io/aigne-framework/blob/main/LICENSE.md)
|
|
8
8
|
|
|
9
|
-
**English** | [中文](README.zh.md)
|
|
10
|
-
|
|
11
9
|
AIGNE Anthropic SDK for integrating with Claude AI models within the [AIGNE Framework](https://github.com/AIGNE-io/aigne-framework).
|
|
12
10
|
|
|
13
11
|
## Introduction
|
|
@@ -105,12 +105,14 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
105
105
|
protected _client?: Anthropic;
|
|
106
106
|
get client(): Anthropic;
|
|
107
107
|
get modelOptions(): ChatModelOptions | undefined;
|
|
108
|
+
private getMaxTokens;
|
|
108
109
|
/**
|
|
109
110
|
* Process the input using Claude's chat model
|
|
110
111
|
* @param input - The input to process
|
|
111
112
|
* @returns The processed output from the model
|
|
112
113
|
*/
|
|
113
114
|
process(input: ChatModelInput): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
|
|
115
|
+
private ajv;
|
|
114
116
|
private _process;
|
|
115
117
|
private extractResultFromAnthropicStream;
|
|
116
118
|
private requestStructuredOutput;
|
|
@@ -6,10 +6,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.AnthropicChatModel = exports.claudeChatModelOptionsSchema = void 0;
|
|
7
7
|
const core_1 = require("@aigne/core");
|
|
8
8
|
const json_schema_js_1 = require("@aigne/core/utils/json-schema.js");
|
|
9
|
+
const logger_js_1 = require("@aigne/core/utils/logger.js");
|
|
9
10
|
const model_utils_js_1 = require("@aigne/core/utils/model-utils.js");
|
|
10
11
|
const stream_utils_js_1 = require("@aigne/core/utils/stream-utils.js");
|
|
11
12
|
const type_utils_js_1 = require("@aigne/core/utils/type-utils.js");
|
|
12
13
|
const sdk_1 = __importDefault(require("@anthropic-ai/sdk"));
|
|
14
|
+
const ajv_1 = require("ajv");
|
|
15
|
+
const jaison_1 = __importDefault(require("jaison"));
|
|
13
16
|
const zod_1 = require("zod");
|
|
14
17
|
const CHAT_MODEL_CLAUDE_DEFAULT_MODEL = "claude-3-7-sonnet-latest";
|
|
15
18
|
/**
|
|
@@ -62,16 +65,32 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
62
65
|
get client() {
|
|
63
66
|
const apiKey = this.options?.apiKey || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_API_KEY;
|
|
64
67
|
if (!apiKey)
|
|
65
|
-
throw new Error("
|
|
68
|
+
throw new Error("AnthropicChatModel requires an API key. Please provide it via `options.apiKey`, or set the `ANTHROPIC_API_KEY` or `CLAUDE_API_KEY` environment variable");
|
|
66
69
|
this._client ??= new sdk_1.default({
|
|
67
70
|
apiKey,
|
|
68
71
|
...this.options?.clientOptions,
|
|
72
|
+
timeout: this.options?.clientOptions?.timeout ?? 600e3,
|
|
69
73
|
});
|
|
70
74
|
return this._client;
|
|
71
75
|
}
|
|
72
76
|
get modelOptions() {
|
|
73
77
|
return this.options?.modelOptions;
|
|
74
78
|
}
|
|
79
|
+
getMaxTokens(model) {
|
|
80
|
+
const matchers = [
|
|
81
|
+
[/claude-opus-4-/, 32000],
|
|
82
|
+
[/claude-sonnet-4-/, 64000],
|
|
83
|
+
[/claude-3-7-sonnet-/, 64000],
|
|
84
|
+
[/claude-3-5-sonnet-/, 8192],
|
|
85
|
+
[/claude-3-5-haiku-/, 8192],
|
|
86
|
+
];
|
|
87
|
+
for (const [regex, maxTokens] of matchers) {
|
|
88
|
+
if (regex.test(model)) {
|
|
89
|
+
return maxTokens;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return 4096;
|
|
93
|
+
}
|
|
75
94
|
/**
|
|
76
95
|
* Process the input using Claude's chat model
|
|
77
96
|
* @param input - The input to process
|
|
@@ -80,6 +99,7 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
80
99
|
process(input) {
|
|
81
100
|
return this._process(input);
|
|
82
101
|
}
|
|
102
|
+
ajv = new ajv_1.Ajv();
|
|
83
103
|
async _process(input) {
|
|
84
104
|
const model = this.options?.model || CHAT_MODEL_CLAUDE_DEFAULT_MODEL;
|
|
85
105
|
const disableParallelToolUse = input.modelOptions?.parallelToolCalls === false ||
|
|
@@ -89,10 +109,15 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
89
109
|
temperature: input.modelOptions?.temperature ?? this.modelOptions?.temperature,
|
|
90
110
|
top_p: input.modelOptions?.topP ?? this.modelOptions?.topP,
|
|
91
111
|
// TODO: make dynamic based on model https://docs.anthropic.com/en/docs/about-claude/models/all-models
|
|
92
|
-
max_tokens:
|
|
112
|
+
max_tokens: this.getMaxTokens(model),
|
|
93
113
|
...convertMessages(input),
|
|
94
114
|
...convertTools({ ...input, disableParallelToolUse }),
|
|
95
115
|
};
|
|
116
|
+
// Claude does not support json_schema response and tool calls in the same request,
|
|
117
|
+
// so we need to handle the case where tools are not used and responseFormat is json
|
|
118
|
+
if (!input.tools?.length && input.responseFormat?.type === "json_schema") {
|
|
119
|
+
return this.requestStructuredOutput(body, input.responseFormat);
|
|
120
|
+
}
|
|
96
121
|
const stream = this.client.messages.stream({
|
|
97
122
|
...body,
|
|
98
123
|
stream: true,
|
|
@@ -101,20 +126,26 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
101
126
|
return this.extractResultFromAnthropicStream(stream, true);
|
|
102
127
|
}
|
|
103
128
|
const result = await this.extractResultFromAnthropicStream(stream);
|
|
129
|
+
// Just return the result if it has tool calls
|
|
130
|
+
if (result.toolCalls?.length)
|
|
131
|
+
return result;
|
|
132
|
+
// Try to parse the text response as JSON
|
|
133
|
+
// If it matches the json_schema, return it as json
|
|
134
|
+
const json = safeParseJSON(result.text || "");
|
|
135
|
+
if (this.ajv.validate(input.responseFormat.jsonSchema.schema, json)) {
|
|
136
|
+
return { ...result, json, text: undefined };
|
|
137
|
+
}
|
|
138
|
+
logger_js_1.logger.warn(`AnthropicChatModel: Text response does not match JSON schema, trying to use tool to extract json `, { text: result.text });
|
|
104
139
|
// Claude doesn't support json_schema response and tool calls in the same request,
|
|
105
140
|
// so we need to make a separate request for json_schema response when the tool calls is empty
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
return result;
|
|
141
|
+
const output = await this.requestStructuredOutput(body, input.responseFormat);
|
|
142
|
+
return {
|
|
143
|
+
...output,
|
|
144
|
+
// merge usage from both requests
|
|
145
|
+
usage: (0, model_utils_js_1.mergeUsage)(result.usage, output.usage),
|
|
146
|
+
};
|
|
115
147
|
}
|
|
116
148
|
async extractResultFromAnthropicStream(stream, streaming) {
|
|
117
|
-
const logs = [];
|
|
118
149
|
const result = new ReadableStream({
|
|
119
150
|
async start(controller) {
|
|
120
151
|
try {
|
|
@@ -136,7 +167,6 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
136
167
|
if (chunk.type === "message_delta" && usage) {
|
|
137
168
|
usage.outputTokens = chunk.usage.output_tokens;
|
|
138
169
|
}
|
|
139
|
-
logs.push(JSON.stringify(chunk));
|
|
140
170
|
// handle streaming text
|
|
141
171
|
if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
|
|
142
172
|
controller.enqueue({
|
|
@@ -223,7 +253,7 @@ class AnthropicChatModel extends core_1.ChatModel {
|
|
|
223
253
|
}
|
|
224
254
|
}
|
|
225
255
|
exports.AnthropicChatModel = AnthropicChatModel;
|
|
226
|
-
function convertMessages({ messages, responseFormat }) {
|
|
256
|
+
function convertMessages({ messages, responseFormat, tools }) {
|
|
227
257
|
const systemMessages = [];
|
|
228
258
|
const msgs = [];
|
|
229
259
|
for (const msg of messages) {
|
|
@@ -273,7 +303,9 @@ function convertMessages({ messages, responseFormat }) {
|
|
|
273
303
|
}
|
|
274
304
|
}
|
|
275
305
|
}
|
|
276
|
-
|
|
306
|
+
// If there are tools and responseFormat is json_schema, we need to add a system message
|
|
307
|
+
// to inform the model about the expected json schema, then trying to parse the response as json
|
|
308
|
+
if (tools?.length && responseFormat?.type === "json_schema") {
|
|
277
309
|
systemMessages.push(`You should provide a json response with schema: ${JSON.stringify(responseFormat.jsonSchema.schema)}`);
|
|
278
310
|
}
|
|
279
311
|
const system = systemMessages.join("\n").trim() || undefined;
|
|
@@ -329,3 +361,13 @@ function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
|
329
361
|
tool_choice: choice,
|
|
330
362
|
};
|
|
331
363
|
}
|
|
364
|
+
function safeParseJSON(text) {
|
|
365
|
+
if (!text)
|
|
366
|
+
return null;
|
|
367
|
+
try {
|
|
368
|
+
return (0, jaison_1.default)(text);
|
|
369
|
+
}
|
|
370
|
+
catch {
|
|
371
|
+
return null;
|
|
372
|
+
}
|
|
373
|
+
}
|
|
@@ -105,12 +105,14 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
105
105
|
protected _client?: Anthropic;
|
|
106
106
|
get client(): Anthropic;
|
|
107
107
|
get modelOptions(): ChatModelOptions | undefined;
|
|
108
|
+
private getMaxTokens;
|
|
108
109
|
/**
|
|
109
110
|
* Process the input using Claude's chat model
|
|
110
111
|
* @param input - The input to process
|
|
111
112
|
* @returns The processed output from the model
|
|
112
113
|
*/
|
|
113
114
|
process(input: ChatModelInput): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
|
|
115
|
+
private ajv;
|
|
114
116
|
private _process;
|
|
115
117
|
private extractResultFromAnthropicStream;
|
|
116
118
|
private requestStructuredOutput;
|
|
@@ -105,12 +105,14 @@ export declare class AnthropicChatModel extends ChatModel {
|
|
|
105
105
|
protected _client?: Anthropic;
|
|
106
106
|
get client(): Anthropic;
|
|
107
107
|
get modelOptions(): ChatModelOptions | undefined;
|
|
108
|
+
private getMaxTokens;
|
|
108
109
|
/**
|
|
109
110
|
* Process the input using Claude's chat model
|
|
110
111
|
* @param input - The input to process
|
|
111
112
|
* @returns The processed output from the model
|
|
112
113
|
*/
|
|
113
114
|
process(input: ChatModelInput): PromiseOrValue<AgentProcessResult<ChatModelOutput>>;
|
|
115
|
+
private ajv;
|
|
114
116
|
private _process;
|
|
115
117
|
private extractResultFromAnthropicStream;
|
|
116
118
|
private requestStructuredOutput;
|
|
@@ -1,9 +1,12 @@
|
|
|
1
1
|
import { ChatModel, } from "@aigne/core";
|
|
2
2
|
import { parseJSON } from "@aigne/core/utils/json-schema.js";
|
|
3
|
+
import { logger } from "@aigne/core/utils/logger.js";
|
|
3
4
|
import { mergeUsage } from "@aigne/core/utils/model-utils.js";
|
|
4
5
|
import { agentResponseStreamToObject } from "@aigne/core/utils/stream-utils.js";
|
|
5
6
|
import { checkArguments, isEmpty, isNonNullable, } from "@aigne/core/utils/type-utils.js";
|
|
6
7
|
import Anthropic from "@anthropic-ai/sdk";
|
|
8
|
+
import { Ajv } from "ajv";
|
|
9
|
+
import jaison from "jaison";
|
|
7
10
|
import { z } from "zod";
|
|
8
11
|
const CHAT_MODEL_CLAUDE_DEFAULT_MODEL = "claude-3-7-sonnet-latest";
|
|
9
12
|
/**
|
|
@@ -56,16 +59,32 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
56
59
|
get client() {
|
|
57
60
|
const apiKey = this.options?.apiKey || process.env.ANTHROPIC_API_KEY || process.env.CLAUDE_API_KEY;
|
|
58
61
|
if (!apiKey)
|
|
59
|
-
throw new Error("
|
|
62
|
+
throw new Error("AnthropicChatModel requires an API key. Please provide it via `options.apiKey`, or set the `ANTHROPIC_API_KEY` or `CLAUDE_API_KEY` environment variable");
|
|
60
63
|
this._client ??= new Anthropic({
|
|
61
64
|
apiKey,
|
|
62
65
|
...this.options?.clientOptions,
|
|
66
|
+
timeout: this.options?.clientOptions?.timeout ?? 600e3,
|
|
63
67
|
});
|
|
64
68
|
return this._client;
|
|
65
69
|
}
|
|
66
70
|
get modelOptions() {
|
|
67
71
|
return this.options?.modelOptions;
|
|
68
72
|
}
|
|
73
|
+
getMaxTokens(model) {
|
|
74
|
+
const matchers = [
|
|
75
|
+
[/claude-opus-4-/, 32000],
|
|
76
|
+
[/claude-sonnet-4-/, 64000],
|
|
77
|
+
[/claude-3-7-sonnet-/, 64000],
|
|
78
|
+
[/claude-3-5-sonnet-/, 8192],
|
|
79
|
+
[/claude-3-5-haiku-/, 8192],
|
|
80
|
+
];
|
|
81
|
+
for (const [regex, maxTokens] of matchers) {
|
|
82
|
+
if (regex.test(model)) {
|
|
83
|
+
return maxTokens;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
return 4096;
|
|
87
|
+
}
|
|
69
88
|
/**
|
|
70
89
|
* Process the input using Claude's chat model
|
|
71
90
|
* @param input - The input to process
|
|
@@ -74,6 +93,7 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
74
93
|
process(input) {
|
|
75
94
|
return this._process(input);
|
|
76
95
|
}
|
|
96
|
+
ajv = new Ajv();
|
|
77
97
|
async _process(input) {
|
|
78
98
|
const model = this.options?.model || CHAT_MODEL_CLAUDE_DEFAULT_MODEL;
|
|
79
99
|
const disableParallelToolUse = input.modelOptions?.parallelToolCalls === false ||
|
|
@@ -83,10 +103,15 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
83
103
|
temperature: input.modelOptions?.temperature ?? this.modelOptions?.temperature,
|
|
84
104
|
top_p: input.modelOptions?.topP ?? this.modelOptions?.topP,
|
|
85
105
|
// TODO: make dynamic based on model https://docs.anthropic.com/en/docs/about-claude/models/all-models
|
|
86
|
-
max_tokens:
|
|
106
|
+
max_tokens: this.getMaxTokens(model),
|
|
87
107
|
...convertMessages(input),
|
|
88
108
|
...convertTools({ ...input, disableParallelToolUse }),
|
|
89
109
|
};
|
|
110
|
+
// Claude does not support json_schema response and tool calls in the same request,
|
|
111
|
+
// so we need to handle the case where tools are not used and responseFormat is json
|
|
112
|
+
if (!input.tools?.length && input.responseFormat?.type === "json_schema") {
|
|
113
|
+
return this.requestStructuredOutput(body, input.responseFormat);
|
|
114
|
+
}
|
|
90
115
|
const stream = this.client.messages.stream({
|
|
91
116
|
...body,
|
|
92
117
|
stream: true,
|
|
@@ -95,20 +120,26 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
95
120
|
return this.extractResultFromAnthropicStream(stream, true);
|
|
96
121
|
}
|
|
97
122
|
const result = await this.extractResultFromAnthropicStream(stream);
|
|
123
|
+
// Just return the result if it has tool calls
|
|
124
|
+
if (result.toolCalls?.length)
|
|
125
|
+
return result;
|
|
126
|
+
// Try to parse the text response as JSON
|
|
127
|
+
// If it matches the json_schema, return it as json
|
|
128
|
+
const json = safeParseJSON(result.text || "");
|
|
129
|
+
if (this.ajv.validate(input.responseFormat.jsonSchema.schema, json)) {
|
|
130
|
+
return { ...result, json, text: undefined };
|
|
131
|
+
}
|
|
132
|
+
logger.warn(`AnthropicChatModel: Text response does not match JSON schema, trying to use tool to extract json `, { text: result.text });
|
|
98
133
|
// Claude doesn't support json_schema response and tool calls in the same request,
|
|
99
134
|
// so we need to make a separate request for json_schema response when the tool calls is empty
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
return result;
|
|
135
|
+
const output = await this.requestStructuredOutput(body, input.responseFormat);
|
|
136
|
+
return {
|
|
137
|
+
...output,
|
|
138
|
+
// merge usage from both requests
|
|
139
|
+
usage: mergeUsage(result.usage, output.usage),
|
|
140
|
+
};
|
|
109
141
|
}
|
|
110
142
|
async extractResultFromAnthropicStream(stream, streaming) {
|
|
111
|
-
const logs = [];
|
|
112
143
|
const result = new ReadableStream({
|
|
113
144
|
async start(controller) {
|
|
114
145
|
try {
|
|
@@ -130,7 +161,6 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
130
161
|
if (chunk.type === "message_delta" && usage) {
|
|
131
162
|
usage.outputTokens = chunk.usage.output_tokens;
|
|
132
163
|
}
|
|
133
|
-
logs.push(JSON.stringify(chunk));
|
|
134
164
|
// handle streaming text
|
|
135
165
|
if (chunk.type === "content_block_delta" && chunk.delta.type === "text_delta") {
|
|
136
166
|
controller.enqueue({
|
|
@@ -216,7 +246,7 @@ export class AnthropicChatModel extends ChatModel {
|
|
|
216
246
|
};
|
|
217
247
|
}
|
|
218
248
|
}
|
|
219
|
-
function convertMessages({ messages, responseFormat }) {
|
|
249
|
+
function convertMessages({ messages, responseFormat, tools }) {
|
|
220
250
|
const systemMessages = [];
|
|
221
251
|
const msgs = [];
|
|
222
252
|
for (const msg of messages) {
|
|
@@ -266,7 +296,9 @@ function convertMessages({ messages, responseFormat }) {
|
|
|
266
296
|
}
|
|
267
297
|
}
|
|
268
298
|
}
|
|
269
|
-
|
|
299
|
+
// If there are tools and responseFormat is json_schema, we need to add a system message
|
|
300
|
+
// to inform the model about the expected json schema, then trying to parse the response as json
|
|
301
|
+
if (tools?.length && responseFormat?.type === "json_schema") {
|
|
270
302
|
systemMessages.push(`You should provide a json response with schema: ${JSON.stringify(responseFormat.jsonSchema.schema)}`);
|
|
271
303
|
}
|
|
272
304
|
const system = systemMessages.join("\n").trim() || undefined;
|
|
@@ -322,3 +354,13 @@ function convertTools({ tools, toolChoice, disableParallelToolUse, }) {
|
|
|
322
354
|
tool_choice: choice,
|
|
323
355
|
};
|
|
324
356
|
}
|
|
357
|
+
function safeParseJSON(text) {
|
|
358
|
+
if (!text)
|
|
359
|
+
return null;
|
|
360
|
+
try {
|
|
361
|
+
return jaison(text);
|
|
362
|
+
}
|
|
363
|
+
catch {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@aigne/anthropic",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.1",
|
|
4
4
|
"description": "AIGNE Anthropic SDK for integrating with Claude AI models",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -32,17 +32,19 @@
|
|
|
32
32
|
}
|
|
33
33
|
},
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@anthropic-ai/sdk": "^0.
|
|
35
|
+
"@anthropic-ai/sdk": "^0.56.0",
|
|
36
|
+
"ajv": "^8.17.1",
|
|
37
|
+
"jaison": "^2.0.2",
|
|
36
38
|
"zod": "^3.25.67",
|
|
37
|
-
"@aigne/core": "^1.
|
|
39
|
+
"@aigne/core": "^1.33.1"
|
|
38
40
|
},
|
|
39
41
|
"devDependencies": {
|
|
40
|
-
"@types/bun": "^1.2.
|
|
41
|
-
"@types/node": "^24.0.
|
|
42
|
+
"@types/bun": "^1.2.18",
|
|
43
|
+
"@types/node": "^24.0.12",
|
|
42
44
|
"npm-run-all": "^4.1.5",
|
|
43
45
|
"rimraf": "^6.0.1",
|
|
44
46
|
"typescript": "^5.8.3",
|
|
45
|
-
"@aigne/test-utils": "^0.5.
|
|
47
|
+
"@aigne/test-utils": "^0.5.6"
|
|
46
48
|
},
|
|
47
49
|
"scripts": {
|
|
48
50
|
"lint": "tsc --noEmit",
|
package/README.zh.md
DELETED
|
@@ -1,116 +0,0 @@
|
|
|
1
|
-
# @aigne/anthropic
|
|
2
|
-
|
|
3
|
-
[](https://star-history.com/#AIGNE-io/aigne-framework)
|
|
4
|
-
[](https://github.com/AIGNE-io/aigne-framework/issues)
|
|
5
|
-
[](https://codecov.io/gh/AIGNE-io/aigne-framework)
|
|
6
|
-
[](https://www.npmjs.com/package/@aigne/anthropic)
|
|
7
|
-
[](https://github.com/AIGNE-io/aigne-framework/blob/main/LICENSE.md)
|
|
8
|
-
|
|
9
|
-
[English](README.md) | **中文**
|
|
10
|
-
|
|
11
|
-
AIGNE Anthropic SDK,用于在 [AIGNE 框架](https://github.com/AIGNE-io/aigne-framework) 中集成 Anthropic 的 Claude AI 模型。
|
|
12
|
-
|
|
13
|
-
## 简介
|
|
14
|
-
|
|
15
|
-
`@aigne/anthropic` 提供了 AIGNE 框架与 Anthropic 的 Claude 语言模型和 API 之间的无缝集成。该包使开发者能够在 AIGNE 应用程序中轻松利用 Anthropic 的 Claude 模型,同时提供框架内一致的接口,充分发挥 Claude 先进的 AI 能力。
|
|
16
|
-
|
|
17
|
-
## 特性
|
|
18
|
-
|
|
19
|
-
* **Anthropic API 集成**:使用官方 SDK 直接连接到 Anthropic 的 API 服务
|
|
20
|
-
* **聊天完成**:支持 Claude 的聊天完成 API 和所有可用模型
|
|
21
|
-
* **工具调用**:内置支持 Claude 的工具调用功能
|
|
22
|
-
* **流式响应**:支持流式响应,提供更高响应性的应用程序体验
|
|
23
|
-
* **类型安全**:为所有 API 和模型提供全面的 TypeScript 类型定义
|
|
24
|
-
* **一致接口**:兼容 AIGNE 框架的模型接口
|
|
25
|
-
* **错误处理**:健壮的错误处理和重试机制
|
|
26
|
-
* **完整配置**:丰富的配置选项用于微调行为
|
|
27
|
-
|
|
28
|
-
## 安装
|
|
29
|
-
|
|
30
|
-
### 使用 npm
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install @aigne/anthropic @aigne/core
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
### 使用 yarn
|
|
37
|
-
|
|
38
|
-
```bash
|
|
39
|
-
yarn add @aigne/anthropic @aigne/core
|
|
40
|
-
```
|
|
41
|
-
|
|
42
|
-
### 使用 pnpm
|
|
43
|
-
|
|
44
|
-
```bash
|
|
45
|
-
pnpm add @aigne/anthropic @aigne/core
|
|
46
|
-
```
|
|
47
|
-
|
|
48
|
-
## 基本用法
|
|
49
|
-
|
|
50
|
-
```typescript file="test/anthropic-chat-model.test.ts" region="example-anthropic-chat-model"
|
|
51
|
-
import { AnthropicChatModel } from "@aigne/anthropic";
|
|
52
|
-
|
|
53
|
-
const model = new AnthropicChatModel({
|
|
54
|
-
// Provide API key directly or use environment variable ANTHROPIC_API_KEY or CLAUDE_API_KEY
|
|
55
|
-
apiKey: "your-api-key", // Optional if set in env variables
|
|
56
|
-
// Specify Claude model version (defaults to 'claude-3-7-sonnet-latest')
|
|
57
|
-
model: "claude-3-haiku-20240307",
|
|
58
|
-
// Configure model behavior
|
|
59
|
-
modelOptions: {
|
|
60
|
-
temperature: 0.7,
|
|
61
|
-
},
|
|
62
|
-
});
|
|
63
|
-
|
|
64
|
-
const result = await model.invoke({
|
|
65
|
-
messages: [{ role: "user", content: "Tell me about yourself" }],
|
|
66
|
-
});
|
|
67
|
-
|
|
68
|
-
console.log(result);
|
|
69
|
-
/* Output:
|
|
70
|
-
{
|
|
71
|
-
text: "I'm Claude, an AI assistant created by Anthropic. How can I help you today?",
|
|
72
|
-
model: "claude-3-haiku-20240307",
|
|
73
|
-
usage: {
|
|
74
|
-
inputTokens: 8,
|
|
75
|
-
outputTokens: 15
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
*/
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## 流式响应
|
|
82
|
-
|
|
83
|
-
```typescript file="test/anthropic-chat-model.test.ts" region="example-anthropic-chat-model-streaming-async-generator"
|
|
84
|
-
import { AnthropicChatModel } from "@aigne/anthropic";
|
|
85
|
-
import { isAgentResponseDelta } from "@aigne/core";
|
|
86
|
-
|
|
87
|
-
const model = new AnthropicChatModel({
|
|
88
|
-
apiKey: "your-api-key",
|
|
89
|
-
model: "claude-3-haiku-20240307",
|
|
90
|
-
});
|
|
91
|
-
|
|
92
|
-
const stream = await model.invoke(
|
|
93
|
-
{
|
|
94
|
-
messages: [{ role: "user", content: "Tell me about yourself" }],
|
|
95
|
-
},
|
|
96
|
-
{ streaming: true },
|
|
97
|
-
);
|
|
98
|
-
|
|
99
|
-
let fullText = "";
|
|
100
|
-
const json = {};
|
|
101
|
-
|
|
102
|
-
for await (const chunk of stream) {
|
|
103
|
-
if (isAgentResponseDelta(chunk)) {
|
|
104
|
-
const text = chunk.delta.text?.text;
|
|
105
|
-
if (text) fullText += text;
|
|
106
|
-
if (chunk.delta.json) Object.assign(json, chunk.delta.json);
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
console.log(fullText); // Output: "I'm Claude, an AI assistant created by Anthropic. How can I help you today?"
|
|
111
|
-
console.log(json); // { model: "claude-3-haiku-20240307", usage: { inputTokens: 8, outputTokens: 15 } }
|
|
112
|
-
```
|
|
113
|
-
|
|
114
|
-
## 许可证
|
|
115
|
-
|
|
116
|
-
Elastic-2.0
|