Skip to content

Commit

Permalink
feat: Adapt gemini translation
Browse files Browse the repository at this point in the history
  • Loading branch information
ZGGSONG committed Jan 18, 2024
1 parent 6348ed7 commit 9ac9420
Show file tree
Hide file tree
Showing 15 changed files with 468 additions and 25 deletions.
4 changes: 3 additions & 1 deletion STranslate.Model/Enums.cs
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,8 @@ public enum ServiceType
ApiService = 0,
BaiduService,
BingService,
OpenAIService
OpenAIService,
GeminiService,
}

/// <summary>
Expand All @@ -118,6 +119,7 @@ public enum IconType
Youdao,
Bing,
OpenAI,
Gemini,
}

/// <summary>
Expand Down
Binary file added STranslate.Style/Resources/gemini.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 3 additions & 0 deletions STranslate.Style/STranslate.Style.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
<Resource Include="Resources\forbidden.ico">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Resources\gemini.png">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
<Resource Include="Resources\google.ico">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</Resource>
Expand Down
1 change: 1 addition & 0 deletions STranslate.Style/Styles/IconStyle.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@
<BitmapImage x:Key="Youdao" UriSource="pack://application:,,,/STranslate.Style;component/Resources/youdao.png" />
<BitmapImage x:Key="Bing" UriSource="pack://application:,,,/STranslate.Style;component/Resources/bing.png" />
<BitmapImage x:Key="OpenAI" UriSource="pack://application:,,,/STranslate.Style;component/Resources/openai.png" />
<BitmapImage x:Key="Gemini" UriSource="pack://application:,,,/STranslate.Style;component/Resources/gemini.png" />
</ResourceDictionary>
1 change: 1 addition & 0 deletions STranslate/Helper/ConfigHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -309,6 +309,7 @@ JsonSerializer serializer
(int)ServiceType.BaiduService => new TranslatorBaidu(),
(int)ServiceType.BingService => new TranslatorBing(),
(int)ServiceType.OpenAIService => new TranslatorOpenAI(),
(int)ServiceType.GeminiService => new TranslatorGemini(),
//TODO: 新接口需要适配
_ => throw new NotSupportedException($"Unsupported ServiceType: {type}")
};
Expand Down
4 changes: 4 additions & 0 deletions STranslate/ViewModels/InputViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,9 @@ await Parallel.ForEachAsync(
case ServiceType.OpenAIService:
await ServiceHandler.OpenAIHandlerAsync(service, InputContent, sourceStr, targetStr, token);
break;
case ServiceType.GeminiService:
await ServiceHandler.GeminiHandlerAsync(service, InputContent, sourceStr, targetStr, token);
break;
default:
break;
}
Expand Down Expand Up @@ -400,6 +403,7 @@ public class CurrentTranslatorConverter : JsonConverter<ITranslator>
(int)ServiceType.BaiduService => new TranslatorBaidu(),
(int)ServiceType.BingService => new TranslatorBing(),
(int)ServiceType.OpenAIService => new TranslatorOpenAI(),
(int)ServiceType.GeminiService => new TranslatorGemini(),
_ => new TranslatorApi(),
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ JsonSerializer serializer
(int)ServiceType.BaiduService => new TranslatorBaidu(),
(int)ServiceType.BingService => new TranslatorBing(),
(int)ServiceType.OpenAIService => new TranslatorOpenAI(),
(int)ServiceType.GeminiService => new TranslatorGemini(),
//TODO: 新接口需要适配
_ => throw new NotSupportedException($"Unsupported ServiceType: {type}")
};
Expand Down
3 changes: 3 additions & 0 deletions STranslate/ViewModels/Preference/ServiceViewModel.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public ServiceViewModel()
TransServices.Add(new TranslatorBaidu());
TransServices.Add(new TranslatorBing());
TransServices.Add(new TranslatorOpenAI());
TransServices.Add(new TranslatorGemini());

ResetView();
}
Expand Down Expand Up @@ -87,6 +88,7 @@ private void TogglePage(ITranslator service)
ServiceType.BaiduService => string.Format("{0}TextBaiduServicesPage", head),
ServiceType.BingService => string.Format("{0}TextBingServicesPage", head),
ServiceType.OpenAIService => string.Format("{0}TextOpenAIServicesPage", head),
ServiceType.GeminiService => string.Format("{0}TextGeminiServicesPage", head),
_ => string.Format("{0}TextApiServicePage", head)
};

Expand All @@ -111,6 +113,7 @@ private void Add(List<object> list)
TranslatorBaidu baidu => baidu.DeepClone(),
TranslatorBing bing => bing.DeepClone(),
TranslatorOpenAI openAI => openAI.DeepClone(),
TranslatorGemini gemini => gemini.DeepClone(),
_ => throw new InvalidOperationException($"Unsupported service type: {service.GetType().Name}")
});

Expand Down
11 changes: 8 additions & 3 deletions STranslate/ViewModels/Preference/Services/TranslatorBaidu.cs
Original file line number Diff line number Diff line change
Expand Up @@ -126,10 +126,11 @@ public bool KeyHide
}
}
}

[RelayCommand]
private void ShowEncryptInfo(string obj)

private void ShowEncryptInfo(string? obj)
{
if (obj == null) return;

if (obj.Equals(nameof(AppID)))
{
IdHide = !IdHide;
Expand All @@ -140,6 +141,10 @@ private void ShowEncryptInfo(string obj)
}
}

private RelayCommand<string>? showEncryptInfoCommand;
[JsonIgnore]
public IRelayCommand<string> ShowEncryptInfoCommand => showEncryptInfoCommand ??= new RelayCommand<string>(new Action<string?>(ShowEncryptInfo));

#endregion Show/Hide Encrypt Info

public async Task<object> TranslateAsync(object request, CancellationToken token)
Expand Down
9 changes: 7 additions & 2 deletions STranslate/ViewModels/Preference/Services/TranslatorBing.cs
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,10 @@ public bool KeyHide
}
}

[RelayCommand]
private void ShowEncryptInfo(string obj)
private void ShowEncryptInfo(string? obj)
{
if (obj == null) return;

if (obj.Equals(nameof(AppID)))
{
IdHide = !IdHide;
Expand All @@ -144,6 +145,10 @@ private void ShowEncryptInfo(string obj)
}
}

private RelayCommand<string>? showEncryptInfoCommand;
[JsonIgnore]
public IRelayCommand<string> ShowEncryptInfoCommand => showEncryptInfoCommand ??= new RelayCommand<string>(new Action<string?>(ShowEncryptInfo));

#endregion Show/Hide Encrypt Info

public async Task<object> TranslateAsync(object request, CancellationToken token)
Expand Down
198 changes: 198 additions & 0 deletions STranslate/ViewModels/Preference/Services/TranslatorGemini.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,198 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http;
using System.Security.Policy;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using STranslate.Model;
using STranslate.Util;

namespace STranslate.ViewModels.Preference.Services
{
public partial class TranslatorGemini : ObservableObject, ITranslator
{
public TranslatorGemini()
: this(Guid.NewGuid(), "https://generativelanguage.googleapis.com", "Gemini") { }

public TranslatorGemini(
Guid guid,
string url,
string name = "",
IconType icon = IconType.Gemini,
string appID = "",
string appKey = "",
bool isEnabled = true,
ServiceType type = ServiceType.GeminiService
)
{
Identify = guid;
Url = url;
Name = name;
Icon = icon;
AppID = appID;
AppKey = appKey;
IsEnabled = isEnabled;
Type = type;
}

[ObservableProperty]
private Guid _identify = Guid.Empty;

[JsonIgnore]
[ObservableProperty]
private ServiceType _type = 0;

[JsonIgnore]
[ObservableProperty]
public bool _isEnabled = true;

[JsonIgnore]
[ObservableProperty]
private string _name = string.Empty;

[JsonIgnore]
[ObservableProperty]
private IconType _icon = IconType.Gemini;

[JsonIgnore]
[ObservableProperty]
public string _url = string.Empty;

[JsonIgnore]
[ObservableProperty]
public string _AppID = string.Empty;

[JsonIgnore]
[ObservableProperty]
public string _appKey = string.Empty;

[JsonIgnore]
public object _data = string.Empty;

[JsonIgnore]
public object Data
{
get => _data;
set
{
if (_data != value)
{
OnPropertyChanging(nameof(Data));
_data = value;
OnPropertyChanged(nameof(Data));
}
}
}

[JsonIgnore]
public List<IconType> Icons { get; private set; } = Enum.GetValues(typeof(IconType)).OfType<IconType>().ToList();

#region Show/Hide Encrypt Info

[JsonIgnore]
private bool _keyHide = true;

[JsonIgnore]
public bool KeyHide
{
get => _keyHide;
set
{
if (_keyHide != value)
{
OnPropertyChanging(nameof(KeyHide));
_keyHide = value;
OnPropertyChanged(nameof(KeyHide));
}
}
}


private void ShowEncryptInfo() => KeyHide = !KeyHide;

private RelayCommand? showEncryptInfoCommand;
[JsonIgnore]
public IRelayCommand ShowEncryptInfoCommand => showEncryptInfoCommand ??= new RelayCommand(new Action(ShowEncryptInfo));

#endregion Show/Hide Encrypt Info

[Obsolete]
public async Task<object> TranslateAsync(object request, CancellationToken token)
{
try
{
if (string.IsNullOrEmpty(Url) || string.IsNullOrEmpty(AppKey))
throw new Exception("请先完善配置");

if (!Url.EndsWith("completions"))
{
Url = Url.TrimEnd('/') + "/completions";
}

if (request != null)
{
var jsonData = JsonConvert.SerializeObject(request);

// 构建请求
var client = new HttpClient(new SocketsHttpHandler());
var req = new HttpRequestMessage
{
Method = HttpMethod.Post,
RequestUri = new Uri(Url),
Content = new StringContent(jsonData, Encoding.UTF8, "application/json")
};
req.Headers.Add("Authorization", $"Bearer {AppKey}");

// 发送请求
using var response = await client.SendAsync(req, HttpCompletionOption.ResponseHeadersRead, token);
// 获取响应流
using var responseStream = await response.Content.ReadAsStreamAsync(token);
using var reader = new System.IO.StreamReader(responseStream);
// 逐行读取并输出结果
while (!reader.EndOfStream || token.IsCancellationRequested)
{
var line = await reader.ReadLineAsync(token);

if (string.IsNullOrEmpty(line?.Trim()))
continue;

var preprocessString = line.Replace("data:", "").Trim();

// 结束标记
if (preprocessString.Equals("[DONE]"))
break;

// 解析JSON数据
var parsedData = JsonConvert.DeserializeObject<JObject>(preprocessString);

if (parsedData is null)
continue;

// 提取content的值
var contentValue = parsedData["choices"]?.FirstOrDefault()?["delta"]?["content"]?.ToString();

if (string.IsNullOrEmpty(contentValue))
continue;

// 输出
Data += contentValue;
//Debug.Write(contentValue);
}
}
}
catch (Exception ex)
{
Data = ex.Message;
}

return Task.FromResult<string?>(null);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,12 @@ public bool KeyHide
}
}

[RelayCommand]
private void ShowEncryptInfo() => KeyHide = !KeyHide;

private RelayCommand? showEncryptInfoCommand;
[JsonIgnore]
public IRelayCommand ShowEncryptInfoCommand => showEncryptInfoCommand ??= new RelayCommand(new Action(ShowEncryptInfo));

#endregion Show/Hide Encrypt Info

[Obsolete]
Expand Down
Loading

0 comments on commit 9ac9420

Please sign in to comment.