146 lines
4.7 KiB
C#
146 lines
4.7 KiB
C#
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
|
||
{
|
||
/// <summary>
|
||
/// 火山方舟API Key
|
||
/// </summary>
|
||
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<string> 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");
|
||
}
|
||
}
|
||
} |