From 2f335a9d466cb47d1f438e6164637d2496ce2f71 Mon Sep 17 00:00:00 2001 From: Pylogmon Date: Thu, 18 May 2023 10:17:26 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0Azure=20OpenAI=20Serv?= =?UTF-8?q?ice=E6=94=AF=E6=8C=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/interfaces/openai.js | 47 +++++++++++++------ src/interfaces/openai_code.js | 36 ++++++++++---- src/interfaces/openai_polish.js | 35 ++++++++++---- src/interfaces/openai_summary.js | 35 ++++++++++---- src/windows/Config/index.jsx | 3 ++ .../Config/pages/InterfaceConfig/index.jsx | 20 +++++++- 6 files changed, 130 insertions(+), 46 deletions(-) diff --git a/src/interfaces/openai.js b/src/interfaces/openai.js index 6b5de18198..d8e7d800f0 100644 --- a/src/interfaces/openai.js +++ b/src/interfaces/openai.js @@ -18,9 +18,14 @@ export const info = { needs: [ { config_key: 'openai_domain', - place_hold: 'api.openai.com', + place_hold: 'api.openai.com(不要加协议头,使用OpenAI官方api此项留空即可)', display_name: '自定义域名', }, + { + config_key: 'openai_path', + place_hold: '/v1/chat/completions(一般不需要改,留空即可,Azure用户根据自己情况修改)', + display_name: '请求路径', + }, { config_key: 'openai_apikey', place_hold: '', @@ -41,26 +46,35 @@ export async function translate(text, from, to, setText) { if (domain == '') { domain = 'api.openai.com'; } + if (domain.startsWith('http')) { + domain = domain.replace('https://', '').replace('http://', ''); + } + let path = get('openai_path') ?? '/v1/chat/completions'; + if (path == '') { + path = '/v1/chat/completions'; + } const apikey = get('openai_apikey') ?? ''; if (apikey == '') { throw '请先配置apikey'; } - let prompt = get('openai_prompt') ?? ''; - if (prompt == '') { - prompt = - 'You are a professional translation engine, please translate the text into a colloquial, professional, elegant and fluent content, without the style of machine translation. You must only translate the text content, never interpret it.'; + let systemPrompt = get('openai_prompt') ?? ''; + if (systemPrompt == '') { + systemPrompt = 'You are a professional translation engine, please translate the text into a colloquial, professional, elegant and fluent content, without the style of machine translation. You must only translate the text content, never interpret it.'; } + let userPrompt = `If the content is in ${supportLanguage[to]}, then translate into ${supportLanguage[get('second_language') ?? 'en']}. Otherwise, translate into ${supportLanguage[to]}:\n"""\n${text}\n"""`; + const stream = get('openai_stream') ?? false; + const service = get('openai_service') ?? 'openai'; - const headers = { + const headers = service == 'openai' ? { 'Content-Type': 'application/json', Authorization: `Bearer ${apikey}`, - }; - let systemPrompt = prompt; - - let userPrompt = `If the content is in ${supportLanguage[to]}, then translate into ${supportLanguage[get('second_language') ?? 'en']}. Otherwise, translate into ${supportLanguage[to]}:\n"""\n${text}\n"""`; + } : { + 'Content-Type': 'application/json', + Authorization: `api-key: ${apikey}`, + } - const body = { + const body = service == 'openai' ? { model: 'gpt-3.5-turbo', temperature: 0, max_tokens: 1000, @@ -72,10 +86,15 @@ export async function translate(text, from, to, setText) { { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }, ], - }; + } : { + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt }, + ] + } if (stream) { - const res = await window.fetch(`https://${domain}/v1/chat/completions`, { + const res = await window.fetch(`https://${domain}${path}`, { method: 'POST', headers: headers, body: JSON.stringify(body) @@ -123,7 +142,7 @@ export async function translate(text, from, to, setText) { throw 'http请求出错\n' + JSON.stringify(res); } } else { - let res = await fetch(`https://${domain}/v1/chat/completions`, { + let res = await fetch(`https://${domain}${path}`, { method: 'POST', headers: headers, body: { type: 'Json', payload: body }, diff --git a/src/interfaces/openai_code.js b/src/interfaces/openai_code.js index c174cb9b54..adc4dafee3 100644 --- a/src/interfaces/openai_code.js +++ b/src/interfaces/openai_code.js @@ -31,25 +31,36 @@ export async function translate(text, from, to, setText) { if (domain == '') { domain = 'api.openai.com'; } + if (domain.startsWith('http')) { + domain = domain.replace('https://', '').replace('http://', ''); + } + let path = get('openai_path') ?? '/v1/chat/completions'; + if (path == '') { + path = '/v1/chat/completions'; + } const apikey = get('openai_apikey') ?? ''; if (apikey == '') { throw '请先配置apikey'; } - let prompt = get('openai_code_prompt') ?? ''; - if (prompt == '') { - prompt = + let systemPrompt = get('openai_code_prompt') ?? ''; + if (systemPrompt == '') { + systemPrompt = 'You are a code explanation engine, you can only explain the code, do not interpret or translate it. Also, please report any bugs you find in the code to the author of the code.'; } + let userPrompt = `Explain the following code in ${supportLanguage[to]}:\n"""\n${text}\n"""`; + const stream = get('openai_stream') ?? false; - const headers = { + const service = get('openai_service') ?? 'openai'; + + const headers = service == 'openai' ? { 'Content-Type': 'application/json', Authorization: `Bearer ${apikey}`, - }; - - let systemPrompt = prompt; - let userPrompt = `Explain the following code in ${supportLanguage[to]}:\n"""\n${text}\n"""`; + } : { + 'Content-Type': 'application/json', + Authorization: `api-key: ${apikey}`, + } - const body = { + const body = service == 'openai' ? { model: 'gpt-3.5-turbo', temperature: 0, max_tokens: 1000, @@ -61,7 +72,12 @@ export async function translate(text, from, to, setText) { { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }, ], - }; + } : { + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt }, + ] + } if (stream) { const res = await window.fetch(`https://${domain}/v1/chat/completions`, { diff --git a/src/interfaces/openai_polish.js b/src/interfaces/openai_polish.js index dde7a80715..9f66532c24 100644 --- a/src/interfaces/openai_polish.js +++ b/src/interfaces/openai_polish.js @@ -30,24 +30,34 @@ export async function translate(text, from, to, setText) { if (domain == '') { domain = 'api.openai.com'; } + if (domain.startsWith('http')) { + domain = domain.replace('https://', '').replace('http://', ''); + } + let path = get('openai_path') ?? '/v1/chat/completions'; + if (path == '') { + path = '/v1/chat/completions'; + } const apikey = get('openai_apikey') ?? ''; if (apikey == '') { throw '请先配置apikey'; } - let prompt = get('openai_polish_prompt') ?? ''; - if (prompt == '') { - prompt = "You are a text embellisher, you can only embellish the text, don't interpret it."; + let systemPrompt = get('openai_polish_prompt') ?? ''; + if (systemPrompt == '') { + systemPrompt = "You are a text embellisher, you can only embellish the text, don't interpret it."; } + let userPrompt = `Embellish in ${supportLanguage[to]}:\n"""\n${text}\n"""`; const stream = get('openai_stream') ?? false; - const headers = { + const service = get('openai_service') ?? 'openai'; + + const headers = service == 'openai' ? { 'Content-Type': 'application/json', Authorization: `Bearer ${apikey}`, - }; - - let systemPrompt = prompt; - let userPrompt = `Embellish in ${supportLanguage[to]}:\n"""\n${text}\n"""`; + } : { + 'Content-Type': 'application/json', + Authorization: `api-key: ${apikey}`, + } - const body = { + const body = service == 'openai' ? { model: 'gpt-3.5-turbo', temperature: 0, max_tokens: 1000, @@ -59,7 +69,12 @@ export async function translate(text, from, to, setText) { { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }, ], - }; + } : { + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt }, + ] + } if (stream) { const res = await window.fetch(`https://${domain}/v1/chat/completions`, { diff --git a/src/interfaces/openai_summary.js b/src/interfaces/openai_summary.js index dce7d6c161..b03c7e2375 100644 --- a/src/interfaces/openai_summary.js +++ b/src/interfaces/openai_summary.js @@ -30,24 +30,34 @@ export async function translate(text, from, to, setText) { if (domain == '') { domain = 'api.openai.com'; } + if (domain.startsWith('http')) { + domain = domain.replace('https://', '').replace('http://', ''); + } + let path = get('openai_path') ?? '/v1/chat/completions'; + if (path == '') { + path = '/v1/chat/completions'; + } const apikey = get('openai_apikey') ?? ''; if (apikey == '') { throw '请先配置apikey'; } - let prompt = get('openai_summary_prompt') ?? ''; - if (prompt == '') { - prompt = "You are a text summarizer, you can only summarize the text, don't interpret it."; + let systemPrompt = get('openai_summary_prompt') ?? ''; + if (systemPrompt == '') { + systemPrompt = "You are a text summarizer, you can only summarize the text, don't interpret it."; } + let userPrompt = `Summarize in ${supportLanguage[to]}:\n"""\n${text}\n"""`; const stream = get('openai_stream') ?? false; - const headers = { + const service = get('openai_service') ?? 'openai'; + + const headers = service == 'openai' ? { 'Content-Type': 'application/json', Authorization: `Bearer ${apikey}`, - }; - - let systemPrompt = prompt; - let userPrompt = `Summarize in ${supportLanguage[to]}:\n"""\n${text}\n"""`; + } : { + 'Content-Type': 'application/json', + Authorization: `api-key: ${apikey}`, + } - const body = { + const body = service == 'openai' ? { model: 'gpt-3.5-turbo', temperature: 0, max_tokens: 1000, @@ -59,7 +69,12 @@ export async function translate(text, from, to, setText) { { role: 'system', content: systemPrompt }, { role: 'user', content: userPrompt }, ], - }; + } : { + messages: [ + { role: 'system', content: systemPrompt }, + { role: 'user', content: userPrompt }, + ] + } if (stream) { const res = await window.fetch(`https://${domain}/v1/chat/completions`, { diff --git a/src/windows/Config/index.jsx b/src/windows/Config/index.jsx index c3cc0b2f72..64faad6a64 100644 --- a/src/windows/Config/index.jsx +++ b/src/windows/Config/index.jsx @@ -32,6 +32,7 @@ export const ankiEnableAtom = atom(true); export const eudicEnableAtom = atom(true); export const eudicCategoryNameAtom = atom(''); export const eudicTokenAtom = atom(''); +export const openaiServiceAtom = atom('openai'); export const interfaceConfigsAtom = atom({}); export const shortcutTranslateAtom = atom(''); export const shortcutPersistentAtom = atom(''); @@ -41,6 +42,7 @@ export default function Config() { const setShortcutTranslate = useSetAtom(shortcutTranslateAtom); const setShortcutPersistent = useSetAtom(shortcutPersistentAtom); const setShortcutOcr = useSetAtom(shortcutOcrAtom); + const setOpenaiService = useSetAtom(openaiServiceAtom); const setInterfaceConfigs = useSetAtom(interfaceConfigsAtom); const setAutoStart = useSetAtom(autoStartAtom); const setAutoCheck = useSetAtom(autoCheckAtom); @@ -95,6 +97,7 @@ export default function Config() { setEudicCategoryName(get('eudic_category_name') ?? 'pot'); setEudicToken(get('eudic_token') ?? ''); setTheme(get('theme') ?? 'auto'); + setOpenaiService(get('openai_service') ?? 'openai'); let interface_configs = {}; Object.keys(interfaces).map((i) => { diff --git a/src/windows/Config/pages/InterfaceConfig/index.jsx b/src/windows/Config/pages/InterfaceConfig/index.jsx index 0cf50744b4..3966763393 100644 --- a/src/windows/Config/pages/InterfaceConfig/index.jsx +++ b/src/windows/Config/pages/InterfaceConfig/index.jsx @@ -1,17 +1,33 @@ -import { TextField, Switch, FormControlLabel } from '@mui/material'; +import { TextField, Switch, FormControlLabel, Select, MenuItem, Tooltip } from '@mui/material'; import { useAtom } from 'jotai'; import { nanoid } from 'nanoid'; import React from 'react'; +import { interfaceConfigsAtom, openaiServiceAtom } from '../..'; import ConfigList from '../../components/ConfigList'; import ConfigItem from '../../components/ConfigItem'; import { set } from '../../../../global/config'; -import { interfaceConfigsAtom } from '../..'; export default function InterfaceConfig() { const [interfaceConfigs, setInterfaceConfigs] = useAtom(interfaceConfigsAtom); + const [openaiService, setOpenaiService] = useAtom(openaiServiceAtom); return ( + + + + + {Object.keys(interfaceConfigs).map((x) => { return (