UNPKG

aisapi

Version:

A JavaScript/TypeScript API library for multiple AI providers

480 lines 19.5 kB
"use strict"; var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } return new (P || (P = Promise))(function (resolve, reject) { function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } step((generator = generator.apply(thisArg, _arguments || [])).next()); }); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.AnthropicProvider = void 0; const base_1 = require("./base"); /** * Anthropic Claude API实现 * 支持文本生成、多模态输入、工具调用等 */ class AnthropicProvider extends base_1.BaseProvider { /** * 创建Anthropic提供商实例 */ constructor(options = {}) { super(options); this.name = 'Anthropic'; this.model = options.model || 'claude-3-7-sonnet-20250219'; this.anthropicVersion = options.anthropicVersion || '2024-06-23'; this.maxRetries = options.maxRetries || 3; } /** * @inheritdoc */ getDefaultBaseUrl() { return 'https://api.anthropic.com/v1'; } /** * @inheritdoc */ validateApiKey() { super.validateApiKey(); if (this.apiKey && !this.apiKey.startsWith('sk-ant-')) { console.warn(`[${this.name}] 警告: API密钥格式可能不正确,应以 'sk-ant-' 开头`); } } /** * @inheritdoc */ generateText(params) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const model = params.model || this.model; // 构建消息格式 const messages = []; // 添加用户消息 messages.push({ role: 'user', content: params.prompt }); // 构建请求体 const requestBody = { model, messages, max_tokens: params.maxTokens || 1000, temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7, stream: params.stream || false }; // 添加系统消息(如果有) if (params.systemMessage) { requestBody.system = params.systemMessage; } // 添加top_p(如果指定) if (params.topP !== undefined) { requestBody.top_p = params.topP; } // 发送请求并获取响应 const data = yield this.sendClaudeRequest('/messages', requestBody); return { text: this.extractTextFromContent(data.content), usage: { promptTokens: ((_b = data.usage) === null || _b === void 0 ? void 0 : _b.input_tokens) || 0, completionTokens: ((_c = data.usage) === null || _c === void 0 ? void 0 : _c.output_tokens) || 0, totalTokens: (((_d = data.usage) === null || _d === void 0 ? void 0 : _d.input_tokens) || 0) + (((_e = data.usage) === null || _e === void 0 ? void 0 : _e.output_tokens) || 0) }, rawResponse: data }; }); } /** * 支持多模态输入的Claude对话 */ chatCompletion(params) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const model = params.model || this.model; // 将ChatMessage[]转换为Claude消息格式 const claudeMessages = this.convertToCloudeMessages(params.messages); // 构建请求体 const requestBody = { model, messages: claudeMessages, max_tokens: params.maxTokens || 1000, temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7, stream: params.stream || false }; // 添加系统消息 if (params.systemMessage) { requestBody.system = params.systemMessage; } // 添加topP if (params.topP !== undefined) { requestBody.top_p = params.topP; } // 添加工具定义 if (params.tools && params.tools.length > 0) { requestBody.tools = params.tools; } // 发送请求并获取响应 const data = yield this.sendClaudeRequest('/messages', requestBody); return { text: this.extractTextFromContent(data.content), usage: { promptTokens: ((_b = data.usage) === null || _b === void 0 ? void 0 : _b.input_tokens) || 0, completionTokens: ((_c = data.usage) === null || _c === void 0 ? void 0 : _c.output_tokens) || 0, totalTokens: (((_d = data.usage) === null || _d === void 0 ? void 0 : _d.input_tokens) || 0) + (((_e = data.usage) === null || _e === void 0 ? void 0 : _e.output_tokens) || 0) }, rawResponse: data }; }); } /** * 创建流式输出的聊天会话 */ createStreamingChatCompletion(params) { return __awaiter(this, void 0, void 0, function* () { var _a; const model = params.model || this.model; // 将ChatMessage[]转换为Claude消息格式 const claudeMessages = this.convertToCloudeMessages(params.messages); // 构建请求体 const requestBody = { model, messages: claudeMessages, max_tokens: params.maxTokens || 1000, temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7, stream: true }; // 添加系统消息 if (params.systemMessage) { requestBody.system = params.systemMessage; } // 添加topP if (params.topP !== undefined) { requestBody.top_p = params.topP; } // 添加工具定义 if (params.tools && params.tools.length > 0) { requestBody.tools = params.tools; } // 获取流式响应 return this.sendClaudeStreamRequest('/messages', requestBody); }); } /** * 生成JSON格式响应 */ generateJSON(params) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const model = params.model || this.model; // 构建消息 const messages = [{ role: 'user', content: params.prompt }]; // 添加JSON格式要求 const systemMessage = (params.systemMessage || '') + '\n请以有效的JSON格式返回响应,不要包含额外的文本说明。'; // 构建请求体 const requestBody = { model, messages, system: systemMessage, max_tokens: params.maxTokens || 1000, temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7 }; // 添加topP(如果指定) if (params.topP !== undefined) { requestBody.top_p = params.topP; } // 发送请求并获取响应 const data = yield this.sendClaudeRequest('/messages', requestBody); // 提取JSON文本 const jsonText = this.extractTextFromContent(data.content); try { // 解析JSON const jsonData = JSON.parse(jsonText); return { data: jsonData, usage: { promptTokens: ((_b = data.usage) === null || _b === void 0 ? void 0 : _b.input_tokens) || 0, completionTokens: ((_c = data.usage) === null || _c === void 0 ? void 0 : _c.output_tokens) || 0, totalTokens: (((_d = data.usage) === null || _d === void 0 ? void 0 : _d.input_tokens) || 0) + (((_e = data.usage) === null || _e === void 0 ? void 0 : _e.output_tokens) || 0) } }; } catch (error) { throw new Error(`[${this.name}] 解析JSON响应失败: ${error.message}`); } }); } /** * 计算消息的token数量 */ countTokens(messages, systemMessage) { return __awaiter(this, void 0, void 0, function* () { const claudeMessages = this.convertToCloudeMessages(messages); const requestBody = { model: this.model, messages: claudeMessages }; if (systemMessage) { requestBody.system = systemMessage; } const data = yield this.sendClaudeRequest('/messages/count_tokens', requestBody); return { input_tokens: data.input_tokens }; }); } /** * 发送Claude API请求 */ sendClaudeRequest(endpoint, body) { return __awaiter(this, void 0, void 0, function* () { const headers = { 'Content-Type': 'application/json', 'x-api-key': this.apiKey || '', 'anthropic-version': this.anthropicVersion }; let retries = 0; while (retries <= this.maxRetries) { try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); const response = yield fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers, body: JSON.stringify(body), signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { const errorData = yield response.json().catch(() => ({})); throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`); } return yield response.json(); } catch (error) { retries++; if (retries > this.maxRetries) { if (error instanceof Error) { throw new Error(`[${this.name}] ${error.message}`); } throw error; } // 指数退避重试 const delay = Math.min(1000 * Math.pow(2, retries), 10000); yield new Promise(resolve => setTimeout(resolve, delay)); } } throw new Error(`[${this.name}] 达到最大重试次数`); }); } /** * 发送Claude流式API请求 */ sendClaudeStreamRequest(endpoint, body) { return __awaiter(this, void 0, void 0, function* () { const headers = { 'Content-Type': 'application/json', 'x-api-key': this.apiKey || '', 'anthropic-version': this.anthropicVersion, 'Accept': 'text/event-stream' }; try { const controller = new AbortController(); const timeoutId = setTimeout(() => controller.abort(), this.timeout); const response = yield fetch(`${this.baseUrl}${endpoint}`, { method: 'POST', headers, body: JSON.stringify(body), signal: controller.signal }); clearTimeout(timeoutId); if (!response.ok) { const errorData = yield response.json().catch(() => ({})); throw new Error(`API请求失败: ${response.status} ${response.statusText} - ${JSON.stringify(errorData)}`); } if (!response.body) { throw new Error('响应没有可读流'); } return response.body; } catch (error) { if (error instanceof Error) { throw new Error(`[${this.name}] ${error.message}`); } throw error; } }); } /** * 从Claude内容块中提取文本 */ extractTextFromContent(content) { return content .filter(item => item.type === 'text') .map(item => item.text || '') .join(''); } /** * 将文本带图像提示发送到Claude * 支持URL或Base64编码图像 */ generateTextWithImage(params) { return __awaiter(this, void 0, void 0, function* () { var _a, _b, _c, _d, _e; const model = params.model || this.model; // 构建多模态内容 const content = []; // 添加图像内容(如果有) if (params.image) { if (params.image.url) { content.push({ type: 'image', source: { type: 'url', url: params.image.url } }); } else if (params.image.base64Data) { content.push({ type: 'image', source: { type: 'base64', media_type: params.image.mimeType || 'image/jpeg', data: params.image.base64Data } }); } } // 添加文档内容(如果有) if (params.document) { if (params.document.url) { content.push({ type: 'document', source: { type: 'url', url: params.document.url } }); } else if (params.document.base64Data) { content.push({ type: 'document', source: { type: 'base64', media_type: params.document.mimeType || 'application/pdf', data: params.document.base64Data } }); } } // 添加文本内容 content.push({ type: 'text', text: params.prompt }); // 构建请求消息 const messages = [{ role: 'user', content }]; // 构建请求体 const requestBody = { model, messages, max_tokens: params.maxTokens || 1000, temperature: (_a = params.temperature) !== null && _a !== void 0 ? _a : 0.7, stream: params.stream || false }; // 添加系统消息(如果有) if (params.systemMessage) { requestBody.system = params.systemMessage; } // 添加top_p(如果指定) if (params.topP !== undefined) { requestBody.top_p = params.topP; } // 发送请求并获取响应 const data = yield this.sendClaudeRequest('/messages', requestBody); return { text: this.extractTextFromContent(data.content), usage: { promptTokens: ((_b = data.usage) === null || _b === void 0 ? void 0 : _b.input_tokens) || 0, completionTokens: ((_c = data.usage) === null || _c === void 0 ? void 0 : _c.output_tokens) || 0, totalTokens: (((_d = data.usage) === null || _d === void 0 ? void 0 : _d.input_tokens) || 0) + (((_e = data.usage) === null || _e === void 0 ? void 0 : _e.output_tokens) || 0) }, rawResponse: data }; }); } /** * 将通用ChatMessage格式转换为Claude消息格式 */ convertToCloudeMessages(messages) { return messages.map(msg => { // Claude不支持function或tool角色,忽略它们或转换为用户消息 const role = msg.role === 'function' || msg.role === 'tool' ? 'user' : (msg.role === 'system' ? 'user' : msg.role); // 简单文本内容 if (typeof msg.content === 'string') { return { role, content: msg.content }; } // 处理复杂内容(数组,可能包含多模态内容) if (Array.isArray(msg.content)) { // 将内容转换为Claude格式 const claudeContent = msg.content.map(item => { // 文本内容 if (typeof item === 'string' || (item && item.type === 'text')) { return { type: 'text', text: typeof item === 'string' ? item : (item.text || '') }; } // 图像内容 if (item && item.type === 'image' && item.image_url) { return { type: 'image', source: { type: 'url', url: item.image_url.url } }; } // 文档内容 if (item && item.type === 'document' && item.document_url) { return { type: 'document', source: { type: 'url', url: item.document_url.url } }; } // 其他内容类型 return { type: 'text', text: typeof item === 'object' ? JSON.stringify(item) : String(item) }; }); return { role, content: claudeContent }; } // 默认处理 return { role, content: String(msg.content || '') }; }); } } exports.AnthropicProvider = AnthropicProvider; //# sourceMappingURL=anthropic.js.map