feat: support waylaidwanderer self-hosted api (#182)

This commit is contained in:
josc146
2023-04-12 21:37:07 +08:00
parent 00a03cf6c9
commit 4f78d225af
6 changed files with 116 additions and 23 deletions
+9 -9
View File
@@ -24,12 +24,12 @@ export async function generateAnswersWithBingWebApi(port, question, session, acc
answer = answer.replaceAll(/\[\^\d+\^\]/g, '')
port.postMessage({ answer: answer, done: false, session: null })
},
...(session.bingWeb.conversationId
...(session.bingWeb_conversationId
? {
conversationId: session.bingWeb.conversationId,
conversationSignature: session.bingWeb.conversationSignature,
clientId: session.bingWeb.clientId,
invocationId: session.bingWeb.invocationId,
conversationId: session.bingWeb_conversationId,
conversationSignature: session.bingWeb_conversationSignature,
clientId: session.bingWeb_clientId,
invocationId: session.bingWeb_invocationId,
}
: {}),
})
@@ -38,10 +38,10 @@ export async function generateAnswersWithBingWebApi(port, question, session, acc
throw err
})
session.bingWeb.conversationSignature = response.conversationSignature
session.bingWeb.conversationId = response.conversationId
session.bingWeb.clientId = response.clientId
session.bingWeb.invocationId = response.invocationId
session.bingWeb_conversationSignature = response.conversationSignature
session.bingWeb_conversationId = response.conversationId
session.bingWeb_clientId = response.clientId
session.bingWeb_invocationId = response.invocationId
pushRecord(session, question, answer)
console.debug('conversation history', { content: session.conversationRecords })
@@ -0,0 +1,76 @@
import { pushRecord, setAbortController } from './shared.mjs'
import { getUserConfig } from '../../config/index.mjs'
import { fetchSSE } from '../../utils/fetch-sse'
import { isEmpty } from 'lodash-es'
/**
* @param {Runtime.Port} port
* @param {string} question
* @param {Session} session
*/
export async function generateAnswersWithWaylaidwandererApi(port, question, session) {
const { controller, messageListener } = setAbortController(port)
const config = await getUserConfig()
let answer = ''
await fetchSSE(config.githubThirdPartyUrl, {
method: 'POST',
signal: controller.signal,
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
message: question,
stream: true,
...(session.bingWeb_conversationId && {
conversationId: session.bingWeb_conversationId,
conversationSignature: session.bingWeb_conversationSignature,
clientId: session.bingWeb_clientId,
invocationId: session.bingWeb_invocationId,
}),
...(session.conversationId && {
conversationId: session.conversationId,
parentMessageId: session.parentMessageId,
}),
}),
onMessage(message) {
console.debug('sse message', message)
if (message === '[DONE]') {
pushRecord(session, question, answer)
console.debug('conversation history', { content: session.conversationRecords })
port.postMessage({ answer: null, done: true, session: session })
return
}
let data
try {
data = JSON.parse(message)
} catch (error) {
console.debug('json error', error)
return
}
if (data.conversationId) session.conversationId = data.conversationId
if (data.parentMessageId) session.parentMessageId = data.parentMessageId
if (data.conversationSignature)
session.bingWeb_conversationSignature = data.conversationSignature
if (data.conversationId) session.bingWeb_conversationId = data.conversationId
if (data.clientId) session.bingWeb_clientId = data.clientId
if (data.invocationId) session.bingWeb_invocationId = data.invocationId
if (typeof data === 'string') {
answer += data
port.postMessage({ answer: answer, done: false, session: null })
}
},
async onStart() {},
async onEnd() {
port.onMessage.removeListener(messageListener)
},
async onError(resp) {
port.onMessage.removeListener(messageListener)
if (resp instanceof Error) throw resp
const error = await resp.json().catch(() => ({}))
throw new Error(!isEmpty(error) ? JSON.stringify(error) : `${resp.status} ${resp.statusText}`)
},
})
}
+4
View File
@@ -12,6 +12,7 @@ import {
} from './apis/openai-api'
import { generateAnswersWithCustomApi } from './apis/custom-api.mjs'
import { generateAnswersWithAzureOpenaiApi } from './apis/azure-openai-api.mjs'
import { generateAnswersWithWaylaidwandererApi } from './apis/waylaidwanderer-api.mjs'
import {
azureOpenAiApiModelKeys,
bingWebModelKeys,
@@ -21,6 +22,7 @@ import {
defaultConfig,
getPreferredLanguageKey,
getUserConfig,
githubThirdPartyApiModelKeys,
gptApiModelKeys,
Models,
} from '../config/index.mjs'
@@ -110,6 +112,8 @@ Browser.runtime.onConnect.addListener((port) => {
)
} else if (azureOpenAiApiModelKeys.includes(session.modelName)) {
await generateAnswersWithAzureOpenaiApi(port, session.question, session)
} else if (githubThirdPartyApiModelKeys.includes(session.modelName)) {
await generateAnswersWithWaylaidwandererApi(port, session.question, session)
}
} catch (err) {
console.error(err)
+7
View File
@@ -20,6 +20,7 @@ export const Models = {
gptApiDavinci: { value: 'text-davinci-003', desc: 'GPT-3.5' },
customModel: { value: '', desc: 'Custom Model' },
azureOpenAi: { value: '', desc: 'ChatGPT (Azure)' },
waylaidwandererApi: { value: '', desc: 'Waylaidwanderer API (Github)' },
}
export const chatgptWebModelKeys = ['chatgptFree35', 'chatgptPlus4']
@@ -28,6 +29,7 @@ export const gptApiModelKeys = ['gptApiDavinci']
export const chatgptApiModelKeys = ['chatgptApi35', 'chatgptApi4_8k', 'chatgptApi4_32k']
export const customApiModelKeys = ['customModel']
export const azureOpenAiApiModelKeys = ['azureOpenAi']
export const githubThirdPartyApiModelKeys = ['waylaidwandererApi']
export const TriggerMode = {
always: 'Always',
@@ -77,6 +79,7 @@ export const defaultConfig = {
customModelApiUrl: 'http://localhost:8000/chat/completions',
customModelName: 'llama-7b-int4',
githubThirdPartyUrl: 'http://127.0.0.1:3000/conversation',
// advanced
@@ -167,6 +170,10 @@ export function isUsingAzureOpenAi(configOrSession) {
return azureOpenAiApiModelKeys.includes(configOrSession.modelName)
}
export function isUsingGithubThirdPartyApi(configOrSession) {
return githubThirdPartyApiModelKeys.includes(configOrSession.modelName)
}
export async function getPreferredLanguageKey() {
const config = await getUserConfig()
if (config.preferredLanguage === 'auto') return config.userLanguage
+12
View File
@@ -7,6 +7,7 @@ import {
isUsingApiKey,
isUsingAzureOpenAi,
isUsingCustomModel,
isUsingGithubThirdPartyApi,
isUsingMultiModeModel,
ModelMode,
Models,
@@ -215,6 +216,17 @@ function GeneralPart({ config, updateConfig }) {
}}
/>
)}
{isUsingGithubThirdPartyApi(config) && (
<input
type="text"
value={config.githubThirdPartyUrl}
placeholder={t('API Url')}
onChange={(e) => {
const url = e.target.value
updateConfig({ githubThirdPartyUrl: url })
}}
/>
)}
</label>
<label>
<legend>{t('Preferred Language')}</legend>
+8 -14
View File
@@ -1,12 +1,5 @@
import { Models } from '../config/index.mjs'
/**
* @typedef {object} BingWeb
* @property {string|null} conversationSignature
* @property {string|null} conversationId
* @property {string|null} clientId
* @property {string|null} invocationId
*/
/**
* @typedef {object} Session
* @property {string|null} question
@@ -20,7 +13,10 @@ import { Models } from '../config/index.mjs'
* @property {string|null} conversationId - chatGPT web mode
* @property {string|null} messageId - chatGPT web mode
* @property {string|null} parentMessageId - chatGPT web mode
* @property {BingWeb} bingWeb
* @property {string|null} bingWeb_conversationSignature
* @property {string|null} bingWeb_conversationId
* @property {string|null} bingWeb_clientId
* @property {string|null} bingWeb_invocationId
*/
/**
* @param {string|null} question
@@ -57,11 +53,9 @@ export function initSession({
parentMessageId: null,
// bing
bingWeb: {
conversationSignature: null,
conversationId: null,
clientId: null,
invocationId: null,
},
bingWeb_conversationSignature: null,
bingWeb_conversationId: null,
bingWeb_clientId: null,
bingWeb_invocationId: null,
}
}