mirror of
https://github.com/wassname/chatGPTBox.git
synced 2026-07-23 12:50:47 +08:00
112 lines
3.3 KiB
JavaScript
112 lines
3.3 KiB
JavaScript
// custom 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-sse.mjs'
|
|
import { getConversationPairs } from '../../utils/get-conversation-pairs.mjs'
|
|
import { isEmpty } from 'lodash-es'
|
|
import { pushRecord, setAbortController } from './shared.mjs'
|
|
|
|
/**
|
|
* @param {Browser.Runtime.Port} port
|
|
* @param {string} question
|
|
* @param {Session} session
|
|
* @param {string} apiUrl
|
|
* @param {string} apiKey
|
|
* @param {string} modelName
|
|
*/
|
|
export async function generateAnswersWithCustomApi(
|
|
port,
|
|
question,
|
|
session,
|
|
apiUrl,
|
|
apiKey,
|
|
modelName,
|
|
) {
|
|
const { controller, messageListener, disconnectListener } = setAbortController(port)
|
|
|
|
const config = await getUserConfig()
|
|
const prompt = getConversationPairs(
|
|
session.conversationRecords.slice(-config.maxConversationContextLength),
|
|
false,
|
|
)
|
|
// prompt.unshift({ role: 'system', content: await getCustomApiPromptBase() })
|
|
prompt.push({ role: 'user', content: question })
|
|
|
|
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, {
|
|
method: 'POST',
|
|
signal: controller.signal,
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
Authorization: `Bearer ${apiKey}`,
|
|
},
|
|
body: JSON.stringify({
|
|
messages: prompt,
|
|
model: modelName,
|
|
stream: true,
|
|
max_tokens: config.maxResponseTokenLength,
|
|
temperature: config.temperature,
|
|
}),
|
|
onMessage(message) {
|
|
console.debug('sse message', message)
|
|
if (finished) return
|
|
if (message.trim() === '[DONE]') {
|
|
finish()
|
|
return
|
|
}
|
|
let data
|
|
try {
|
|
data = JSON.parse(message)
|
|
} catch (error) {
|
|
console.debug('json error', error)
|
|
return
|
|
}
|
|
|
|
if (data.response) answer = data.response
|
|
else {
|
|
const delta = data.choices[0]?.delta?.content
|
|
const content = data.choices[0]?.message?.content
|
|
const text = data.choices[0]?.text
|
|
if (delta !== undefined) {
|
|
answer += delta
|
|
} else if (content) {
|
|
answer = content
|
|
} else if (text) {
|
|
answer += text
|
|
}
|
|
}
|
|
port.postMessage({ answer: answer, done: false, session: null })
|
|
|
|
if (data.choices[0]?.finish_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}`)
|
|
},
|
|
})
|
|
}
|