This commit is contained in:
josc146
2024-08-05 19:01:06 +08:00
parent c496f87fe6
commit 6877a1b7bc
22 changed files with 134 additions and 184 deletions
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Immer das schwebende Fenster anzeigen, die Seitenleiste für alle Website-Adapter deaktivieren",
"Allow ESC to close all floating windows": "ESC-Taste zum Schließen aller schwebenden Fenster zulassen",
"Export All Data": "Alle Daten exportieren",
"Import All Data": "Alle Daten importieren"
"Import All Data": "Alle Daten importieren",
"Keep-Alive Time": "Keep-Alive-Zeit",
"5m": "5m",
"30m": "30m",
"Forever": "Für immer"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Always display floating window, disable sidebar for all site adapters",
"Allow ESC to close all floating windows": "Allow ESC to close all floating windows",
"Export All Data": "Export All Data",
"Import All Data": "Import All Data"
"Import All Data": "Import All Data",
"Keep-Alive Time": "Keep-Alive Time",
"5m": "5m",
"30m": "30m",
"Forever": "Forever"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Mostrar siempre la ventana flotante, desactivar la barra lateral para todos los adaptadores de sitios",
"Allow ESC to close all floating windows": "Permitir que ESC cierre todas las ventanas flotantes",
"Export All Data": "Exportar todos los datos",
"Import All Data": "Importar todos los datos"
"Import All Data": "Importar todos los datos",
"Keep-Alive Time": "Tiempo de mantenimiento de la conexión",
"5m": "5m",
"30m": "30m",
"Forever": "Siempre"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Toujours afficher la fenêtre flottante, désactiver la barre latérale pour tous les adaptateurs de site",
"Allow ESC to close all floating windows": "Autoriser la touche ESC pour fermer toutes les fenêtres flottantes",
"Export All Data": "Exporter toutes les données",
"Import All Data": "Importer toutes les données"
"Import All Data": "Importer toutes les données",
"Keep-Alive Time": "Temps de maintien de la connexion",
"5m": "5m",
"30m": "30m",
"Forever": "Toujours"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Selalu tampilkan jendela mengambang, nonaktifkan sidebar untuk semua adapter situs",
"Allow ESC to close all floating windows": "Izinkan ESC untuk menutup semua jendela mengambang",
"Export All Data": "Ekspor Semua Data",
"Import All Data": "Impor Semua Data"
"Import All Data": "Impor Semua Data",
"Keep-Alive Time": "Waktu Tetap Hidup",
"5m": "5m",
"30m": "30m",
"Forever": "Selamanya"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Mostra sempre la finestra flottante, disabilita la barra laterale per tutti gli adattatori del sito",
"Allow ESC to close all floating windows": "Consenti ESC per chiudere tutte le finestre flottanti",
"Export All Data": "Esporta tutti i dati",
"Import All Data": "Importa tutti i dati"
"Import All Data": "Importa tutti i dati",
"Keep-Alive Time": "Tempo di mantenimento",
"5m": "5m",
"30m": "30m",
"Forever": "Per sempre"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "常にフローティングウィンドウを表示し、すべてのサイトアダプターでサイドバーを無効にします",
"Allow ESC to close all floating windows": "ESCキーですべてのフローティングウィンドウを閉じる",
"Export All Data": "すべてのデータをエクスポート",
"Import All Data": "すべてのデータをインポート"
"Import All Data": "すべてのデータをインポート",
"Keep-Alive Time": "Keep-Alive時間",
"5m": "5分",
"30m": "30分",
"Forever": "永久"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "항상 떠다니는 창을 표시하고 모든 사이트 어댑터의 사이드바를 비활성화합니다",
"Allow ESC to close all floating windows": "ESC를 눌러 모든 떠다니는 창을 닫도록 허용",
"Export All Data": "모든 데이터 내보내기",
"Import All Data": "모든 데이터 가져오기"
"Import All Data": "모든 데이터 가져오기",
"Keep-Alive Time": "Keep-Alive 시간",
"5m": "5분",
"30m": "30분",
"Forever": "영원히"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Sempre exibir janela flutuante, desativar barra lateral para todos os adaptadores de site",
"Allow ESC to close all floating windows": "Permitir ESC para fechar todas as janelas flutuantes",
"Export All Data": "Exportar Todos os Dados",
"Import All Data": "Importar Todos os Dados"
"Import All Data": "Importar Todos os Dados",
"Keep-Alive Time": "Tempo de Manutenção de Conexão",
"5m": "5m",
"30m": "30m",
"Forever": "Para sempre"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Всегда отображать плавающее окно, отключить боковую панель для всех адаптеров сайтов",
"Allow ESC to close all floating windows": "Разрешить ESC для закрытия всех плавающих окон",
"Export All Data": "Экспорт всех данных",
"Import All Data": "Импорт всех данных"
"Import All Data": "Импорт всех данных",
"Keep-Alive Time": "Время поддержания активности",
"5m": "5m",
"30m": "30m",
"Forever": "Вечно"
}
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "Her zaman kayan pencereyi görüntüle, tüm site adaptörleri için kenar çubuğunu devre dışı bırak",
"Allow ESC to close all floating windows": "ESC tuşuyla tüm kayan pencereleri kapatmaya izin ver",
"Export All Data": "Tüm Verileri Dışa Aktar",
"Import All Data": "Tüm Verileri İçe Aktar"
"Import All Data": "Tüm Verileri İçe Aktar",
"Keep-Alive Time": "Canlı Tutma Süresi",
"5m": "5m",
"30m": "30m",
"Forever": "Sonsuza dek"
}
+1 -3
View File
@@ -77,7 +77,6 @@
"ChatGPT (GPT-4-8k)": "ChatGPT (GPT-4-8k)",
"ChatGPT (GPT-4-32k)": "ChatGPT (GPT-4-32k)",
"GPT-3.5": "GPT-3.5",
"Ollama API": "Ollama API",
"Custom Model": "自定义模型",
"Balanced": "平衡",
"Creative": "有创造力",
@@ -148,8 +147,7 @@
"Allow ESC to close all floating windows": "允许按ESC关闭所有浮动窗口",
"Export All Data": "导出所有数据",
"Import All Data": "导入所有数据",
"Temperature": "温度",
"keep-alive Time": "保活时间",
"Keep-Alive Time": "保活时间",
"5m": "5分钟",
"30m": "半小时",
"Forever": "永久"
+5 -1
View File
@@ -146,5 +146,9 @@
"Always display floating window, disable sidebar for all site adapters": "總是顯示浮動視窗,停用所有網站適配器的側邊欄",
"Allow ESC to close all floating windows": "允許按 ESC 關閉所有浮動視窗",
"Export All Data": "匯出所有資料",
"Import All Data": "匯入所有資料"
"Import All Data": "匯入所有資料",
"Keep-Alive Time": "保持連線時間",
"5m": "5 分鐘",
"30m": "30 分鐘",
"Forever": "永遠"
}
+1 -7
View File
@@ -127,13 +127,7 @@ async function executeApi(session, port, config) {
config.customModelName,
)
} else if (ollamaApiModelKeys.includes(session.modelName)) {
await generateAnswersWithOllamaApi(
port,
session.question,
session,
config.ollamaApiKey,
config.ollamaModelName,
)
await generateAnswersWithOllamaApi(port, session.question, session)
} else if (azureOpenAiApiModelKeys.includes(session.modelName)) {
await generateAnswersWithAzureOpenaiApi(port, session.question, session)
} else if (claudeApiModelKeys.includes(session.modelName)) {
+2 -1
View File
@@ -251,7 +251,8 @@ export const defaultConfig = {
ollamaEndpoint: 'http://127.0.0.1:11434',
ollamaModelName: 'llama3.1',
keepAliveTime: '5m',
ollamaApiKey: '',
ollamaKeepAliveTime: '5m',
// advanced
-45
View File
@@ -1,7 +1,5 @@
import '../styles.scss'
import { useTranslation } from 'react-i18next'
import { parseFloatWithClamp, parseIntWithClamp } from '../../utils/index.mjs'
import { isUsingOllamaModel } from '../../config/index.mjs'
import PropTypes from 'prop-types'
import { Tab, TabList, TabPanel, Tabs } from 'react-tabs'
import Browser from 'webextension-polyfill'
@@ -58,49 +56,6 @@ function ApiParams({ config, updateConfig }) {
}}
/>
</label>
{isUsingOllamaModel(config) && (
<label>
{`${t('keep-alive Time')}: `}
<div className="label-group">
<label>
<input
type="radio"
name="keepAliveTime"
value="5m"
checked={config.keepAliveTime === '5m'}
onChange={(e) => {
updateConfig({ keepAliveTime: e.target.value })
}}
/>
{t('5m')}
</label>
<label>
<input
type="radio"
name="keepAliveTime"
value="30m"
checked={config.keepAliveTime === '30m'}
onChange={(e) => {
updateConfig({ keepAliveTime: e.target.value })
}}
/>
{t('30m')}
</label>
<label>
<input
type="radio"
name="keepAliveTime"
value="-1"
checked={config.keepAliveTime === '-1'}
onChange={(e) => {
updateConfig({ keepAliveTime: e.target.value })
}}
/>
{t('Forever')}
</label>
</div>
</label>
)}
</>
)
}
+41
View File
@@ -350,6 +350,47 @@ export function GeneralPart({ config, updateConfig }) {
}}
/>
)}
{isUsingOllamaModel(config) && (
<div style={{ display: 'flex', gap: '10px' }}>
{t('Keep-Alive Time') + ':'}
<label>
<input
type="radio"
name="ollamaKeepAliveTime"
value="5m"
checked={config.ollamaKeepAliveTime === '5m'}
onChange={(e) => {
updateConfig({ ollamaKeepAliveTime: e.target.value })
}}
/>
{t('5m')}
</label>
<label>
<input
type="radio"
name="ollamaKeepAliveTime"
value="30m"
checked={config.ollamaKeepAliveTime === '30m'}
onChange={(e) => {
updateConfig({ ollamaKeepAliveTime: e.target.value })
}}
/>
{t('30m')}
</label>
<label>
<input
type="radio"
name="ollamaKeepAliveTime"
value="-1"
checked={config.ollamaKeepAliveTime === '-1'}
onChange={(e) => {
updateConfig({ ollamaKeepAliveTime: e.target.value })
}}
/>
{t('Forever')}
</label>
</div>
)}
{isUsingOllamaModel(config) && (
<input
type="text"
-15
View File
@@ -23,11 +23,6 @@
--active-color: #eaecf0;
}
#app {
max-width: 600px;
margin: 0 auto;
}
.container-page-mode {
display: flex;
flex-direction: column;
@@ -63,7 +58,6 @@
}
.footer {
max-width: 580px;
width: 90%;
position: fixed;
bottom: 10px;
@@ -94,12 +88,3 @@
background: var(--active-color);
}
}
.label-group {
display: flex;
align-items: center;
}
.label-group label {
margin-right: 10px;
}
+27 -73
View File
@@ -1,84 +1,38 @@
// ollama api version
// There is a lot of duplicated code here, but it is very easy to refactor.
// The current state is mainly convenient for making targeted changes at any time,
// and it has not yet had a negative impact on maintenance.
// If necessary, I will refactor.
import { getUserConfig } from '../../config/index.mjs'
import { fetchSSE } from '../../utils/fetch-ollama.mjs'
import { getConversationPairs } from '../../utils/get-conversation-pairs.mjs'
import { isEmpty } from 'lodash-es'
import { pushRecord, setAbortController } from './shared.mjs'
import { generateAnswersWithChatgptApiCompat } from './openai-api.mjs'
/**
* @param {Browser.Runtime.Port} port
* @param {string} question
* @param {Session} session
* @param {string} apiKey
* @param {string} modelName
*/
export async function generateAnswersWithOllamaApi(port, question, session, apiKey, modelName) {
const { controller, messageListener, disconnectListener } = setAbortController(port)
export async function generateAnswersWithOllamaApi(port, question, session) {
const config = await getUserConfig()
const prompt = getConversationPairs(
session.conversationRecords.slice(-config.maxConversationContextLength),
false,
)
// prompt.unshift({ role: 'system', content: await getOllamaApiPromptBase() })
prompt.push({ role: 'user', content: question })
const apiUrl = config.ollamaEndpoint
let answer = ''
let finished = false
const finish = () => {
finished = true
pushRecord(session, question, answer)
console.debug('conversation history', { content: session.conversationRecords })
port.postMessage({ answer: null, done: true, session: session })
}
await fetchSSE(`${apiUrl}/api/chat`, {
method: 'POST',
signal: controller.signal,
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
return generateAnswersWithChatgptApiCompat(
config.ollamaEndpoint + '/v1',
port,
question,
session,
config.ollamaApiKey,
'ollamaModel',
{
model: config.ollamaModelName,
},
body: JSON.stringify({
messages: prompt,
model: modelName,
stream: true,
max_tokens: config.maxResponseTokenLength,
temperature: config.temperature,
keep_alive: config.keepAliveTime === '-1' ? -1 : config.keepAliveTime,
).then(() =>
fetch(config.ollamaEndpoint + '/api/generate', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${config.ollamaApiKey}`,
},
body: JSON.stringify({
model: config.ollamaModelName,
prompt: 't',
options: {
num_predict: 1,
},
keep_alive: config.ollamaKeepAliveTime === '-1' ? -1 : config.ollamaKeepAliveTime,
}),
}),
onMessage(message) {
console.debug('sse message', message)
if (finished) return
let data = message
const delta = data.message?.content
if (delta) {
answer += delta
port.postMessage({ answer: answer, done: false, session: null })
}
if (data.done_reason) {
finish()
return
}
},
async onStart() {},
async onEnd() {
port.postMessage({ done: true })
port.onMessage.removeListener(messageListener)
port.onDisconnect.removeListener(disconnectListener)
},
async onError(resp) {
port.onMessage.removeListener(messageListener)
port.onDisconnect.removeListener(disconnectListener)
if (resp instanceof Error) throw resp
const error = await resp.json().catch(() => ({}))
throw new Error(!isEmpty(error) ? JSON.stringify(error) : `${resp.status} ${resp.statusText}`)
},
})
)
}
+2
View File
@@ -125,6 +125,7 @@ export async function generateAnswersWithChatgptApiCompat(
session,
apiKey,
modelName,
extraBody = {},
) {
const { controller, messageListener, disconnectListener } = setAbortController(port)
@@ -157,6 +158,7 @@ export async function generateAnswersWithChatgptApiCompat(
stream: true,
max_tokens: config.maxResponseTokenLength,
temperature: config.temperature,
...extraBody,
}),
onMessage(message) {
console.debug('sse message', message)
-27
View File
@@ -1,27 +0,0 @@
export async function fetchSSE(resource, options) {
const { onMessage, onStart, onEnd, onError, ...fetchOptions } = options
const resp = await fetch(resource, fetchOptions).catch(async (err) => {
await onError(err)
})
if (!resp) return
if (!resp.ok) {
await onError(resp)
return
}
let hasStarted = false
const reader = resp.body.getReader()
let result
while (!(result = await reader.read()).done) {
const chunk = result.value
const str = new TextDecoder().decode(chunk)
if (!hasStarted) {
const str = new TextDecoder().decode(chunk)
hasStarted = true
await onStart(str)
}
let data = JSON.parse(str)
onMessage(data)
if (data.done) break
}
await onEnd()
}
-1
View File
@@ -33,7 +33,6 @@ export async function fetchSSE(resource, options) {
console.debug('not common response', error)
}
if (fakeSseData) {
console.log('FAKE')
parser.feed(new TextEncoder().encode(fakeSseData))
break
}