using OpenAI; using OpenAI.Chat; using System; using System.ClientModel; using System.Collections.Generic; using System.Linq; using System.Net; using System.Text; using System.Threading; using System.Threading.Tasks; namespace MCI18n.AI { internal class I18nChatClient { /// /// 火山方舟API Key /// private string API_KEY = "API_KEY"; private string API_ENDPOINT = "https://ark.cn-beijing.volces.com/api/v3"; private readonly ChatClient _client; // 使用信号量限制并发请求数 private static readonly SemaphoreSlim _semaphore = new SemaphoreSlim(2, 3); // 最多2个并发请求,可根据API限制调整 // 重试次数和延迟 private const int MaxRetries = 3; private static readonly TimeSpan InitialRetryDelay = TimeSpan.FromSeconds(1); public I18nChatClient(string modelName) { _client = new ChatClient(modelName, new ApiKeyCredential(API_KEY), new OpenAIClientOptions { Endpoint = new Uri(API_ENDPOINT), NetworkTimeout = TimeSpan.FromSeconds(20d) }); } private string SystemPrompt = @" 你是一个minecraft相关的语言翻译机器人。 你需要翻译用户提供的文本到指定的目标语言。 源语言通常是英文。 你只需要翻译文本,禁止解释或提供额外信息。 如果存在多种解释或是含义,只需要给出最贴近Minecraft与社区Mod相关语言的一个。 被{}包裹的内容保留原文与位置。 "; private string Prompt = @" 目标语言:{0} 用户提供的文本: {1} "; public string Translate(string text, string targetLanguage) { try { _semaphore.Wait(); // 获取信号量 try { var quest = string.Format(Prompt, targetLanguage, text); var response = _client.CompleteChat( ChatMessage.CreateSystemMessage(SystemPrompt), ChatMessage.CreateUserMessage($"{quest}") ); if (!string.IsNullOrWhiteSpace(response.Value.Content[0].Text)) { return response.Value.Content[0].Text; } else { throw new Exception("No response from translation model."); } } finally { _semaphore.Release(); // 释放信号量 } } catch (Exception ex) { throw; } } public async Task TranslateAsync(string text, string targetLanguage) { int retries = 0; TimeSpan delay = InitialRetryDelay; while (true) { try { await _semaphore.WaitAsync(); // 异步获取信号量 try { var quest = string.Format(Prompt, targetLanguage, text); var response = await _client.CompleteChatAsync( ChatMessage.CreateSystemMessage(SystemPrompt), ChatMessage.CreateUserMessage($"{quest}") ); if (!string.IsNullOrWhiteSpace(response.Value.Content[0].Text)) { return response.Value.Content[0].Text; } else { throw new Exception("No response from translation model."); } } finally { _semaphore.Release(); // 释放信号量 } } catch (ClientResultException ex) when (ex.Status == 429 && retries < MaxRetries) { // 针对429错误特殊处理,采用退避策略 retries++; await Task.Delay(delay); delay = TimeSpan.FromMilliseconds(delay.TotalMilliseconds * 2); // 指数退避 continue; // 重试请求 } catch (Exception ex) { throw; } break; // 如果成功或者非429错误,退出循环 } // 这里不会被执行到,只是为了满足编译器要求 throw new Exception("Unexpected code path"); } } }