// AI翻译服务 // filepath: h:\blews\akmon\uni_modules\ak-ai-news\services\ai-translation-service.uts import { AkReq } from '@/uni_modules/ak-req/index.uts' import type { TranslationResult, TranslationOptions, AIProvider, AIResponse, AIServiceConfig } from '../types/ai-types.uts' export class AITranslationService { private config: AIServiceConfig private req: AkReq private cache: Map = new Map() constructor(config: AIServiceConfig) { this.config = config this.req = new AkReq() } /** * 翻译文本 - 智能选择最佳AI服务 */ async translateText( text: string, targetLang: string, sourceLang?: string, options?: TranslationOptions ): Promise> { try { // 检查缓存 const cacheKey = this.generateCacheKey(text, targetLang, sourceLang) const cached = this.cache.get(cacheKey) if (cached && this.isCacheValid(cached)) { return { success: true, data: cached, processingTimeMs: 0, costUSD: 0 } } // 智能选择提供商 const provider = this.selectOptimalProvider(text, targetLang, options) let result: TranslationResult const startTime = Date.now() switch (provider) { case 'openai': result = await this.translateWithOpenAI(text, targetLang, sourceLang, options) break case 'google': result = await this.translateWithGoogle(text, targetLang, sourceLang, options) break case 'baidu': result = await this.translateWithBaidu(text, targetLang, sourceLang, options) break default: throw new Error(`不支持的AI提供商: ${provider}`) } result.processingTimeMs = Date.now() - startTime // 质量检查 if (result.qualityScore < (options?.qualityThreshold ?? 0.7)) { // 尝试使用备用提供商 const fallbackProvider = this.getFallbackProvider(provider) if (fallbackProvider) { const fallbackResult = await this.translateWithProvider( text, targetLang, sourceLang, fallbackProvider, options ) if (fallbackResult.qualityScore > result.qualityScore) { result = fallbackResult } } } // 缓存结果 this.cache.set(cacheKey, result) // 记录使用统计 await this.recordUsage(result) return { success: true, data: result, processingTimeMs: result.processingTimeMs, costUSD: result.costUSD, provider: result.provider } } catch (error) { console.error('翻译失败:', error) return { success: false, error: error instanceof Error ? error.message : '翻译服务异常', errorCode: 'TRANSLATION_FAILED' } } } /** * 批量翻译 */ async batchTranslate( texts: string[], targetLang: string, sourceLang?: string, options?: TranslationOptions ): Promise> { try { const results: TranslationResult[] = [] const batchSize = 10 // 批处理大小 for (let i = 0; i < texts.length; i += batchSize) { const batch = texts.slice(i, i + batchSize) const batchPromises = batch.map(text => this.translateText(text, targetLang, sourceLang, options) ) const batchResults = await Promise.all(batchPromises) for (const result of batchResults) { if (result.success && result.data) { results.push(result.data) } } // 避免API限流 if (i + batchSize < texts.length) { await this.delay(100) } } return { success: true, data: results, processingTimeMs: results.reduce((sum, r) => sum + r.processingTimeMs, 0), costUSD: results.reduce((sum, r) => sum + r.costUSD, 0) } } catch (error) { return { success: false, error: error instanceof Error ? error.message : '批量翻译失败', errorCode: 'BATCH_TRANSLATION_FAILED' } } } /** * OpenAI翻译实现 */ private async translateWithOpenAI( text: string, targetLang: string, sourceLang?: string, options?: TranslationOptions ): Promise { const openaiConfig = this.config.openai if (!openaiConfig) { throw new Error('OpenAI配置未找到') } const prompt = this.buildOpenAIPrompt(text, targetLang, sourceLang, options) const response = await this.req.post({ url: `${openaiConfig.baseURL || 'https://api.openai.com'}/v1/chat/completions`, headers: { 'Authorization': `Bearer ${openaiConfig.apiKey}`, 'Content-Type': 'application/json' }, data: { model: options?.model || openaiConfig.model, messages: [ { role: 'system', content: '你是一个专业的翻译助手,能够提供高质量的多语言翻译服务。' }, { role: 'user', content: prompt } ], max_tokens: options?.maxTokens || openaiConfig.maxTokens, temperature: options?.temperature || openaiConfig.temperature } }) if (!response.success || !response.data) { throw new Error('OpenAI API调用失败') } const choice = response.data.choices?.[0] if (!choice) { throw new Error('OpenAI响应格式错误') } return this.parseOpenAIResponse( choice.message.content, text, targetLang, sourceLang || 'auto', response.data.usage ) } /** * Google翻译实现 */ private async translateWithGoogle( text: string, targetLang: string, sourceLang?: string, options?: TranslationOptions ): Promise { const googleConfig = this.config.google if (!googleConfig) { throw new Error('Google翻译配置未找到') } const startTime = Date.now() const response = await this.req.post({ url: 'https://translation.googleapis.com/language/translate/v2', headers: { 'Content-Type': 'application/json' }, data: { key: googleConfig.apiKey, q: text, target: this.convertLanguageCode(targetLang, 'google'), source: sourceLang ? this.convertLanguageCode(sourceLang, 'google') : undefined, format: 'text' } }) if (!response.success || !response.data) { throw new Error('Google翻译API调用失败') } const translation = response.data.data?.translations?.[0] if (!translation) { throw new Error('Google翻译响应格式错误') } return { translatedText: translation.translatedText, originalText: text, sourceLang: translation.detectedSourceLanguage || sourceLang || 'auto', targetLang, confidence: 0.9, // Google翻译通常质量较高 qualityScore: 0.85, provider: 'google', tokensUsed: Math.ceil(text.length / 4), // 估算token数 processingTimeMs: Date.now() - startTime, costUSD: this.calculateGoogleCost(text.length) } } /** * 百度翻译实现 */ private async translateWithBaidu( text: string, targetLang: string, sourceLang?: string, options?: TranslationOptions ): Promise { const baiduConfig = this.config.baidu if (!baiduConfig) { throw new Error('百度翻译配置未找到') } const startTime = Date.now() const salt = Date.now().toString() const sign = this.generateBaiduSign(text, salt, baiduConfig.apiKey, baiduConfig.secretKey) const response = await this.req.post({ url: 'https://fanyi-api.baidu.com/api/trans/vip/translate', headers: { 'Content-Type': 'application/x-www-form-urlencoded' }, data: { q: text, from: sourceLang ? this.convertLanguageCode(sourceLang, 'baidu') : 'auto', to: this.convertLanguageCode(targetLang, 'baidu'), appid: baiduConfig.apiKey, salt: salt, sign: sign } }) if (!response.success || !response.data) { throw new Error('百度翻译API调用失败') } const result = response.data.trans_result?.[0] if (!result) { throw new Error('百度翻译响应格式错误') } return { translatedText: result.dst, originalText: text, sourceLang: response.data.from || sourceLang || 'auto', targetLang, confidence: 0.85, qualityScore: 0.8, provider: 'baidu', tokensUsed: Math.ceil(text.length / 4), processingTimeMs: Date.now() - startTime, costUSD: this.calculateBaiduCost(text.length) } } /** * 选择最优提供商 */ private selectOptimalProvider( text: string, targetLang: string, options?: TranslationOptions ): AIProvider { if (options?.provider) { return options.provider } // 根据文本长度和语言选择最佳提供商 const textLength = text.length const isChineseTarget = targetLang.startsWith('zh') const isChineseSource = /[\u4e00-\u9fff]/.test(text) // 中文相关翻译优先使用百度 if (isChineseTarget || isChineseSource) { return 'baidu' } // 长文本使用OpenAI(更好的上下文理解) if (textLength > 1000) { return 'openai' } // 短文本使用Google(速度快,成本低) return 'google' } /** * 获取备用提供商 */ private getFallbackProvider(primary: AIProvider): AIProvider | null { switch (primary) { case 'openai': return 'google' case 'google': return 'baidu' case 'baidu': return 'google' default: return null } } /** * 生成缓存键 */ private generateCacheKey(text: string, targetLang: string, sourceLang?: string): string { const source = sourceLang || 'auto' const hash = this.simpleHash(text) return `${source}-${targetLang}-${hash}` } /** * 检查缓存是否有效 */ private isCacheValid(result: TranslationResult): boolean { // 简单的缓存有效性检查,可以根据需要扩展 return result.qualityScore > 0.7 } /** * 构建OpenAI提示词 */ private buildOpenAIPrompt( text: string, targetLang: string, sourceLang?: string, options?: TranslationOptions ): string { let prompt = `请将以下文本翻译成${this.getLanguageName(targetLang)}:\n\n${text}\n\n` if (options?.culturalAdaptation) { prompt += '请考虑文化差异,进行适当的本地化调整。\n' } if (options?.preserveFormatting) { prompt += '请保持原文的格式和结构。\n' } prompt += '只返回翻译结果,不要包含其他解释。' return prompt } /** * 解析OpenAI响应 */ private parseOpenAIResponse( content: string, originalText: string, targetLang: string, sourceLang: string, usage: any ): TranslationResult { return { translatedText: content.trim(), originalText, sourceLang, targetLang, confidence: 0.9, qualityScore: 0.9, provider: 'openai', tokensUsed: usage?.total_tokens || 0, processingTimeMs: 0, costUSD: this.calculateOpenAICost(usage?.total_tokens || 0) } } /** * 转换语言代码 */ private convertLanguageCode(code: string, provider: AIProvider): string { const codeMap: Record> = { openai: { 'zh-CN': 'Chinese', 'en-US': 'English', 'ja-JP': 'Japanese', 'ko-KR': 'Korean' }, google: { 'zh-CN': 'zh', 'en-US': 'en', 'ja-JP': 'ja', 'ko-KR': 'ko' }, baidu: { 'zh-CN': 'zh', 'en-US': 'en', 'ja-JP': 'jp', 'ko-KR': 'kor' }, custom: {} } return codeMap[provider]?.[code] || code } /** * 获取语言名称 */ private getLanguageName(code: string): string { const nameMap: Record = { 'zh-CN': '中文', 'en-US': 'English', 'ja-JP': '日语', 'ko-KR': '韩语', 'es-ES': 'Spanish', 'fr-FR': 'French', 'de-DE': 'German' } return nameMap[code] || code } /** * 计算成本 */ private calculateOpenAICost(tokens: number): number { // GPT-4 pricing: $0.03 per 1K tokens (input + output) return (tokens / 1000) * 0.03 } private calculateGoogleCost(textLength: number): number { // Google Translate: $20 per 1M characters return (textLength / 1000000) * 20 } private calculateBaiduCost(textLength: number): number { // 百度翻译:较低成本,假设$5 per 1M characters return (textLength / 1000000) * 5 } /** * 生成百度签名 */ private generateBaiduSign(text: string, salt: string, appid: string, key: string): string { // 简化的签名生成,实际应用中需要使用MD5 const str = appid + text + salt + key return this.simpleHash(str) } /** * 简单哈希函数 */ private simpleHash(str: string): string { let hash = 0 for (let i = 0; i < str.length; i++) { const char = str.charCodeAt(i) hash = ((hash << 5) - hash) + char hash = hash & hash // Convert to 32-bit integer } return Math.abs(hash).toString(36) } /** * 延迟函数 */ private delay(ms: number): Promise { return new Promise(resolve => setTimeout(resolve, ms)) } /** * 记录使用统计 */ private async recordUsage(result: TranslationResult): Promise { try { // 这里可以将使用统计发送到数据库 console.log('翻译使用统计:', { provider: result.provider, tokensUsed: result.tokensUsed, costUSD: result.costUSD, processingTimeMs: result.processingTimeMs }) } catch (error) { console.error('记录使用统计失败:', error) } } /** * 根据提供商翻译 */ private async translateWithProvider( text: string, targetLang: string, sourceLang: string | undefined, provider: AIProvider, options?: TranslationOptions ): Promise { switch (provider) { case 'openai': return await this.translateWithOpenAI(text, targetLang, sourceLang, options) case 'google': return await this.translateWithGoogle(text, targetLang, sourceLang, options) case 'baidu': return await this.translateWithBaidu(text, targetLang, sourceLang, options) default: throw new Error(`不支持的提供商: ${provider}`) } } }