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