diff --git a/SubtitleEdit.sln.DotSettings b/SubtitleEdit.sln.DotSettings
index 61e5bb287..1a607200a 100644
--- a/SubtitleEdit.sln.DotSettings
+++ b/SubtitleEdit.sln.DotSettings
@@ -32,6 +32,7 @@
True
True
True
+ True
True
True
True
diff --git a/src/libse/AutoTranslate/ChatGptTranslate.cs b/src/libse/AutoTranslate/ChatGptTranslate.cs
index fa8511f8a..ee471e1f5 100644
--- a/src/libse/AutoTranslate/ChatGptTranslate.cs
+++ b/src/libse/AutoTranslate/ChatGptTranslate.cs
@@ -76,7 +76,7 @@ namespace Nikse.SubtitleEdit.Core.AutoTranslate
var model = Configuration.Settings.Tools.ChatGptModel;
if (string.IsNullOrEmpty(model))
{
- model = "gpt-4o-mini";
+ model = Models[0];
Configuration.Settings.Tools.ChatGptModel = model;
}
diff --git a/src/libse/AutoTranslate/GroqTranslate.cs b/src/libse/AutoTranslate/GroqTranslate.cs
new file mode 100644
index 000000000..551734562
--- /dev/null
+++ b/src/libse/AutoTranslate/GroqTranslate.cs
@@ -0,0 +1,120 @@
+using Nikse.SubtitleEdit.Core.Common;
+using Nikse.SubtitleEdit.Core.SubtitleFormats;
+using Nikse.SubtitleEdit.Core.Translate;
+using System;
+using System.Collections.Generic;
+using System.Net.Http;
+using System.Net.Http.Headers;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+using Nikse.SubtitleEdit.Core.Settings;
+
+namespace Nikse.SubtitleEdit.Core.AutoTranslate
+{
+ public class GroqTranslate : IAutoTranslator
+ {
+ private HttpClient _httpClient;
+
+ public static string StaticName { get; set; } = "Groq";
+ public string Name => StaticName;
+ public string Url => "https://groq.com/";
+ public string Error { get; set; }
+ public int MaxCharacters => 1500;
+
+ ///
+ /// See https://console.groq.com/docs/models
+ ///
+ public static string[] Models => new[]
+ {
+ "llama3-8b-8192",
+ "llama3-70b-8192",
+ "llama3-groq-8b-8192-tool-use-preview",
+ "llama3-groq-70b-8192-tool-use-preview",
+ "mixtral-8x7b-32768",
+ "gemma-7b-it",
+ "gemma2-9b-it",
+ };
+
+ public void Initialize()
+ {
+ _httpClient?.Dispose();
+ _httpClient = new HttpClient();
+ _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Content-Type", "application/json");
+ _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("accept", "application/json");
+ _httpClient.BaseAddress = new Uri(Configuration.Settings.Tools.GroqUrl.TrimEnd('/'));
+ _httpClient.Timeout = TimeSpan.FromMinutes(15);
+
+ if (!string.IsNullOrEmpty(Configuration.Settings.Tools.GroqApiKey))
+ {
+ _httpClient.DefaultRequestHeaders.TryAddWithoutValidation("Authorization", "Bearer " + Configuration.Settings.Tools.GroqApiKey);
+ }
+ }
+
+ public List GetSupportedSourceLanguages()
+ {
+ return ListLanguages();
+ }
+
+ public List GetSupportedTargetLanguages()
+ {
+ return ListLanguages();
+ }
+
+ //curl -X POST "https://api.groq.com/openai/v1/chat/completions" \
+ //-H "Authorization: Bearer $GROQ_API_KEY" \
+ //-H "Content-Type: application/json" \
+ //-d '{"messages": [{"role": "user", "content": "Explain the importance of fast language models"}], "model": "llama3-8b-8192"}
+
+ public async Task Translate(string text, string sourceLanguageCode, string targetLanguageCode, CancellationToken cancellationToken)
+ {
+ var model = Configuration.Settings.Tools.GroqModel;
+ if (string.IsNullOrEmpty(model))
+ {
+ model = Models[0];
+ Configuration.Settings.Tools.GroqModel = model;
+ }
+
+ if (string.IsNullOrEmpty(Configuration.Settings.Tools.GroqPrompt))
+ {
+ Configuration.Settings.Tools.GroqPrompt = new ToolsSettings().GroqPrompt;
+ }
+ var prompt = string.Format(Configuration.Settings.Tools.GroqPrompt, sourceLanguageCode, targetLanguageCode);
+ var input = "{\"model\": \"" + model + "\",\"messages\": [{ \"role\": \"user\", \"content\": \"" + prompt + "\\n\\n" + Json.EncodeJsonText(text.Trim()) + "\" }]}";
+ var content = new StringContent(input, Encoding.UTF8);
+ content.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json");
+ var result = await _httpClient.PostAsync(string.Empty, content, cancellationToken);
+ var bytes = await result.Content.ReadAsByteArrayAsync();
+ var json = Encoding.UTF8.GetString(bytes).Trim();
+ if (!result.IsSuccessStatusCode)
+ {
+ Error = json;
+ SeLogger.Error("Groq Translate failed calling API: Status code=" + result.StatusCode + Environment.NewLine + json);
+ }
+
+ result.EnsureSuccessStatusCode();
+
+ var parser = new SeJsonParser();
+ var resultText = parser.GetFirstObject(json, "content");
+ if (resultText == null)
+ {
+ return string.Empty;
+ }
+
+ var outputText = Json.DecodeJsonText(resultText).Trim();
+ if (outputText.StartsWith('"') && outputText.EndsWith('"') && !text.StartsWith('"'))
+ {
+ outputText = outputText.Trim('"').Trim();
+ }
+
+ outputText = ChatGptTranslate.FixNewLines(outputText);
+ outputText = ChatGptTranslate.RemovePreamble(text, outputText);
+ return outputText.Trim();
+ }
+
+ public static List ListLanguages()
+ {
+ return ChatGptTranslate.ListLanguages();
+ }
+ }
+}
diff --git a/src/libse/Settings/Settings.cs b/src/libse/Settings/Settings.cs
index a91dc6c62..129e8739b 100644
--- a/src/libse/Settings/Settings.cs
+++ b/src/libse/Settings/Settings.cs
@@ -2186,6 +2186,30 @@ namespace Nikse.SubtitleEdit.Core.Settings
settings.Tools.ChatGptModel = subNode.InnerText;
}
+ subNode = node.SelectSingleNode("GroqUrl");
+ if (subNode != null)
+ {
+ settings.Tools.GroqUrl = subNode.InnerText;
+ }
+
+ subNode = node.SelectSingleNode("GroqPrompt");
+ if (subNode != null)
+ {
+ settings.Tools.GroqPrompt = subNode.InnerText;
+ }
+
+ subNode = node.SelectSingleNode("GroqApiKey");
+ if (subNode != null)
+ {
+ settings.Tools.GroqApiKey = subNode.InnerText;
+ }
+
+ subNode = node.SelectSingleNode("GroqModel");
+ if (subNode != null)
+ {
+ settings.Tools.GroqModel = subNode.InnerText;
+ }
+
subNode = node.SelectSingleNode("LmStudioApiUrl");
if (subNode != null)
{
@@ -8881,6 +8905,10 @@ namespace Nikse.SubtitleEdit.Core.Settings
textWriter.WriteElementString("ChatGptPrompt", settings.Tools.ChatGptPrompt);
textWriter.WriteElementString("ChatGptApiKey", settings.Tools.ChatGptApiKey);
textWriter.WriteElementString("ChatGptModel", settings.Tools.ChatGptModel);
+ textWriter.WriteElementString("GroqUrl", settings.Tools.GroqUrl);
+ textWriter.WriteElementString("GroqPrompt", settings.Tools.GroqPrompt);
+ textWriter.WriteElementString("GroqKey", settings.Tools.GroqApiKey);
+ textWriter.WriteElementString("GroqModel", settings.Tools.GroqModel);
textWriter.WriteElementString("LmStudioApiUrl", settings.Tools.LmStudioApiUrl);
textWriter.WriteElementString("LmStudioModel", settings.Tools.LmStudioModel);
textWriter.WriteElementString("LmStudioPrompt", settings.Tools.LmStudioPrompt);
diff --git a/src/libse/Settings/ToolsSettings.cs b/src/libse/Settings/ToolsSettings.cs
index c3791b02e..29d572398 100644
--- a/src/libse/Settings/ToolsSettings.cs
+++ b/src/libse/Settings/ToolsSettings.cs
@@ -70,6 +70,10 @@ namespace Nikse.SubtitleEdit.Core.Settings
public string ChatGptPrompt { get; set; }
public string ChatGptApiKey { get; set; }
public string ChatGptModel { get; set; }
+ public string GroqUrl { get; set; }
+ public string GroqPrompt { get; set; }
+ public string GroqApiKey { get; set; }
+ public string GroqModel { get; set; }
public string LmStudioApiUrl { get; set; }
public string LmStudioModel { get; set; }
public string LmStudioPrompt { get; set; }