diff --git a/src/main/java/com/star/easydoc/common/Consts.java b/src/main/java/com/star/easydoc/common/Consts.java index cb425b6..88ca369 100644 --- a/src/main/java/com/star/easydoc/common/Consts.java +++ b/src/main/java/com/star/easydoc/common/Consts.java @@ -30,11 +30,11 @@ private Consts() {} public static final Set ENABLE_TRANSLATOR_SET = ImmutableSet.of(Consts.YOUDAO_TRANSLATOR, Consts.BAIDU_TRANSLATOR, Consts.TENCENT_TRANSLATOR, Consts.ALIYUN_TRANSLATOR, Consts.YOUDAO_AI_TRANSLATOR, Consts.MICROSOFT_TRANSLATOR, Consts.MICROSOFT_FREE_TRANSLATOR, Consts.GOOGLE_TRANSLATOR, - Consts.GOOGLE_FREE_TRANSLATOR, Consts.CHATGLM_GPT, Consts.LOCAL_DICTIONARY, Consts.SIMPLE_SPLITTER, - Consts.CLOSE_TRANSLATOR, Consts.CUSTOM_URL); + Consts.GOOGLE_FREE_TRANSLATOR, Consts.CHATGLM_GPT, Consts.OPENAI_GPT, Consts.OPENAI_TRANSLATOR, Consts.LOCAL_DICTIONARY, Consts.SIMPLE_SPLITTER, + Consts.CLOSE_TRANSLATOR, Consts.CUSTOM_URL, Consts.DEEPLX_TRANSLATOR); /** AI翻译集合 */ - public static final Set AI_TRANSLATOR = ImmutableSet.of(Consts.CHATGLM_GPT); + public static final Set AI_TRANSLATOR = ImmutableSet.of(Consts.CHATGLM_GPT, Consts.OPENAI_GPT); /** * 腾讯翻译 @@ -80,6 +80,14 @@ private Consts() {} * 智谱清言 */ public static final String CHATGLM_GPT = "智谱清言"; + /** + * OpenAI API + */ + public static final String OPENAI_GPT = "OpenAI API"; + /** + * OpenAI 翻译(复用 OpenAI 配置,走翻译流程) + */ + public static final String OPENAI_TRANSLATOR = "OpenAI 翻译"; /** * 本地词典 */ @@ -96,4 +104,9 @@ private Consts() {} * 关闭翻译 */ public static final String CLOSE_TRANSLATOR = "关闭(只使用自定义翻译)"; + /** + * DeepLX 翻译 + */ + public static final String DEEPLX_TRANSLATOR = "DeepLX 翻译"; } + diff --git a/src/main/java/com/star/easydoc/config/EasyDocConfig.java b/src/main/java/com/star/easydoc/config/EasyDocConfig.java index eac7e0a..77cc429 100644 --- a/src/main/java/com/star/easydoc/config/EasyDocConfig.java +++ b/src/main/java/com/star/easydoc/config/EasyDocConfig.java @@ -126,6 +126,16 @@ public class EasyDocConfig { * chatglmApiKey */ private String chatGlmApiKey; + /** OpenAI apiKey */ + private String openAiApiKey; + /** OpenAI 模型 */ + private String openAiModel; + /** OpenAI Base URL */ + private String openAiBaseUrl; + /** DeepLX Base URL */ + private String deepLxBaseUrl; + /** DeepLX Token */ + private String deepLxToken; /** * 微软key */ @@ -187,6 +197,12 @@ public void reset() { accessKeySecret = null; youdaoAppKey = null; youdaoAppSecret = null; + chatGlmApiKey = null; + openAiApiKey = null; + openAiModel = null; + openAiBaseUrl = null; + deepLxBaseUrl = null; + deepLxToken = null; wordMap = new TreeMap<>(); projectWordMap = new TreeMap<>(); classTemplateConfig = new TemplateConfig(); @@ -645,6 +661,46 @@ public void setChatGlmApiKey(String chatGlmApiKey) { this.chatGlmApiKey = chatGlmApiKey; } + public String getOpenAiApiKey() { + return openAiApiKey; + } + + public void setOpenAiApiKey(String openAiApiKey) { + this.openAiApiKey = openAiApiKey; + } + + public String getOpenAiModel() { + return openAiModel; + } + + public String getOpenAiBaseUrl() { + return openAiBaseUrl; + } + + public void setOpenAiBaseUrl(String openAiBaseUrl) { + this.openAiBaseUrl = openAiBaseUrl; + } + + public String getDeepLxBaseUrl() { + return deepLxBaseUrl; + } + + public String getDeepLxToken() { + return deepLxToken; + } + + public void setDeepLxToken(String deepLxToken) { + this.deepLxToken = deepLxToken; + } + + public void setDeepLxBaseUrl(String deepLxBaseUrl) { + this.deepLxBaseUrl = deepLxBaseUrl; + } + + public void setOpenAiModel(String openAiModel) { + this.openAiModel = openAiModel; + } + public String getCoverMode() { return coverMode; } diff --git a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/ClassDocGenerator.java b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/ClassDocGenerator.java index 3b74a97..ef9bd96 100644 --- a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/ClassDocGenerator.java +++ b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/ClassDocGenerator.java @@ -77,7 +77,8 @@ private String generateWithAI(PsiElement psiElement) { String prompt; // 定义提示变量 try { // 将资源文件中的文本读取为字符串 - prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), "prompts/chatglm", "class.prompt")); + String folder = Consts.OPENAI_GPT.equals(config.getTranslator()) ? "prompts/openai" : "prompts/chatglm"; + prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), folder, "class.prompt")); } catch (IOException e) { // 如果发生IO异常,则抛出运行时异常 throw new RuntimeException(e); diff --git a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/FieldDocGenerator.java b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/FieldDocGenerator.java index 92b9389..718c763 100644 --- a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/FieldDocGenerator.java +++ b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/FieldDocGenerator.java @@ -79,7 +79,8 @@ public String generate(PsiElement psiElement) { private String generateWithAI(PsiElement psiElement) { String prompt; try { - prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), "prompts/chatglm", "field.prompt")); + String folder = Consts.OPENAI_GPT.equals(config.getTranslator()) ? "prompts/openai" : "prompts/chatglm"; + prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), folder, "field.prompt")); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/MethodDocGenerator.java b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/MethodDocGenerator.java index c007bbc..80ef2cb 100644 --- a/src/main/java/com/star/easydoc/javadoc/service/generator/impl/MethodDocGenerator.java +++ b/src/main/java/com/star/easydoc/javadoc/service/generator/impl/MethodDocGenerator.java @@ -99,7 +99,8 @@ private String getDefaultTemplate(PsiMethod psiMethod) { private String generateWithAI(PsiElement psiElement) { String prompt; try { - prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), "prompts/chatglm", "method.prompt")); + String folder = Consts.OPENAI_GPT.equals(config.getTranslator()) ? "prompts/openai" : "prompts/chatglm"; + prompt = IOUtils.toString(ResourceUtil.getResource(getClass(), folder, "method.prompt")); } catch (IOException e) { throw new RuntimeException(e); } diff --git a/src/main/java/com/star/easydoc/service/gpt/GptService.java b/src/main/java/com/star/easydoc/service/gpt/GptService.java index 910af4f..775fac1 100644 --- a/src/main/java/com/star/easydoc/service/gpt/GptService.java +++ b/src/main/java/com/star/easydoc/service/gpt/GptService.java @@ -7,6 +7,7 @@ import com.star.easydoc.common.Consts; import com.star.easydoc.config.EasyDocConfig; import com.star.easydoc.service.gpt.impl.ChatGlmGptSupplier; +import com.star.easydoc.service.gpt.impl.OpenAiGptSupplier; import org.apache.commons.lang3.StringUtils; /** @@ -34,6 +35,7 @@ public void init(EasyDocConfig config) { } gptSupplierMap = ImmutableMap.builder() .put(Consts.CHATGLM_GPT, new ChatGlmGptSupplier().init(config)) + .put(Consts.OPENAI_GPT, new OpenAiGptSupplier().init(config)) .build(); this.config = config; } diff --git a/src/main/java/com/star/easydoc/service/gpt/impl/OpenAiGptSupplier.java b/src/main/java/com/star/easydoc/service/gpt/impl/OpenAiGptSupplier.java new file mode 100644 index 0000000..3905a2a --- /dev/null +++ b/src/main/java/com/star/easydoc/service/gpt/impl/OpenAiGptSupplier.java @@ -0,0 +1,109 @@ +package com.star.easydoc.service.gpt.impl; + +import com.alibaba.fastjson2.JSON; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.star.easydoc.common.util.HttpUtil; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Map; + +/** + * OpenAI Chat Completions API + * https://api.openai.com/v1/chat/completions + */ +public class OpenAiGptSupplier extends AbstractGptSupplier { + + private static final String DEFAULT_BASE = "https://api.openai.com/v1"; + /** 超时 */ + private static final int TIMEOUT = 30 * 1000; + + @Override + public String chat(String content) { + String apiKey = getConfig().getOpenAiApiKey(); + String model = getConfig().getOpenAiModel(); + if (StringUtils.isBlank(apiKey) || StringUtils.isBlank(model)) { + return StringUtils.EMPTY; + } + + Map headers = Maps.newHashMap(); + headers.put("Authorization", "Bearer " + apiKey); + headers.put("Content-Type", "application/json"); + + Message message = new Message(); + message.setRole("user"); + message.setContent(content); + + OpenAiRequest request = new OpenAiRequest(); + request.setModel(model); + request.setMessages(Lists.newArrayList(message)); + request.setStream(false); + + String base = StringUtils.isNotBlank(getConfig().getOpenAiBaseUrl()) ? getConfig().getOpenAiBaseUrl() : DEFAULT_BASE; + String url = base.endsWith("/") ? (base + "chat/completions") : (base + "/chat/completions"); + String response = HttpUtil.postJson(url, headers, JSON.toJSONString(request), TIMEOUT); + String result = JSON.parseObject(response) + .getJSONArray("choices") + .getJSONObject(0) + .getJSONObject("message") + .getString("content"); + + // 复用 ChatGLM 的返回处理逻辑,提取 /** ... */ + return "/**" + org.apache.commons.lang.StringUtils.substringBeforeLast( + org.apache.commons.lang.StringUtils.substringAfterLast(result, "/**"), "*/") + "*/"; + } + + // --- request/response payloads --- + private static class OpenAiRequest { + private String model; + private List messages; + private Boolean stream; + + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public List getMessages() { + return messages; + } + + public void setMessages(List messages) { + this.messages = messages; + } + + public Boolean getStream() { + return stream; + } + + public void setStream(Boolean stream) { + this.stream = stream; + } + } + + private static class Message { + private String role; + private String content; + + public String getRole() { + return role; + } + + public void setRole(String role) { + this.role = role; + } + + public String getContent() { + return content; + } + + public void setContent(String content) { + this.content = content; + } + } +} + diff --git a/src/main/java/com/star/easydoc/service/translator/TranslatorService.java b/src/main/java/com/star/easydoc/service/translator/TranslatorService.java index f254a52..f879eb6 100644 --- a/src/main/java/com/star/easydoc/service/translator/TranslatorService.java +++ b/src/main/java/com/star/easydoc/service/translator/TranslatorService.java @@ -21,12 +21,14 @@ import com.star.easydoc.service.translator.impl.AliyunTranslator; import com.star.easydoc.service.translator.impl.BaiduTranslator; import com.star.easydoc.service.translator.impl.CustomTranslator; +import com.star.easydoc.service.translator.impl.DeepLXTranslator; import com.star.easydoc.service.translator.impl.GoogleFreeTranslator; import com.star.easydoc.service.translator.impl.GoogleTranslator; import com.star.easydoc.service.translator.impl.JinshanTranslator; import com.star.easydoc.service.translator.impl.LocalTranslator; import com.star.easydoc.service.translator.impl.MicrosoftFreeTranslator; import com.star.easydoc.service.translator.impl.MicrosoftTranslator; +import com.star.easydoc.service.translator.impl.OpenAiTranslator; import com.star.easydoc.service.translator.impl.SimpleSplitterTranslator; import com.star.easydoc.service.translator.impl.TencentTranslator; import com.star.easydoc.service.translator.impl.YoudaoAiTranslator; @@ -68,6 +70,8 @@ public void init(EasyDocConfig config) { .put(Consts.MICROSOFT_FREE_TRANSLATOR, new MicrosoftFreeTranslator().init(config)) .put(Consts.GOOGLE_TRANSLATOR, new GoogleTranslator().init(config)) .put(Consts.GOOGLE_FREE_TRANSLATOR, new GoogleFreeTranslator().init(config)) + .put(Consts.DEEPLX_TRANSLATOR, new DeepLXTranslator().init(config)) + .put(Consts.OPENAI_TRANSLATOR, new OpenAiTranslator().init(config)) .put(Consts.SIMPLE_SPLITTER, new SimpleSplitterTranslator().init(config)) .put(Consts.LOCAL_DICTIONARY, new LocalTranslator().init(config)) .put(Consts.CUSTOM_URL, new CustomTranslator().init(config)) diff --git a/src/main/java/com/star/easydoc/service/translator/impl/DeepLXTranslator.java b/src/main/java/com/star/easydoc/service/translator/impl/DeepLXTranslator.java new file mode 100644 index 0000000..66f2b57 --- /dev/null +++ b/src/main/java/com/star/easydoc/service/translator/impl/DeepLXTranslator.java @@ -0,0 +1,67 @@ +package com.star.easydoc.service.translator.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.google.common.collect.Maps; +import com.intellij.openapi.diagnostic.Logger; +import com.star.easydoc.common.util.HttpUtil; +import org.apache.commons.lang3.StringUtils; + +import java.util.Map; + +/** + * DeepLX 翻译 + * 文档参考: https://deeplx.owo.network/endpoints/free.html + * + * 使用说明: + * - 默认使用公共免费端点:https://deeplx.owo.network/translate + * - 如需自建或替换,请在设置中为“DeepLX 翻译”配置 DeepLX 地址(独立字段,不再复用自定义HTTP) + * - 如有鉴权令牌,可在设置中“密钥”处填写(将作为 Authorization: Bearer ${token} 发送) + */ +public class DeepLXTranslator extends AbstractTranslator { + + private static final Logger LOGGER = Logger.getInstance(DeepLXTranslator.class); + private static final String DEFAULT_URL = "https://deeplx.owo.network/translate"; + + @Override + protected String translateCh2En(String text) { + return translate("ZH", "EN", text); + } + + @Override + protected String translateEn2Ch(String text) { + return translate("EN", "ZH", text); + } + + private String translate(String from, String to, String query) { + String cfg = getConfig().getDeepLxBaseUrl(); + String url = StringUtils.isBlank(cfg) ? DEFAULT_URL : cfg; + String json = null; + try { + Map headers = Maps.newHashMap(); + if (StringUtils.isNotBlank(getConfig().getDeepLxToken())) { + headers.put("Authorization", "Bearer " + getConfig().getDeepLxToken()); + } + JSONObject body = new JSONObject(); + body.put("text", query); + body.put("source_lang", from); + body.put("target_lang", to); + + json = HttpUtil.postJson(url, headers, JSON.toJSONString(body), getConfig().getTimeout()); + JSONObject resp = JSON.parseObject(json); + if (resp == null) { + return StringUtils.EMPTY; + } + Integer code = resp.getInteger("code"); + if (code != null && code == 200) { + return StringUtils.defaultString(resp.getString("data")); + } + LOGGER.error(String.format("deeplx translate error:url:%s,response:%s", url, json)); + return StringUtils.EMPTY; + } catch (Exception e) { + LOGGER.error(String.format("deeplx translate error:url:%s,response:%s", url, json), e); + return StringUtils.EMPTY; + } + } +} + diff --git a/src/main/java/com/star/easydoc/service/translator/impl/OpenAiTranslator.java b/src/main/java/com/star/easydoc/service/translator/impl/OpenAiTranslator.java new file mode 100644 index 0000000..fb44272 --- /dev/null +++ b/src/main/java/com/star/easydoc/service/translator/impl/OpenAiTranslator.java @@ -0,0 +1,105 @@ +package com.star.easydoc.service.translator.impl; + +import com.alibaba.fastjson2.JSON; +import com.alibaba.fastjson2.JSONObject; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import com.intellij.openapi.diagnostic.Logger; +import com.star.easydoc.common.util.HttpUtil; +import com.star.easydoc.service.translator.impl.AbstractTranslator; +import org.apache.commons.lang3.StringUtils; + +import java.util.List; +import java.util.Map; + +/** + * OpenAI 翻译器(复用 OpenAI 配置,走翻译流程) + * 使用 Chat Completions,将输入作为 user 消息,并使用 system 提示强约束只返回纯译文。 + */ +public class OpenAiTranslator extends AbstractTranslator { + + private static final Logger LOGGER = Logger.getInstance(OpenAiTranslator.class); + private static final String DEFAULT_BASE = "https://api.openai.com/v1"; + private static final int TIMEOUT = 30 * 1000; + + @Override + protected String translateCh2En(String text) { + return translate(text, true); + } + + @Override + protected String translateEn2Ch(String text) { + return translate(text, false); + } + + private String translate(String text, boolean zh2en) { + String apiKey = getConfig().getOpenAiApiKey(); + String model = getConfig().getOpenAiModel(); + if (StringUtils.isBlank(apiKey) || StringUtils.isBlank(model)) { + return StringUtils.EMPTY; + } + Map headers = Maps.newHashMap(); + headers.put("Authorization", "Bearer " + apiKey); + headers.put("Content-Type", "application/json"); + + // system + user + Message system = new Message(); + system.setRole("system"); + system.setContent(zh2en ? + "You are a translation engine. Translate Chinese to concise English. Return translation only without explanations." : + "You are a translation engine. Translate English to concise Chinese. Return translation only without explanations."); + Message user = new Message(); + user.setRole("user"); + user.setContent(text); + + OpenAiRequest request = new OpenAiRequest(); + request.setModel(model); + request.setMessages(Lists.newArrayList(system, user)); + request.setStream(false); + request.setTemperature(0.0); + + String base = StringUtils.isNotBlank(getConfig().getOpenAiBaseUrl()) ? getConfig().getOpenAiBaseUrl() : DEFAULT_BASE; + String url = base.endsWith("/") ? (base + "chat/completions") : (base + "/chat/completions"); + + String json = null; + try { + json = HttpUtil.postJson(url, headers, JSON.toJSONString(request), TIMEOUT); + JSONObject obj = JSON.parseObject(json); + if (obj == null) { + return StringUtils.EMPTY; + } + String result = obj.getJSONArray("choices").getJSONObject(0).getJSONObject("message").getString("content"); + return StringUtils.defaultString(result).trim(); + } catch (Exception e) { + LOGGER.error("openai translate error:url:" + url + ",response:" + json, e); + return StringUtils.EMPTY; + } + } + + // --- request payloads --- + private static class OpenAiRequest { + private String model; + private List messages; + private Boolean stream; + private Double temperature; + + public String getModel() { return model; } + public void setModel(String model) { this.model = model; } + public List getMessages() { return messages; } + public void setMessages(List messages) { this.messages = messages; } + public Boolean getStream() { return stream; } + public void setStream(Boolean stream) { this.stream = stream; } + public Double getTemperature() { return temperature; } + public void setTemperature(Double temperature) { this.temperature = temperature; } + } + + private static class Message { + private String role; + private String content; + public String getRole() { return role; } + public void setRole(String role) { this.role = role; } + public String getContent() { return content; } + public void setContent(String content) { this.content = content; } + } +} + diff --git a/src/main/java/com/star/easydoc/view/settings/CommonSettingsConfigurable.java b/src/main/java/com/star/easydoc/view/settings/CommonSettingsConfigurable.java index 161388e..2b853e7 100644 --- a/src/main/java/com/star/easydoc/view/settings/CommonSettingsConfigurable.java +++ b/src/main/java/com/star/easydoc/view/settings/CommonSettingsConfigurable.java @@ -86,6 +86,21 @@ public boolean isModified() { if (!Objects.equals(config.getChatGlmApiKey(), view.getChatGlmApiKeyTextField().getText())) { return true; } + if (!Objects.equals(config.getOpenAiApiKey(), view.getOpenAiApiKeyTextField().getText())) { + return true; + } + if (!Objects.equals(config.getOpenAiModel(), view.getOpenAiModelTextField().getText())) { + return true; + } + if (!Objects.equals(config.getOpenAiBaseUrl(), view.getOpenAiBaseUrlTextField().getText())) { + return true; + } + if (!Objects.equals(config.getDeepLxBaseUrl(), view.getDeepLxBaseUrlTextField().getText())) { + return true; + } + if (!Objects.equals(config.getDeepLxToken(), view.getDeepLxTokenTextField().getText())) { + return true; + } if (!Objects.equals(config.getCustomUrl(), view.getCustomUrlTextField().getText())) { return true; } @@ -107,6 +122,11 @@ public void apply() throws ConfigurationException { config.setMicrosoftRegion(view.getMicrosoftRegionTextField().getText()); config.setGoogleKey(view.getGoogleKeyTextField().getText()); config.setChatGlmApiKey(view.getChatGlmApiKeyTextField().getText()); + config.setOpenAiApiKey(view.getOpenAiApiKeyTextField().getText()); + config.setOpenAiModel(view.getOpenAiModelTextField().getText()); + config.setOpenAiBaseUrl(StringUtils.strip(view.getOpenAiBaseUrlTextField().getText())); + config.setDeepLxBaseUrl(StringUtils.strip(view.getDeepLxBaseUrlTextField().getText())); + config.setDeepLxToken(StringUtils.strip(view.getDeepLxTokenTextField().getText())); config.setCustomUrl(StringUtils.strip(view.getCustomUrlTextField().getText())); if (config.getWordMap() == null) { config.setWordMap(new TreeMap<>()); @@ -165,6 +185,17 @@ public void apply() throws ConfigurationException { throw new ConfigurationException("apiKey不能为空"); } } + if (Consts.OPENAI_GPT.equals(config.getTranslator()) || Consts.OPENAI_TRANSLATOR.equals(config.getTranslator())) { + if (StringUtils.isBlank(config.getOpenAiApiKey())) { + throw new ConfigurationException("OpenAI apiKey不能为空"); + } + if (StringUtils.isBlank(config.getOpenAiModel())) { + throw new ConfigurationException("OpenAI 模型不能为空"); + } + if (StringUtils.isNotBlank(config.getOpenAiBaseUrl()) && !config.getOpenAiBaseUrl().startsWith("http")) { + throw new ConfigurationException("OpenAI Base URL 只支持 http 或 https"); + } + } if (Consts.CUSTOM_URL.equals(config.getTranslator())) { if (StringUtils.isBlank(config.getCustomUrl())) { throw new ConfigurationException("自定义地址不能为空"); @@ -182,6 +213,11 @@ public void apply() throws ConfigurationException { throw new ConfigurationException("自定义地址需要包含{query}占位符,请查看说明文档"); } } + if (Consts.DEEPLX_TRANSLATOR.equals(config.getTranslator())) { + if (StringUtils.isNotBlank(config.getDeepLxBaseUrl()) && !config.getDeepLxBaseUrl().startsWith("http")) { + throw new ConfigurationException("DeepLX 地址只支持 http 或 https"); + } + } if (StringUtils.isBlank(view.getTimeoutTextField().getText()) || !view.getTimeoutTextField().getText().matches("^[1-9][0-9]*$")) { throw new ConfigurationException("超时时间必须为数字"); diff --git a/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.form b/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.form index 90de186..7507fbd 100644 --- a/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.form +++ b/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.form @@ -32,7 +32,7 @@ - + @@ -64,6 +64,9 @@ + + + @@ -215,7 +218,7 @@ - + @@ -248,7 +251,7 @@ - + @@ -387,12 +390,94 @@ - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.java b/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.java index f1704eb..bf2f19c 100644 --- a/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.java +++ b/src/main/java/com/star/easydoc/view/settings/CommonSettingsView.java @@ -82,6 +82,18 @@ public class CommonSettingsView { private JLabel googleKeyLabel; private JTextField chatGlmApiKeyTextField; private JLabel chatGlmApiKeyLabel; + private JTextField openAiApiKeyTextField; + private JLabel openAiApiKeyLabel; + private JTextField openAiModelTextField; + private JLabel openAiModelLabel; + private JTextField openAiBaseUrlTextField; + private JLabel openAiBaseUrlLabel; + + private JTextField deepLxBaseUrlTextField; + private JLabel deepLxBaseUrlLabel; + private JTextField deepLxTokenTextField; + private JLabel deepLxTokenLabel; + private JTextField microsoftRegionTextField; private JLabel microsoftRegionLabel; private JTextField timeoutTextField; @@ -224,7 +236,12 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); appIdTextField.setVisible(true); tokenTextField.setVisible(true); @@ -238,7 +255,12 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.TENCENT_TRANSLATOR.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -253,7 +275,11 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); appIdTextField.setVisible(false); tokenTextField.setVisible(false); @@ -267,7 +293,11 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.ALIYUN_TRANSLATOR.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -282,7 +312,12 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); appIdTextField.setVisible(false); tokenTextField.setVisible(false); @@ -296,7 +331,12 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.YOUDAO_AI_TRANSLATOR.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -311,7 +351,12 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); appIdTextField.setVisible(false); tokenTextField.setVisible(false); @@ -325,7 +370,12 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.MICROSOFT_TRANSLATOR.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -340,6 +390,7 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(true); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); appIdTextField.setVisible(false); @@ -354,7 +405,9 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(true); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.GOOGLE_TRANSLATOR.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -369,6 +422,9 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(true); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); appIdTextField.setVisible(false); @@ -383,7 +439,11 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(true); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.CHATGLM_GPT.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -397,6 +457,9 @@ private void setVisible(Object selectedItem) { microsoftKeyLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(true); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); appIdTextField.setVisible(false); @@ -410,7 +473,92 @@ private void setVisible(Object selectedItem) { microsoftKeyTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(true); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + customUrlHelpButton.setVisible(false); + } else if (Consts.OPENAI_GPT.equals(selectedItem)) { + appIdLabel.setVisible(false); + tokenLabel.setVisible(false); + secretIdLabel.setVisible(false); + secretKeyLabel.setVisible(false); + accessKeyIdLabel.setVisible(false); + accessKeySecretLabel.setVisible(false); + youdaoAppKeyLabel.setVisible(false); + youdaoAppSecretLabel.setVisible(false); + microsoftKeyLabel.setVisible(false); + microsoftRegionLabel.setVisible(false); + googleKeyLabel.setVisible(false); + chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(true); + openAiModelLabel.setVisible(true); + openAiBaseUrlLabel.setVisible(true); + customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); + + + appIdTextField.setVisible(false); + tokenTextField.setVisible(false); + secretIdTextField.setVisible(false); + secretKeyTextField.setVisible(false); + accessKeyIdTextField.setVisible(false); + accessKeySecretTextField.setVisible(false); + youdaoAppKeyTextField.setVisible(false); + youdaoAppSecretTextField.setVisible(false); + microsoftKeyTextField.setVisible(false); + microsoftRegionTextField.setVisible(false); + googleKeyTextField.setVisible(false); + chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(true); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); + + openAiModelTextField.setVisible(true); + openAiBaseUrlTextField.setVisible(true); + customUrlTextField.setVisible(false); + customUrlHelpButton.setVisible(false); + } else if (Consts.OPENAI_TRANSLATOR.equals(selectedItem)) { + // 复用 OpenAI 配置,显示三项 + appIdLabel.setVisible(false); + tokenLabel.setVisible(false); + secretIdLabel.setVisible(false); + secretKeyLabel.setVisible(false); + accessKeyIdLabel.setVisible(false); + accessKeySecretLabel.setVisible(false); + youdaoAppKeyLabel.setVisible(false); + youdaoAppSecretLabel.setVisible(false); + microsoftKeyLabel.setVisible(false); + microsoftRegionLabel.setVisible(false); + googleKeyLabel.setVisible(false); + chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(true); + openAiModelLabel.setVisible(true); + openAiBaseUrlLabel.setVisible(true); + customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); + + appIdTextField.setVisible(false); + tokenTextField.setVisible(false); + secretIdTextField.setVisible(false); + secretKeyTextField.setVisible(false); + accessKeyIdTextField.setVisible(false); + accessKeySecretTextField.setVisible(false); + youdaoAppKeyTextField.setVisible(false); + youdaoAppSecretTextField.setVisible(false); + microsoftKeyTextField.setVisible(false); + microsoftRegionTextField.setVisible(false); + googleKeyTextField.setVisible(false); + chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(true); + openAiModelTextField.setVisible(true); + openAiBaseUrlTextField.setVisible(true); + customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(false); } else if (Consts.CUSTOM_URL.equals(selectedItem)) { appIdLabel.setVisible(false); @@ -424,7 +572,12 @@ private void setVisible(Object selectedItem) { microsoftKeyLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(true); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); appIdTextField.setVisible(false); tokenTextField.setVisible(false); @@ -437,8 +590,52 @@ private void setVisible(Object selectedItem) { microsoftKeyTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(true); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(true); + } else if (Consts.DEEPLX_TRANSLATOR.equals(selectedItem)) { + appIdLabel.setVisible(false); + tokenLabel.setVisible(false); + secretIdLabel.setVisible(false); + secretKeyLabel.setVisible(false); + accessKeyIdLabel.setVisible(false); + accessKeySecretLabel.setVisible(false); + youdaoAppKeyLabel.setVisible(false); + youdaoAppSecretLabel.setVisible(false); + microsoftKeyLabel.setVisible(false); + microsoftRegionLabel.setVisible(false); + googleKeyLabel.setVisible(false); + chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); + customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(true); + deepLxTokenLabel.setVisible(true); + + appIdTextField.setVisible(false); + tokenTextField.setVisible(false); + secretIdTextField.setVisible(false); + secretKeyTextField.setVisible(false); + accessKeyIdTextField.setVisible(false); + accessKeySecretTextField.setVisible(false); + youdaoAppKeyTextField.setVisible(false); + youdaoAppSecretTextField.setVisible(false); + microsoftKeyTextField.setVisible(false); + microsoftRegionTextField.setVisible(false); + googleKeyTextField.setVisible(false); + chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); + customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(true); + deepLxTokenTextField.setVisible(true); + customUrlHelpButton.setVisible(false); } else { appIdLabel.setVisible(false); tokenLabel.setVisible(false); @@ -452,7 +649,12 @@ private void setVisible(Object selectedItem) { microsoftRegionLabel.setVisible(false); googleKeyLabel.setVisible(false); chatGlmApiKeyLabel.setVisible(false); + openAiApiKeyLabel.setVisible(false); + openAiModelLabel.setVisible(false); + openAiBaseUrlLabel.setVisible(false); customUrlLabel.setVisible(false); + deepLxBaseUrlLabel.setVisible(false); + deepLxTokenLabel.setVisible(false); appIdTextField.setVisible(false); tokenTextField.setVisible(false); @@ -466,7 +668,12 @@ private void setVisible(Object selectedItem) { microsoftRegionTextField.setVisible(false); googleKeyTextField.setVisible(false); chatGlmApiKeyTextField.setVisible(false); + openAiApiKeyTextField.setVisible(false); + openAiModelTextField.setVisible(false); + openAiBaseUrlTextField.setVisible(false); customUrlTextField.setVisible(false); + deepLxBaseUrlTextField.setVisible(false); + deepLxTokenTextField.setVisible(false); customUrlHelpButton.setVisible(false); } } @@ -573,6 +780,12 @@ public void refresh() { setMicrosoftRegionTextField(config.getMicrosoftRegion()); setGoogleKeyTextField(config.getGoogleKey()); setChatGlmApiKeyTextField(config.getChatGlmApiKey()); + setOpenAiApiKeyTextField(config.getOpenAiApiKey()); + setOpenAiModelTextField(config.getOpenAiModel()); + setOpenAiBaseUrlTextField(config.getOpenAiBaseUrl()); + setDeepLxBaseUrlTextField(config.getDeepLxBaseUrl()); + setDeepLxTokenTextField(config.getDeepLxToken()); + setCustomUrlTextField(config.getCustomUrl()); refreshWordMap(); projectList.clearSelection(); @@ -720,6 +933,30 @@ public void setChatGlmApiKeyTextField(String apiKey) { this.chatGlmApiKeyTextField.setText(apiKey); } + public JTextField getOpenAiApiKeyTextField() { + return openAiApiKeyTextField; + } + + public void setOpenAiApiKeyTextField(String apiKey) { + this.openAiApiKeyTextField.setText(apiKey); + } + + public JTextField getOpenAiModelTextField() { + return openAiModelTextField; + } + + public void setOpenAiModelTextField(String model) { + this.openAiModelTextField.setText(model); + } + public JTextField getOpenAiBaseUrlTextField() { + return openAiBaseUrlTextField; + } + + public void setOpenAiBaseUrlTextField(String baseUrl) { + this.openAiBaseUrlTextField.setText(baseUrl); + } + + public JTextField getTimeoutTextField() { return timeoutTextField; } @@ -735,4 +972,21 @@ public JTextField getCustomUrlTextField() { public void setCustomUrlTextField(String customUrl) { this.customUrlTextField.setText(customUrl); } + + public JTextField getDeepLxBaseUrlTextField() { + return deepLxBaseUrlTextField; + } + + public void setDeepLxBaseUrlTextField(String url) { + this.deepLxBaseUrlTextField.setText(url); + } + + public JTextField getDeepLxTokenTextField() { + return deepLxTokenTextField; + } + + public void setDeepLxTokenTextField(String token) { + this.deepLxTokenTextField.setText(token); + } } + diff --git a/src/main/resources/prompts/openai/class.prompt b/src/main/resources/prompts/openai/class.prompt new file mode 100644 index 0000000..b8cb051 --- /dev/null +++ b/src/main/resources/prompts/openai/class.prompt @@ -0,0 +1,31 @@ +你是一名高级java研发工程师,对代码质量有着严苛的要求。 +接下来我将要给你一份代码,内容是一个类,你需要返回这段代码的符合javadoc标准规范的类上的javadoc注释。 + +请注意 +- 注释是中文 +- javadoc注释是以/**开始,以*/结束的,所以你的回答也必须是以/**开始,以*/结束,不要包含其它的内容。 +- 不要包含除注释之外的内容 +- 不要返回你建议的内容,只返回符合javadoc标准规范的类上的javadoc注释 +- 不要返回不确定的信息 +- 注释尽量简洁明了 +- 作者是 {author} +- 当前时间是 {date} +例如: +给定代码: +public class Test { + public void test() { + System.out.println("Hello World!"); + } +} +你需要返回: +/** + * 测试类:用于测试 + * + * @author 作者 + * @date 2024/04/29 + */ + +下面是代码 + +{code} + diff --git a/src/main/resources/prompts/openai/field.prompt b/src/main/resources/prompts/openai/field.prompt new file mode 100644 index 0000000..dbb23e3 --- /dev/null +++ b/src/main/resources/prompts/openai/field.prompt @@ -0,0 +1,21 @@ +你是一名高级java研发工程师,对代码质量有着严苛的要求。 +接下来我将要给你一份代码,内容是一个属性变量,你需要返回这段代码的符合javadoc标准规范的属性上的javadoc注释。 + +请注意 +- 注释是中文 +- javadoc注释是以/**开始,以*/结束的,所以你的回答也必须是以/**开始,以*/结束,不要包含其它的内容。 +- 不要包含除注释之外的内容 +- 不要返回你建议的内容,只返回javadoc注释 +- 不要返回不确定的信息 +- 注释尽量简洁明了 +例如: +给定代码: +private String name; + +你需要返回: +/** 名称 */ + +下面是代码 + +{code} + diff --git a/src/main/resources/prompts/openai/method.prompt b/src/main/resources/prompts/openai/method.prompt new file mode 100644 index 0000000..d415915 --- /dev/null +++ b/src/main/resources/prompts/openai/method.prompt @@ -0,0 +1,32 @@ +你是一名高级java研发工程师,对代码质量有着严苛的要求。 +接下来我将要给你一份代码,内容是一个方法,你需要返回这段代码的符合javadoc标准规范的方法上的javadoc注释。 + +请注意 +- 注释是中文 +- javadoc注释是以/**开始,以*/结束的,所以你的回答也必须是以/**开始,以*/结束,不要包含其它的内容。 +- 不要包含除注释之外的内容 +- 不要返回你建议的内容,只返回javadoc注释 +- 不要返回不确定的信息 +- 注释尽量简洁明了 +例如: +给定代码: +public int add(Integer a, Integer b) throws IllegalArgumentException { + if (a == null || b == null) { + throw new IllegalArgumentException("参数不能为空"); + } + return a + b; +} +你需要返回: +/** + * add方法,用于求和 + * + * @param a 第一个参数 + * @param b 第二个参数 + * @return 两个参数的和 + * @throws IllegalArgumentException 参数为空时抛出异常 + */ + +下面是代码 + +{code} +