import axios from 'axios'; import crypto from 'crypto'; import config from '../../config/index.js'; import { enhanceFormsOfWords } from './enhanceFormsOfWords.js'; /** * AI平台接口类 * 定义了所有AI平台需要实现的方法 */ class AIProvider { /** * 生成文章 * @param {string} content - 生成文章的提示内容 * @returns {Promise} - 返回生成的文章JSON字符串 */ async generateArticle(content) { throw new Error('Method not implemented'); } } /** * OpenAI平台实现 */ class OpenAIProvider extends AIProvider { constructor() { super(); this.headers = { "Authorization": "Bearer " + config.openai.apikey, "Content-Type": "application/json" }; this.url = "https://api.openai.com/v1/chat/completions"; this.model = "gpt-3.5-turbo"; } async generateArticle(content) { const postJSON = { "model": this.model, "messages": [ { "role": "user", "content": content, } ] }; try { const response = await axios.post(this.url, postJSON, { headers: this.headers }); return response.data.choices[0].message.content; } catch (error) { console.error("OpenAI API error:", error); throw error; } } } /** * 火山云AI平台实现 */ class VolcesAIProvider extends AIProvider { /** * 创建火山云AI提供者实例 * @param {string} version - 版本号 */ constructor(version) { super(); if (version.indexOf("deepseek")>0){ version=version.substring(7); } // 获取当前版本的配置,如果版本不存在则使用1.5版本 const currentConfig = { apikey: config.huoshancloud.apikeyHLR, model: version }; this.version = version; this.headers = { 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/39.0.2171.65 Safari/537.36', "Authorization": "Bearer " + currentConfig.apikey, "Content-Type": "application/json" }; this.url = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"; this.model = currentConfig.model; } async generateArticle(content) { let postJSON = { "model": this.model, "messages": [ { "role": "system", "content": "你是一个专业的AI助手,请以JSON格式回复。" }, { "role": "user", "content": content } ] }; if (this.version.indexOf("deepseek")>=0 || this.version.indexOf("seed-1")>=0){ postJSON.response_format={ "type": "json_object" }; postJSON.thinking={ "type": "disabled" }; } try { console.log(`火山云${this.version}`); // 移除encodeURI,直接使用原始URL const response = await axios.post(this.url, postJSON, { headers: this.headers }); return response.data.choices[0].message.content; } catch (error) { console.error("VolcesAI API error:", error); // 添加更详细的错误日志 if (error.response) { console.error("错误详情:", { status: error.response.status, data: error.response.data }); } throw error; } } } /** * 讯飞星火平台实现 (spark X1版本) */ class XunFeiYunAIProvider extends AIProvider { constructor() { super(); // 使用API Key和Secret拼接成"AK:SK"格式 this.apiKey = `${config.xfyun.apikey}:${config.xfyun.apisecret}`; this.headers = { "Content-Type": "application/json", "Authorization": `Bearer ${this.apiKey}` }; this.url = "https://spark-api-open.xf-yun.com/v2/chat/completions"; } async generateArticle(content) { const postJSON = { "model": "x1", "messages": [ { "role": "user", "content": content } ], "temperature": 0.7, "max_tokens": 2048, "user": "123456" // 固定用户ID }; try { // 增加重试机制 let retries = 3; let lastError = null; while (retries > 0) { try { console.log(`讯飞云`); const response = await axios.post(this.url, postJSON, { headers: this.headers, timeout: 60000 // 增加到60秒超时 }); // 处理OpenAI兼容格式的响应 if (response.data?.choices?.[0]?.message?.content) { return response.data.choices[0].message.content; } console.error("XunFeiYun X1 API response:", response.data); throw new Error("Invalid response format from XunFeiYun X1 API"); } catch (error) { lastError = error; retries--; if (retries > 0) { console.warn(`API请求失败,剩余重试次数: ${retries},等待2秒后重试...`); await new Promise(resolve => setTimeout(resolve, 2000)); continue; } // 更详细的错误日志 if (error.response) { console.error("XFYun API error response:", { status: error.response.status, data: error.response.data, headers: error.response.headers }); } else if (error.request) { console.error("XFYun API request error:", { method: error.config.method, url: error.config.url, headers: error.config.headers, data: error.config.data }); } else { console.error("XFYun API setup error:", error.message); } throw error; } } throw lastError || new Error("API请求失败"); } catch (error) { console.error("XFYun API error:", error); throw error; } } } /** * 阿里云通义平台实现 */ class AliyunAIProvider extends AIProvider { constructor(model = 'qwen-plus') { super(); let url="https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions"; this.accessKey = config.aliyun.apikeyHLR; this.headers = { "Content-Type": "application/json", "Accept": "application/json" }; this.url = url; this.model = model; } /** * 生成文章 * @param {string} content - 生成文章的提示内容 * @returns {Promise} - 返回生成的文章内容 */ async generateArticle(content) { // 设置请求头中的API密钥 this.headers["Authorization"] = `Bearer ${this.accessKey}`; const postJSON = { "model": this.model, "messages": [ { "role": "user", "content": content } ], "temperature": 0.7, "top_p": 0.8 }; try { console.log(`阿里云 ${this.model}`); const response = await axios.post(this.url, postJSON, { headers: this.headers }); // 根据阿里云通义API的返回格式提取内容 if (response.data && response.data.choices && response.data.choices[0] && response.data.choices[0].message) { let responseContent = response.data.choices[0].message.content; // 处理可能的Markdown代码块标记 if (responseContent.startsWith('```json') || responseContent.startsWith('```')) { console.log("阿里云返回了Markdown代码块,正在处理..."); // 移除开头的```json或``` responseContent = responseContent.replace(/^```(?:json)?\s*\n/, ''); // 移除结尾的``` responseContent = responseContent.replace(/\n```\s*$/, ''); } return responseContent; } else { throw new Error("Unexpected response format from Aliyun API"); } } catch (error) { console.error("Aliyun AI API error:", error); throw error; } } } /** * 腾讯混元大模型平台实现 */ class TencentHunyuanAIProvider extends AIProvider { constructor(model = 'hunyuan-turbos-latest') { super(); this.headers = { "Authorization": "Bearer " + config.tencentcloudHunyuan.apikey, "Content-Type": "application/json" }; this.url = "https://api.hunyuan.cloud.tencent.com/v1/chat/completions"; this.model = model; } async generateArticle(content) { const postJSON = { "model": this.model, "messages": [ { "role": "user", "content": content, } ] }; try { console.log(`腾讯云${this.model}`); const response = await axios.post(this.url, postJSON, { headers: this.headers }); return response.data.choices[0].message.content; } catch (error) { console.error("OpenAI API error:", error); throw error; } } } /** * 百度千帆平台实现 */ class BaiduAIProvider extends AIProvider { constructor(model = 'deepseek-v3') { super(); this.headers = { "Authorization": "Bearer " + config.baiducloud.apikey, "Content-Type": "application/json" }; this.url = 'https://qianfan.baidubce.com/v2/chat/completions'; this.model = model; } async generateArticle(content) { const postJSON = { "model": this.model, "messages": [ { "role": "user", "content": content, } ], "temperature": 0.8, "top_p": 0.8, "penalty_score": 1 }; try { // 增加重试机制 let retries = 3; let lastError = null; let backoffTime = 1000; // 初始等待时间1秒 while (retries > 0) { try { console.log(`百度千帆 ${this.model}`); const response = await axios.post(this.url, postJSON, { headers: this.headers, timeout: 60000 // 60秒超时 }); // 处理响应格式 if (response.data?.choices?.[0]?.message?.content) { return response.data.choices[0].message.content; } else if (response.data?.result) { return response.data.result; } else { console.error("百度千帆API响应格式异常:", response.data); throw new Error("Unexpected response format from Baidu API"); } } catch (error) { lastError = error; // 特别处理429错误(请求过多) if (error.response && error.response.status === 429) { console.warn(`百度千帆API限流,等待${backoffTime/1000}秒后重试...`); await new Promise(resolve => setTimeout(resolve, backoffTime)); backoffTime *= 2; // 指数退避策略 retries--; continue; } // 处理其他错误 retries--; if (retries > 0) { console.warn(`API请求失败,剩余重试次数: ${retries},等待${backoffTime/1000}秒后重试...`); await new Promise(resolve => setTimeout(resolve, backoffTime)); backoffTime *= 2; // 指数退避策略 continue; } // 详细记录错误信息 if (error.response) { console.error("百度千帆API错误响应:", { status: error.response.status, data: error.response.data, headers: error.response.headers }); } else if (error.request) { console.error("百度千帆API请求错误:", { method: error.config.method, url: error.config.url, headers: error.config.headers, data: error.config.data }); } else { console.error("百度千帆API设置错误:", error.message); } throw error; } } throw lastError || new Error("百度千帆API请求失败,已达到最大重试次数"); } catch (error) { console.error("Baidu API error:", error); throw error; } } } /** * Openrouter平台实现 */ class OpenrouterProvider extends AIProvider { constructor() { super(); this.headers = { "Authorization": "Bearer " + config.openroutercloud.apikey, "Content-Type": "application/json" }; this.url = "https://openrouter.ai/api/v1/chat/completions"; this.model = "moonshotai/kimi-k2:free"; } async generateArticle(content) { const postJSON = { "model": this.model, "messages": [ { "role": "user", "content": content, } ] }; try { console.log(`Openrouter ${this.model}`); const response = await axios.post(this.url, postJSON, { headers: this.headers }); return response.data.choices[0].message.content; } catch (error) { console.error("OpenAI API error:", error); throw error; } } } /** * AI提供者工厂类 * 根据配置创建不同的AI平台实例 */ class AIProviderFactory { /** * 获取AI提供者实例 * @param {string} provider - AI提供者名称 * @returns {AIProvider} - 返回对应的AI提供者实例 */ static getProvider(provider) { const providerLower = provider.toLowerCase(); // 处理传统提供者名称 switch (providerLower) { case 'openai': return new OpenAIProvider(); case 'openrouter-moonshotai/kimi-k2': return new OpenrouterProvider("moonshotai/kimi-k2:free"); case 'doubao-1-5-pro-32k-250115': return new VolcesAIProvider(providerLower); case 'doubao-seed-1-6-250615': return new VolcesAIProvider(providerLower); case 'doubao-deepseek-v3-250324': return new VolcesAIProvider("deepseek-v3-250324"); case 'doubao-deepseek-r1-250528': return new VolcesAIProvider("deepseek-r1-250528"); case 'doubao-kimi-k2-250711': return new VolcesAIProvider("kimi-k2-250711"); case 'ali-qwen-plus-2025-07-14': return new AliyunAIProvider("qwen-plus-2025-07-14"); case 'ali-qwen-max': return new AliyunAIProvider("qwen-max"); case 'llama-4-scout-17b-16e-instruct': return new AliyunAIProvider(providerLower); case 'llama-4-maverick-17b-128e-instruct': return new AliyunAIProvider(providerLower); case 'ali-deepseek-r1-0528': return new AliyunAIProvider("deepseek-r1-0528"); case 'ali-deepseek-v3': return new AliyunAIProvider("deepseek-v3"); case 'ali-moonshot-kimi-k2-instruct': return new AliyunAIProvider("Moonshot-Kimi-K2-Instruct"); case 'xf-yun-spark-x1': return new XunFeiYunAIProvider(); case 'tencent-hunyuan-turbos-latest': return new TencentHunyuanAIProvider("hunyuan-turbos-latest"); case 'tencent-hunyuan-t1-latest': return new TencentHunyuanAIProvider("hunyuan-t1-latest"); case 'baidu-deepseek-v3': return new BaiduAIProvider(); case 'baidu-deepseek-r1': return new BaiduAIProvider("deepseek-r1"); case 'baidu-ernie-4.5-turbo-vl-32k-preview': return new BaiduAIProvider("ernie-4.5-turbo-vl-32k-preview"); default: return new VolcesAIProvider("doubao-1-5-pro-32k-250115"); // 默认使用火山云1.5 } } } /** * 生成文章的主函数 * @param {string} content - 生成文章的提示内容 * @param {string} provider - AI提供者名称,默认为'volces' * @returns {Promise} - 返回生成的文章JSON字符串 */ async function generateArticle(content, provider) { try { const aiProvider = AIProviderFactory.getProvider(provider); const result = await aiProvider.generateArticle(content); return result; } catch (error) { console.error("Generate article error:", error); throw error; } } /** * 验证并修复JSON结构 * @param {string} jsonString - 需要验证和修复的JSON字符串 * @returns {string} - 返回修复后的JSON字符串 */ function validateAndFixJSON(jsonString) { // 如果输入不是字符串,直接返回 if (typeof jsonString !== 'string') { console.error("输入不是字符串类型"); return jsonString; } // 预处理:移除Markdown代码块标记 let processedJson = jsonString; // 检查并移除Markdown代码块标记 if (processedJson.includes('```')) { console.log("检测到Markdown代码块,尝试移除标记"); // 处理可能的多行代码块 const codeBlockRegex = /```(?:json)?\s*\n([\s\S]*?)\n```/; const match = processedJson.match(codeBlockRegex); if (match && match[1]) { // 提取代码块内容 processedJson = match[1]; console.log("成功提取代码块内容"); } else { // 如果正则匹配失败,尝试简单替换 processedJson = processedJson.replace(/^```(?:json)?\s*\n/, ''); processedJson = processedJson.replace(/\n```\s*$/, ''); } } try { // 尝试解析JSON const parsed = JSON.parse(processedJson); return processedJson; } catch (error) { console.error("JSON解析错误,尝试修复:", error); // 尝试修复常见的JSON错误 let fixedJson = processedJson; // 修复缺少引号的键 fixedJson = fixedJson.replace(/(\s*?)(\w+)(\s*?):/g, '"$2":'); // 修复单引号,但不影响缩写 fixedJson = fixedJson.replace(/(? { // 检查句子是否包含中文字符 if (/[\u4e00-\u9fa5]/.test(sentence)) { chineseSentences.push(sentence); } else { englishSentences.push(sentence); } }); // 更新ArticleEnglish数组,只保留英文句子 json.ArticleEnglish = englishSentences; // 如果ArticleChinese不存在或不是数组,则创建它 if (!json.ArticleChinese || !Array.isArray(json.ArticleChinese)) { json.ArticleChinese = []; } // 将中文句子添加到ArticleChinese数组中 chineseSentences.forEach(sentence => { if (!json.ArticleChinese.includes(sentence)) { json.ArticleChinese.push(sentence); } }); } // 根据输入类型返回相应的结果 return isString ? JSON.stringify(json) : json; } // 默认导出,保持向后兼容性 export default { generateArticle, enhanceFormsOfWords, validateAndFixJSON, normalizeArticleFields };