ilhooq's picture
Change API endpoint
31e289c
raw
history blame contribute delete
No virus
4.43 kB
const md = window.markdownit({
linkify: true,
highlight(code, lang) {
const language = hljs.getLanguage(lang) ? lang : 'plaintext';
const html = hljs.highlight(code, {language: language, ignoreIllegals: true }).value
return `<pre class="hljs-code-container my-3"><div class="hljs-code-header"><span>${language}</span><button class="hljs-copy-button">Copy</button></div><code class="hljs language-${language}">${html}</code></pre>`
},
});
new ClipboardJS('.hljs-copy-button', {
target: function(trigger) {
console.log(trigger.parentNode.nextElementSibling)
return trigger.parentNode.nextElementSibling;
}
});
async function getApiUrl() {
if (getApiUrl.url) return getApiUrl.url;
try {
const response = await fetch("/chat/completions", {
method: "OPTIONS",
});
if (response.status !== 200) throw new Error();
getApiUrl.url = "/chat/completions";
const corsHeaders = (
response.headers.get("Access-Control-Allow-Headers") || ""
).toLowerCase();
getApiUrl.tokenRequired = corsHeaders.includes("authorization");
} catch (e) {
getApiUrl.url = "https://api.openai.com/v1/chat/completions";
getApiUrl.tokenRequired = true;
}
return getApiUrl.url;
}
async function postRequest(url, headers, body) {
const response = await fetch(url, {
method: "POST",
headers: headers,
body: JSON.stringify(body),
});
if (!response.ok) {
throw new Error(await response.text());
}
return response;
}
async function readStream(stream, progressCallback) {
const reader = stream.getReader();
const textDecoder = new TextDecoder('utf-8');
let responseObj = {};
while (true) {
const { done, value } = await reader.read();
if (done) break;
const lines = textDecoder.decode(value).split("\n");
processLines(lines, responseObj, progressCallback);
}
return responseObj;
}
function processLines(lines, responseObj, progressCallback) {
for (const line of lines) {
if (line.startsWith("data: ")) {
if (line.includes("[DONE]")) {
return responseObj;
}
try {
const data = JSON.parse(line.slice(6));
const delta = data.choices[0].delta;
Object.keys(delta).forEach(key => {
responseObj[key] = (responseObj[key] || "") + delta[key];
progressCallback(responseObj);
});
} catch (e) {
console.log("Error parsing line:", line);
}
}
}
}
async function complete(messages, token, progressCallback) {
const apiUrl = await getApiUrl();
const headers = { "Content-Type": "application/json" };
if (getApiUrl.tokenRequired) {
headers.Authorization = `Bearer ${token}`;
}
const body = {
model: "gpt-3.5-turbo",
messages: messages,
stream: true,
};
const response = await postRequest(apiUrl, headers, body);
return readStream(response.body, progressCallback);
}
function chatMessage(message) {
return {
scrollToBottom() {
const chatContainer = document.getElementById('chatContainer');
const main = chatContainer.parentElement;
main.scrollTop = main.scrollHeight;
},
watchEffect(message)
{
this.$nextTick(() => {
this.$el.innerHTML = md.render(message);
this.scrollToBottom()
});
}
}
}
function chatApp() {
return {
messages: [],
newMessage: '',
init() {
this.messages = [
{ role: 'system', content: 'You are a programing assistant. Answer using markdown.' }
];
hljs.configure({
'cssSelector' : 'pre code'
});
},
sendMessage() {
if (this.newMessage.trim() === '') return;
const userMessage = { role: 'user', content: this.newMessage };
this.messages.push(userMessage);
this.messages.push({ role: 'assistant', content: '' });
const lastMsgIndex = this.messages.length - 1;
try {
complete(
this.messages,
'no-token',
(message) => {
if (message.content)
this.messages[lastMsgIndex].content = message.content;
}
);
} catch (error) {
console.log(error.message);
return;
} finally {
this.newMessage = '';
}
},
clearMessages() {
this.messages = [];
},
};
}