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");
}
}
}