forked from open-webui/open-webui
Merge pull request #186 from ollama-webui/dev
feat: `/chat` route support
This commit is contained in:
commit
a7bec01d7b
4 changed files with 377 additions and 303 deletions
|
@ -2,6 +2,8 @@
|
|||
|
||||
## Connection Errors
|
||||
|
||||
Make sure you have the **latest version of Ollama** installed before proceeding with the installation. You can find the latest version of Ollama at [https://ollama.ai/](https://ollama.ai/).
|
||||
|
||||
If you encounter difficulties connecting to the Ollama server, please follow these steps to diagnose and resolve the issue:
|
||||
|
||||
**1. Verify Ollama Server Configuration**
|
||||
|
@ -43,5 +45,6 @@ docker run --platform linux/amd64 -d -p 3000:8080 -e OLLAMA_API_BASE_URL=http://
|
|||
```
|
||||
|
||||
## References
|
||||
|
||||
[Change Docker Desktop Settings on Mac](https://docs.docker.com/desktop/settings/mac/) Search for "x86" in that page.
|
||||
[Run x86 (Intel) and ARM based images on Apple Silicon (M1) Macs?](https://forums.docker.com/t/run-x86-intel-and-arm-based-images-on-apple-silicon-m1-macs/117123)
|
||||
|
|
|
@ -162,7 +162,15 @@
|
|||
const editMessageHandler = async (messageId) => {
|
||||
// let editMessage = history.messages[messageId];
|
||||
history.messages[messageId].edit = true;
|
||||
history.messages[messageId].originalContent = history.messages[messageId].content;
|
||||
history.messages[messageId].editedContent = history.messages[messageId].content;
|
||||
|
||||
await tick();
|
||||
|
||||
const editElement = document.getElementById(`message-edit-${messageId}`);
|
||||
|
||||
editElement.style.height = '';
|
||||
editElement.style.height = `${editElement.scrollHeight}px`;
|
||||
};
|
||||
|
||||
const confirmEditMessage = async (messageId) => {
|
||||
|
@ -195,6 +203,11 @@
|
|||
await sendPrompt(userPrompt, userMessageId, $chatId);
|
||||
};
|
||||
|
||||
const confirmEditResponseMessage = async (messageId) => {
|
||||
history.messages[messageId].edit = false;
|
||||
history.messages[messageId].content = history.messages[messageId].editedContent;
|
||||
};
|
||||
|
||||
const cancelEditMessage = (messageId) => {
|
||||
history.messages[messageId].edit = false;
|
||||
history.messages[messageId].editedContent = undefined;
|
||||
|
@ -415,19 +428,15 @@
|
|||
{#if message?.edit === true}
|
||||
<div class=" w-full">
|
||||
<textarea
|
||||
id="message-edit-{message.id}"
|
||||
class=" bg-transparent outline-none w-full resize-none"
|
||||
bind:value={history.messages[message.id].editedContent}
|
||||
on:input={(e) => {
|
||||
e.target.style.height = '';
|
||||
e.target.style.height = `${e.target.scrollHeight}px`;
|
||||
}}
|
||||
on:focus={(e) => {
|
||||
e.target.style.height = '';
|
||||
e.target.style.height = `${e.target.scrollHeight}px`;
|
||||
}}
|
||||
/>
|
||||
|
||||
<div class=" mt-2 flex justify-center space-x-2 text-sm font-medium">
|
||||
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
|
||||
<button
|
||||
class="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded-lg"
|
||||
on:click={() => {
|
||||
|
@ -609,199 +618,239 @@
|
|||
</div>
|
||||
</div>
|
||||
{/if}
|
||||
{:else}
|
||||
<div class="w-full">
|
||||
{@html marked(message.content.replace('\\\\', '\\\\\\'))}
|
||||
{/if}
|
||||
|
||||
{#if message.done}
|
||||
<div class=" flex justify-start space-x-1 -mt-2">
|
||||
{#if message.parentId !== null && message.parentId in history.messages && (history.messages[message.parentId]?.childrenIds.length ?? 0) > 1}
|
||||
<div class="flex self-center">
|
||||
<button
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
showPreviousMessage(message);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="text-xs font-bold self-center">
|
||||
{history.messages[message.parentId].childrenIds.indexOf(message.id) +
|
||||
1} / {history.messages[message.parentId].childrenIds.length}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
showNextMessage(message);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<!-- <button
|
||||
class="invisible group-hover:visible p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
editMessageHandler(message.id);
|
||||
{#if message.role === 'assistant'}
|
||||
<div>
|
||||
{#if message?.edit === true}
|
||||
<div class=" w-full">
|
||||
<textarea
|
||||
id="message-edit-{message.id}"
|
||||
class=" bg-transparent outline-none w-full resize-none"
|
||||
bind:value={history.messages[message.id].editedContent}
|
||||
on:input={(e) => {
|
||||
e.target.style.height = `${e.target.scrollHeight}px`;
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
|
||||
/>
|
||||
</svg>
|
||||
</button> -->
|
||||
/>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
copyToClipboard(message.content);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
rateMessage(messageIdx, 1);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-4 h-4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
|
||||
/></svg
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
rateMessage(messageIdx, -1);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-4 h-4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
|
||||
/></svg
|
||||
>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
speakMessage(message.content);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{#if messageIdx + 1 === messages.length}
|
||||
<div class=" mt-2 mb-1 flex justify-center space-x-2 text-sm font-medium">
|
||||
<button
|
||||
type="button"
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={regenerateResponse}
|
||||
class="px-4 py-2 bg-emerald-600 hover:bg-emerald-700 text-gray-100 transition rounded-lg"
|
||||
on:click={() => {
|
||||
confirmEditResponseMessage(message.id);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
Save
|
||||
</button>
|
||||
|
||||
<button
|
||||
class=" px-4 py-2 hover:bg-gray-100 dark:bg-gray-800 dark:hover:bg-gray-700 text-gray-700 dark:text-gray-100 transition outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg"
|
||||
on:click={() => {
|
||||
cancelEditMessage(message.id);
|
||||
}}
|
||||
>
|
||||
Cancel
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{:else}
|
||||
<div class="w-full">
|
||||
{@html marked(message.content.replace('\\\\', '\\\\\\'))}
|
||||
|
||||
{#if message.done}
|
||||
<div class=" flex justify-start space-x-1 -mt-2">
|
||||
{#if message.parentId !== null && message.parentId in history.messages && (history.messages[message.parentId]?.childrenIds.length ?? 0) > 1}
|
||||
<div class="flex self-center">
|
||||
<button
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
showPreviousMessage(message);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M12.79 5.23a.75.75 0 01-.02 1.06L8.832 10l3.938 3.71a.75.75 0 11-1.04 1.08l-4.5-4.25a.75.75 0 010-1.08l4.5-4.25a.75.75 0 011.06.02z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<div class="text-xs font-bold self-center">
|
||||
{history.messages[message.parentId].childrenIds.indexOf(
|
||||
message.id
|
||||
) + 1} / {history.messages[message.parentId].childrenIds.length}
|
||||
</div>
|
||||
|
||||
<button
|
||||
class="self-center"
|
||||
on:click={() => {
|
||||
showNextMessage(message);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 20 20"
|
||||
fill="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
fill-rule="evenodd"
|
||||
d="M7.21 14.77a.75.75 0 01.02-1.06L11.168 10 7.23 6.29a.75.75 0 111.04-1.08l4.5 4.25a.75.75 0 010 1.08l-4.5 4.25a.75.75 0 01-1.06-.02z"
|
||||
clip-rule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
editMessageHandler(message.id);
|
||||
}}
|
||||
>
|
||||
<path
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.862 4.487l1.687-1.688a1.875 1.875 0 112.652 2.652L6.832 19.82a4.5 4.5 0 01-1.897 1.13l-2.685.8.8-2.685a4.5 4.5 0 011.13-1.897L16.863 4.487zm0 0L19.5 7.125"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
copyToClipboard(message.content);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M15.666 3.888A2.25 2.25 0 0013.5 2.25h-3c-1.03 0-1.9.693-2.166 1.638m7.332 0c.055.194.084.4.084.612v0a.75.75 0 01-.75.75H9a.75.75 0 01-.75-.75v0c0-.212.03-.418.084-.612m7.332 0c.646.049 1.288.11 1.927.184 1.1.128 1.907 1.077 1.907 2.185V19.5a2.25 2.25 0 01-2.25 2.25H6.75A2.25 2.25 0 014.5 19.5V6.257c0-1.108.806-2.057 1.907-2.185a48.208 48.208 0 011.927-.184"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
rateMessage(messageIdx, 1);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
class="w-4 h-4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M14 9V5a3 3 0 0 0-3-3l-4 9v11h11.28a2 2 0 0 0 2-1.7l1.38-9a2 2 0 0 0-2-2.3zM7 22H4a2 2 0 0 1-2-2v-7a2 2 0 0 1 2-2h3"
|
||||
/></svg
|
||||
>
|
||||
</button>
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
rateMessage(messageIdx, -1);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
stroke="currentColor"
|
||||
fill="none"
|
||||
stroke-width="2"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
class="w-4 h-4"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
><path
|
||||
d="M10 15v4a3 3 0 0 0 3 3l4-9V2H5.72a2 2 0 0 0-2 1.7l-1.38 9a2 2 0 0 0 2 2.3zm7-13h2.67A2.31 2.31 0 0 1 22 4v7a2.31 2.31 0 0 1-2.33 2H17"
|
||||
/></svg
|
||||
>
|
||||
</button>
|
||||
|
||||
<button
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={() => {
|
||||
speakMessage(message.content);
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M19.114 5.636a9 9 0 010 12.728M16.463 8.288a5.25 5.25 0 010 7.424M6.75 8.25l4.72-4.72a.75.75 0 011.28.53v15.88a.75.75 0 01-1.28.53l-4.72-4.72H4.51c-.88 0-1.704-.507-1.938-1.354A9.01 9.01 0 012.25 12c0-.83.112-1.633.322-2.396C2.806 8.756 3.63 8.25 4.51 8.25H6.75z"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
|
||||
{#if messageIdx + 1 === messages.length}
|
||||
<button
|
||||
type="button"
|
||||
class="{messageIdx + 1 === messages.length
|
||||
? 'visible'
|
||||
: 'invisible group-hover:visible'} p-1 rounded dark:hover:bg-gray-800 transition"
|
||||
on:click={regenerateResponse}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
fill="none"
|
||||
viewBox="0 0 24 24"
|
||||
stroke-width="1.5"
|
||||
stroke="currentColor"
|
||||
class="w-4 h-4"
|
||||
>
|
||||
<path
|
||||
stroke-linecap="round"
|
||||
stroke-linejoin="round"
|
||||
d="M16.023 9.348h4.992v-.001M2.985 19.644v-4.992m0 0h4.992m-4.993 0l3.181 3.183a8.25 8.25 0 0013.803-3.7M4.031 9.865a8.25 8.25 0 0113.803-3.7l3.181 3.182m0-4.991v4.99"
|
||||
/>
|
||||
</svg>
|
||||
</button>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
|
|
|
@ -76,6 +76,13 @@
|
|||
selectedModels = $page.url.searchParams.get('models')
|
||||
? $page.url.searchParams.get('models')?.split(',')
|
||||
: $settings.models ?? [''];
|
||||
|
||||
let _settings = JSON.parse(localStorage.getItem('settings') ?? '{}');
|
||||
console.log(_settings);
|
||||
settings.set({
|
||||
...$settings,
|
||||
..._settings
|
||||
});
|
||||
};
|
||||
|
||||
//////////////////////////
|
||||
|
@ -118,38 +125,11 @@
|
|||
];
|
||||
}
|
||||
|
||||
await tick();
|
||||
|
||||
window.scrollTo({ top: document.body.scrollHeight });
|
||||
|
||||
const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
...($settings.authHeader && { Authorization: $settings.authHeader }),
|
||||
...($user && { Authorization: `Bearer ${localStorage.token}` })
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
prompt: userPrompt,
|
||||
system: $settings.system ?? undefined,
|
||||
options: {
|
||||
seed: $settings.seed ?? undefined,
|
||||
temperature: $settings.temperature ?? undefined,
|
||||
repeat_penalty: $settings.repeat_penalty ?? undefined,
|
||||
top_k: $settings.top_k ?? undefined,
|
||||
top_p: $settings.top_p ?? undefined,
|
||||
num_ctx: $settings.num_ctx ?? undefined,
|
||||
...($settings.options ?? {})
|
||||
},
|
||||
format: $settings.requestFormat ?? undefined,
|
||||
context:
|
||||
history.messages[parentId] !== null &&
|
||||
history.messages[parentId].parentId in history.messages
|
||||
? history.messages[history.messages[parentId].parentId]?.context ?? undefined
|
||||
: undefined
|
||||
})
|
||||
});
|
||||
|
||||
// const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, {
|
||||
// const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'text/event-stream',
|
||||
|
@ -158,17 +138,8 @@
|
|||
// },
|
||||
// body: JSON.stringify({
|
||||
// model: model,
|
||||
// messages: [
|
||||
// $settings.system
|
||||
// ? {
|
||||
// role: 'system',
|
||||
// content: $settings.system
|
||||
// }
|
||||
// : undefined,
|
||||
// ...messages
|
||||
// ]
|
||||
// .filter((message) => message)
|
||||
// .map((message) => ({ role: message.role, content: message.content })),
|
||||
// prompt: userPrompt,
|
||||
// system: $settings.system ?? undefined,
|
||||
// options: {
|
||||
// seed: $settings.seed ?? undefined,
|
||||
// temperature: $settings.temperature ?? undefined,
|
||||
|
@ -178,10 +149,48 @@
|
|||
// num_ctx: $settings.num_ctx ?? undefined,
|
||||
// ...($settings.options ?? {})
|
||||
// },
|
||||
// format: $settings.requestFormat ?? undefined
|
||||
// format: $settings.requestFormat ?? undefined,
|
||||
// context:
|
||||
// history.messages[parentId] !== null &&
|
||||
// history.messages[parentId].parentId in history.messages
|
||||
// ? history.messages[history.messages[parentId].parentId]?.context ?? undefined
|
||||
// : undefined
|
||||
// })
|
||||
// });
|
||||
|
||||
const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
...($settings.authHeader && { Authorization: $settings.authHeader }),
|
||||
...($user && { Authorization: `Bearer ${localStorage.token}` })
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
messages: [
|
||||
$settings.system
|
||||
? {
|
||||
role: 'system',
|
||||
content: $settings.system
|
||||
}
|
||||
: undefined,
|
||||
...messages
|
||||
]
|
||||
.filter((message) => message)
|
||||
.map((message) => ({ role: message.role, content: message.content })),
|
||||
options: {
|
||||
seed: $settings.seed ?? undefined,
|
||||
temperature: $settings.temperature ?? undefined,
|
||||
repeat_penalty: $settings.repeat_penalty ?? undefined,
|
||||
top_k: $settings.top_k ?? undefined,
|
||||
top_p: $settings.top_p ?? undefined,
|
||||
num_ctx: $settings.num_ctx ?? undefined,
|
||||
...($settings.options ?? {})
|
||||
},
|
||||
format: $settings.requestFormat ?? undefined
|
||||
})
|
||||
});
|
||||
|
||||
const reader = res.body
|
||||
.pipeThrough(new TextDecoderStream())
|
||||
.pipeThrough(splitStream('\n'))
|
||||
|
@ -189,12 +198,9 @@
|
|||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done || stopResponseFlag) {
|
||||
if (stopResponseFlag) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
}
|
||||
|
||||
if (done || stopResponseFlag || _chatId !== $chatId) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -205,18 +211,28 @@
|
|||
if (line !== '') {
|
||||
console.log(line);
|
||||
let data = JSON.parse(line);
|
||||
|
||||
if ('detail' in data) {
|
||||
throw data;
|
||||
}
|
||||
|
||||
if (data.done == false) {
|
||||
if (responseMessage.content == '' && data.response == '\n') {
|
||||
if (responseMessage.content == '' && data.message.content == '\n') {
|
||||
continue;
|
||||
} else {
|
||||
responseMessage.content += data.response;
|
||||
responseMessage.content += data.message.content;
|
||||
messages = messages;
|
||||
}
|
||||
} else if ('detail' in data) {
|
||||
throw data;
|
||||
} else {
|
||||
responseMessage.done = true;
|
||||
responseMessage.context = data.context;
|
||||
responseMessage.context = data.context ?? null;
|
||||
responseMessage.info = {
|
||||
total_duration: data.total_duration,
|
||||
prompt_eval_count: data.prompt_eval_count,
|
||||
prompt_eval_duration: data.prompt_eval_duration,
|
||||
eval_count: data.eval_count,
|
||||
eval_duration: data.eval_duration
|
||||
};
|
||||
messages = messages;
|
||||
}
|
||||
}
|
||||
|
@ -324,12 +340,9 @@
|
|||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done || stopResponseFlag) {
|
||||
if (stopResponseFlag) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
}
|
||||
|
||||
if (done || stopResponseFlag || _chatId !== $chatId) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -152,38 +152,11 @@
|
|||
];
|
||||
}
|
||||
|
||||
await tick();
|
||||
|
||||
window.scrollTo({ top: document.body.scrollHeight });
|
||||
|
||||
const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
...($settings.authHeader && { Authorization: $settings.authHeader }),
|
||||
...($user && { Authorization: `Bearer ${localStorage.token}` })
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
prompt: userPrompt,
|
||||
system: $settings.system ?? undefined,
|
||||
options: {
|
||||
seed: $settings.seed ?? undefined,
|
||||
temperature: $settings.temperature ?? undefined,
|
||||
repeat_penalty: $settings.repeat_penalty ?? undefined,
|
||||
top_k: $settings.top_k ?? undefined,
|
||||
top_p: $settings.top_p ?? undefined,
|
||||
num_ctx: $settings.num_ctx ?? undefined,
|
||||
...($settings.options ?? {})
|
||||
},
|
||||
format: $settings.requestFormat ?? undefined,
|
||||
context:
|
||||
history.messages[parentId] !== null &&
|
||||
history.messages[parentId].parentId in history.messages
|
||||
? history.messages[history.messages[parentId].parentId]?.context ?? undefined
|
||||
: undefined
|
||||
})
|
||||
});
|
||||
|
||||
// const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, {
|
||||
// const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/generate`, {
|
||||
// method: 'POST',
|
||||
// headers: {
|
||||
// 'Content-Type': 'text/event-stream',
|
||||
|
@ -192,17 +165,8 @@
|
|||
// },
|
||||
// body: JSON.stringify({
|
||||
// model: model,
|
||||
// messages: [
|
||||
// $settings.system
|
||||
// ? {
|
||||
// role: 'system',
|
||||
// content: $settings.system
|
||||
// }
|
||||
// : undefined,
|
||||
// ...messages
|
||||
// ]
|
||||
// .filter((message) => message)
|
||||
// .map((message) => ({ role: message.role, content: message.content })),
|
||||
// prompt: userPrompt,
|
||||
// system: $settings.system ?? undefined,
|
||||
// options: {
|
||||
// seed: $settings.seed ?? undefined,
|
||||
// temperature: $settings.temperature ?? undefined,
|
||||
|
@ -212,10 +176,48 @@
|
|||
// num_ctx: $settings.num_ctx ?? undefined,
|
||||
// ...($settings.options ?? {})
|
||||
// },
|
||||
// format: $settings.requestFormat ?? undefined
|
||||
// format: $settings.requestFormat ?? undefined,
|
||||
// context:
|
||||
// history.messages[parentId] !== null &&
|
||||
// history.messages[parentId].parentId in history.messages
|
||||
// ? history.messages[history.messages[parentId].parentId]?.context ?? undefined
|
||||
// : undefined
|
||||
// })
|
||||
// });
|
||||
|
||||
const res = await fetch(`${$settings?.API_BASE_URL ?? OLLAMA_API_BASE_URL}/chat`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'text/event-stream',
|
||||
...($settings.authHeader && { Authorization: $settings.authHeader }),
|
||||
...($user && { Authorization: `Bearer ${localStorage.token}` })
|
||||
},
|
||||
body: JSON.stringify({
|
||||
model: model,
|
||||
messages: [
|
||||
$settings.system
|
||||
? {
|
||||
role: 'system',
|
||||
content: $settings.system
|
||||
}
|
||||
: undefined,
|
||||
...messages
|
||||
]
|
||||
.filter((message) => message)
|
||||
.map((message) => ({ role: message.role, content: message.content })),
|
||||
options: {
|
||||
seed: $settings.seed ?? undefined,
|
||||
temperature: $settings.temperature ?? undefined,
|
||||
repeat_penalty: $settings.repeat_penalty ?? undefined,
|
||||
top_k: $settings.top_k ?? undefined,
|
||||
top_p: $settings.top_p ?? undefined,
|
||||
num_ctx: $settings.num_ctx ?? undefined,
|
||||
...($settings.options ?? {})
|
||||
},
|
||||
format: $settings.requestFormat ?? undefined
|
||||
})
|
||||
});
|
||||
|
||||
const reader = res.body
|
||||
.pipeThrough(new TextDecoderStream())
|
||||
.pipeThrough(splitStream('\n'))
|
||||
|
@ -223,12 +225,9 @@
|
|||
|
||||
while (true) {
|
||||
const { value, done } = await reader.read();
|
||||
if (done || stopResponseFlag) {
|
||||
if (stopResponseFlag) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
}
|
||||
|
||||
if (done || stopResponseFlag || _chatId !== $chatId) {
|
||||
responseMessage.done = true;
|
||||
messages = messages;
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -239,18 +238,28 @@
|
|||
if (line !== '') {
|
||||
console.log(line);
|
||||
let data = JSON.parse(line);
|
||||
|
||||
if ('detail' in data) {
|
||||
throw data;
|
||||
}
|
||||
|
||||
if (data.done == false) {
|
||||
if (responseMessage.content == '' && data.response == '\n') {
|
||||
if (responseMessage.content == '' && data.message.content == '\n') {
|
||||
continue;
|
||||
} else {
|
||||
responseMessage.content += data.response;
|
||||
responseMessage.content += data.message.content;
|
||||
messages = messages;
|
||||
}
|
||||
} else if ('detail' in data) {
|
||||
throw data;
|
||||
} else {
|
||||
responseMessage.done = true;
|
||||
responseMessage.context = data.context;
|
||||
responseMessage.context = data.context ?? null;
|
||||
responseMessage.info = {
|
||||
total_duration: data.total_duration,
|
||||
prompt_eval_count: data.prompt_eval_count,
|
||||
prompt_eval_duration: data.prompt_eval_duration,
|
||||
eval_count: data.eval_count,
|
||||
eval_duration: data.eval_duration
|
||||
};
|
||||
messages = messages;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue