diff --git a/lib/ai-translate.ts b/lib/ai-translate.ts index 1e7a5e5..b6fd695 100644 --- a/lib/ai-translate.ts +++ b/lib/ai-translate.ts @@ -1,139 +1,79 @@ import OpenAI from "openai"; +import {getConfig} from "@/lib/config"; -// AI 翻译配置 -interface AIConfig { - apiKey: string; - baseUrl?: string; - model?: string; -} - -// 默认配置(从环境变量) -function getDefaultConfig(): AIConfig { - return { - apiKey: process.env.AI_API_KEY || "", - baseUrl: process.env.AI_BASE_URL || undefined, - model: process.env.AI_MODEL || "gpt-3.5-turbo", - }; -} - -// 模块级配置存储 -let savedConfig: AIConfig | null = null; - -// 设置保存的配置 -export function setAIConfig(config: AIConfig) { - savedConfig = config; -} - -// 获取配置(优先使用保存的配置) -export function getAIConfig(): AIConfig { - return savedConfig || getDefaultConfig(); -} - -// 解析翻译结果 function parseTranslation(content: string): string | null { - const patterns = [ - /english\s*:\s*['"]([^'"]+)['"]/i, - /english\s*[:\s]+([^,'"\n]+)/i, - /['"]([^'"]+)['"]\s*[,}].*english/i, - /^([^,]+)\s*,\s*english\s*:\s*['"]([^'"]+)['"]/i, - ]; + // 第一步:清理内容,移除 Markdown 代码块、换行、多余空格 + const cleanContent = content + .replace(/```json|```/g, '') // 移除 ```json 和 ``` + .replace(/\n/g, ' ') // 把换行换成空格 + .trim(); - for (const pattern of patterns) { - const match = content.match(pattern); - if (match) { - return match[1]?.trim() || null; + // 精准匹配 english 字段(支持任何格式、带空格) + const regex = /"english"\s*:\s*["']([^"']+)["']/i; + const match = cleanContent.match(regex); + + if (match && match[1]) { + return match[1].trim(); } - } - - return null; + return null; } // 翻译单个词组(带重试) -export async function translateWithAI( - word: string, - config?: AIConfig, - maxRetries: number = 3 -): Promise { - const aiConfig = config || getAIConfig(); +export async function translateWithAI(word: string): Promise { + // 获取配置 + const aiConfig = getConfig().ai - if (!aiConfig.apiKey) { - throw new Error("AI API Key 未配置"); - } + if (!aiConfig.apiKey) { + throw new Error("AI API Key 未配置"); + } - const client = new OpenAI({ - apiKey: aiConfig.apiKey, - baseURL: aiConfig.baseUrl, - }); - - const prompt = `你是一个专业的中文到英文翻译助手。 + const client = new OpenAI({ + apiKey: aiConfig.apiKey, + baseURL: aiConfig.baseUrl, + }); + const prompt = `你是一个专业的中文到英文翻译助手。 任务:将给定的中文词组翻译成英文。 - 严格要求: 1. 必须严格返回 JSON 格式:{"word":"中文原文","english":"英文翻译"} 2. 不要返回任何其他内容,不要解释 -3. 只返回这一行 JSON -4. 翻译要简洁、准确 +3. 只返回这一行 JSON,不要加引号,不要加代码块 +中文词组:${word}`; -中文词组:${word} - -请立即返回 JSON 结果:`; - - for (let attempt = 0; attempt < maxRetries; attempt++) { try { - const completion = await client.chat.completions.create({ - model: aiConfig.model || "gpt-3.5-turbo", - messages: [ - { - role: "system", - content: "你是一个严格遵循指令的翻译助手。必须只返回要求的 JSON 格式,不要返回任何其他内容。", - }, - { role: "user", content: prompt }, - ], - temperature: 0, - max_tokens: 50, - }); - - const content = completion.choices[0]?.message?.content || ""; - const translation = parseTranslation(content); - - if (translation && translation.length > 0) { - return translation; - } - - // Fallback: 提取英文单词 - const fallbackMatch = content.match(/[a-zA-Z][a-zA-Z\s-]*/); - if (fallbackMatch) { - const fallback = fallbackMatch[0].trim(); - if (fallback.length > 1) { - return fallback; - } - } + const completion = await client.chat.completions.create({ + model: aiConfig.model, + messages: [ + { + role: "system", + content: "你是一个严格遵循指令的翻译助手。必须只返回一行纯 JSON,不要加任何其他文字、符号、代码块。", + }, + {role: "user", content: prompt}, + ] + }); + const content = completion.choices[0]?.message?.content || ""; + return parseTranslation(content); } catch (error) { - console.error(`Attempt ${attempt + 1} error:`, error); + console.error("翻译出错:", error); } - } - - return null; + return null; } - // 批量翻译词组 export async function batchTranslateWithAI( - words: string[], - config?: AIConfig + words: string[] ): Promise> { - const results = new Map(); + const results = new Map(); - for (const word of words) { - try { - const translation = await translateWithAI(word, config); - if (translation) { - results.set(word, translation); - } - } catch (error) { - console.error(`Failed to translate "${word}":`, error); + for (const word of words) { + try { + const translation = await translateWithAI(word); + if (translation) { + results.set(word, translation); + } + } catch (error) { + console.error(`Failed to translate "${word}":`, error); + } } - } - return results; + return results; } diff --git a/lib/database.ts b/lib/database.ts index 5e539c3..4aa8844 100644 --- a/lib/database.ts +++ b/lib/database.ts @@ -14,16 +14,6 @@ const pool = mysql.createPool({ connectionLimit: 10, queueLimit: 0, }); -console.log({ - host: dataBaseConfig.host || "127.0.0.1", - port: dataBaseConfig.port || 3306, - user: dataBaseConfig.user || "root", - password: dataBaseConfig.password || "123456", - database: dataBaseConfig.database || "recipe_tools", - waitForConnections: true, - connectionLimit: 10, - queueLimit: 0, -}) export default pool; /**