修复AI翻译功能
This commit is contained in:
+25
-85
@@ -1,60 +1,27 @@
|
||||
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;
|
||||
}
|
||||
|
||||
// 翻译单个词组(带重试)
|
||||
export async function translateWithAI(
|
||||
word: string,
|
||||
config?: AIConfig,
|
||||
maxRetries: number = 3
|
||||
): Promise<string | null> {
|
||||
const aiConfig = config || getAIConfig();
|
||||
export async function translateWithAI(word: string): Promise<string | null> {
|
||||
// 获取配置
|
||||
const aiConfig = getConfig().ai
|
||||
|
||||
if (!aiConfig.apiKey) {
|
||||
throw new Error("AI API Key 未配置");
|
||||
@@ -66,67 +33,40 @@ export async function translateWithAI(
|
||||
});
|
||||
|
||||
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",
|
||||
model: aiConfig.model,
|
||||
messages: [
|
||||
{
|
||||
role: "system",
|
||||
content: "你是一个严格遵循指令的翻译助手。必须只返回要求的 JSON 格式,不要返回任何其他内容。",
|
||||
content: "你是一个严格遵循指令的翻译助手。必须只返回一行纯 JSON,不要加任何其他文字、符号、代码块。",
|
||||
},
|
||||
{ role: "user", content: prompt },
|
||||
],
|
||||
temperature: 0,
|
||||
max_tokens: 50,
|
||||
{role: "user", content: prompt},
|
||||
]
|
||||
});
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
return parseTranslation(content);
|
||||
} catch (error) {
|
||||
console.error(`Attempt ${attempt + 1} error:`, error);
|
||||
console.error("翻译出错:", error);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
// 批量翻译词组
|
||||
export async function batchTranslateWithAI(
|
||||
words: string[],
|
||||
config?: AIConfig
|
||||
words: string[]
|
||||
): Promise<Map<string, string>> {
|
||||
const results = new Map<string, string>();
|
||||
|
||||
for (const word of words) {
|
||||
try {
|
||||
const translation = await translateWithAI(word, config);
|
||||
const translation = await translateWithAI(word);
|
||||
if (translation) {
|
||||
results.set(word, translation);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
|
||||
Reference in New Issue
Block a user