Skip to content
GitLab
Menu
Projects
Groups
Snippets
Loading...
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
chenpangpang
open-webui
Commits
d680d52b
"...git@developer.sourcefind.cn:tsoc/hg-misc-tools.git" did not exist on "3fdc646fdd16bcd7e3aeef60c5149b685f68b8f3"
Commit
d680d52b
authored
May 02, 2024
by
Timothy J. Baek
Browse files
feat:'@' model support
parent
bf35297e
Changes
5
Hide whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
97 additions
and
30 deletions
+97
-30
src/lib/components/chat/MessageInput.svelte
src/lib/components/chat/MessageInput.svelte
+52
-11
src/lib/components/chat/MessageInput/Models.svelte
src/lib/components/chat/MessageInput/Models.svelte
+5
-13
src/lib/components/icons/XMark.svelte
src/lib/components/icons/XMark.svelte
+15
-0
src/routes/(app)/+page.svelte
src/routes/(app)/+page.svelte
+17
-4
src/routes/(app)/c/[id]/+page.svelte
src/routes/(app)/c/[id]/+page.svelte
+8
-2
No files found.
src/lib/components/chat/MessageInput.svelte
View file @
d680d52b
<script lang="ts">
<script lang="ts">
import { toast } from 'svelte-sonner';
import { toast } from 'svelte-sonner';
import { onMount, tick, getContext } from 'svelte';
import { onMount, tick, getContext } from 'svelte';
import { settings, showSidebar } from '$lib/stores';
import {
modelfiles,
settings, showSidebar } from '$lib/stores';
import { blobToFile, calculateSHA256, findWordIndices } from '$lib/utils';
import { blobToFile, calculateSHA256, findWordIndices } from '$lib/utils';
import Prompts from './MessageInput/PromptCommands.svelte';
import Suggestions from './MessageInput/Suggestions.svelte';
import {
import {
uploadDocToVectorDB,
uploadDocToVectorDB,
uploadWebToVectorDB,
uploadWebToVectorDB,
uploadYoutubeTranscriptionToVectorDB
uploadYoutubeTranscriptionToVectorDB
} from '$lib/apis/rag';
} from '$lib/apis/rag';
import { SUPPORTED_FILE_TYPE, SUPPORTED_FILE_EXTENSIONS, WEBUI_BASE_URL } from '$lib/constants';
import { transcribeAudio } from '$lib/apis/audio';
import Prompts from './MessageInput/PromptCommands.svelte';
import Suggestions from './MessageInput/Suggestions.svelte';
import AddFilesPlaceholder from '../AddFilesPlaceholder.svelte';
import AddFilesPlaceholder from '../AddFilesPlaceholder.svelte';
import { SUPPORTED_FILE_TYPE, SUPPORTED_FILE_EXTENSIONS } from '$lib/constants';
import Documents from './MessageInput/Documents.svelte';
import Documents from './MessageInput/Documents.svelte';
import Models from './MessageInput/Models.svelte';
import Models from './MessageInput/Models.svelte';
import { transcribeAudio } from '$lib/apis/audio';
import Tooltip from '../common/Tooltip.svelte';
import Tooltip from '../common/Tooltip.svelte';
import
Page
from '
../../../routes/(app)/+page
.svelte';
import
XMark
from '
$lib/components/icons/XMark
.svelte';
const i18n = getContext('i18n');
const i18n = getContext('i18n');
...
@@ -25,6 +27,8 @@
...
@@ -25,6 +27,8 @@
export let stopResponse: Function;
export let stopResponse: Function;
export let autoScroll = true;
export let autoScroll = true;
export let selectedModel = '';
let chatTextAreaElement: HTMLTextAreaElement;
let chatTextAreaElement: HTMLTextAreaElement;
let filesInputElement;
let filesInputElement;
...
@@ -424,11 +428,11 @@
...
@@ -424,11 +428,11 @@
<div class="fixed bottom-0 {$showSidebar ? 'left-0 lg:left-[260px]' : 'left-0'} right-0">
<div class="fixed bottom-0 {$showSidebar ? 'left-0 lg:left-[260px]' : 'left-0'} right-0">
<div class="w-full">
<div class="w-full">
<div class="
px-2.5 -mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center">
<div class="px-2.5
lg:px-16
-mb-0.5 mx-auto inset-x-0 bg-transparent flex justify-center">
<div class="flex flex-col max-w-5xl w-full">
<div class="flex flex-col max-w-5xl w-full">
<div class="relative">
<div class="relative">
{#if autoScroll === false && messages.length > 0}
{#if autoScroll === false && messages.length > 0}
<div class=" absolute -top-12 left-0 right-0 flex justify-center">
<div class=" absolute -top-12 left-0 right-0 flex justify-center
z-30
">
<button
<button
class=" bg-white border border-gray-100 dark:border-none dark:bg-white/20 p-1.5 rounded-full"
class=" bg-white border border-gray-100 dark:border-none dark:bg-white/20 p-1.5 rounded-full"
on:click={() => {
on:click={() => {
...
@@ -488,14 +492,46 @@
...
@@ -488,14 +492,46 @@
bind:user
bind:user
bind:chatInputPlaceholder
bind:chatInputPlaceholder
{messages}
{messages}
on:select={(e) => {
selectedModel = e.detail;
chatTextAreaElement?.focus();
}}
/>
/>
<!-- {#if messages.length == 0 && suggestionPrompts.length !== 0}
{#if selectedModel !== ''}
<Suggestions {suggestionPrompts} {submitPrompt} />
<div
{/if} -->
class="md:px-3 py-2.5 text-left w-full flex justify-between items-center absolute bottom-0 left-0 right-0 bg-gradient-to-t from-50% from-white dark:from-gray-900"
>
<div class="flex items-center gap-2 text-sm dark:text-gray-500">
<img
alt="model profile"
class="size-5 max-w-[28px] object-cover rounded-full"
src={$modelfiles.find((modelfile) => modelfile.tagName === selectedModel.id)
?.imageUrl ??
($i18n.language === 'dg-DG'
? `/doge.png`
: `${WEBUI_BASE_URL}/static/favicon.png`)}
/>
<div>
Talking to <span class=" font-medium">{selectedModel.name} </span>
</div>
</div>
<div>
<button
class="flex items-center"
on:click={() => {
selectedModel = '';
}}
>
<XMark />
</button>
</div>
</div>
{/if}
</div>
</div>
</div>
</div>
</div>
</div>
<div class="bg-white dark:bg-gray-900">
<div class="bg-white dark:bg-gray-900">
<div class="max-w-6xl px-2.5 lg:px-16 mx-auto inset-x-0">
<div class="max-w-6xl px-2.5 lg:px-16 mx-auto inset-x-0">
<div class=" pb-2">
<div class=" pb-2">
...
@@ -832,6 +868,11 @@
...
@@ -832,6 +868,11 @@
e.target.style.height = '';
e.target.style.height = '';
e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';
e.target.style.height = Math.min(e.target.scrollHeight, 200) + 'px';
}
}
if (e.key === 'Escape') {
console.log('Escape');
selectedModel = '';
}
}}
}}
rows="1"
rows="1"
on:input={(e) => {
on:input={(e) => {
...
...
src/lib/components/chat/MessageInput/Models.svelte
View file @
d680d52b
<script lang="ts">
<script lang="ts">
import { createEventDispatcher } from 'svelte';
import { generatePrompt } from '$lib/apis/ollama';
import { generatePrompt } from '$lib/apis/ollama';
import { models } from '$lib/stores';
import { models } from '$lib/stores';
import { splitStream } from '$lib/utils';
import { splitStream } from '$lib/utils';
...
@@ -7,14 +9,14 @@
...
@@ -7,14 +9,14 @@
const i18n = getContext('i18n');
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
export let prompt = '';
export let prompt = '';
export let user = null;
export let user = null;
export let chatInputPlaceholder = '';
export let chatInputPlaceholder = '';
export let messages = [];
export let messages = [];
let selectedModel = null;
let selectedIdx = 0;
let selectedIdx = 0;
let filteredModels = [];
let filteredModels = [];
...
@@ -36,9 +38,7 @@
...
@@ -36,9 +38,7 @@
const confirmSelect = async (model) => {
const confirmSelect = async (model) => {
prompt = '';
prompt = '';
selectedModel = model;
dispatch('select', model);
console.log(selectedModel);
};
};
const confirmSelectCollaborativeChat = async (model) => {
const confirmSelectCollaborativeChat = async (model) => {
...
@@ -170,11 +170,3 @@
...
@@ -170,11 +170,3 @@
</div>
</div>
{/if}
{/if}
{/if}
{/if}
{#if selectedModel !== null}
<div class="md:px-2 mb-3 text-left w-full absolute bottom-0 left-0 right-0">
<div>
{JSON.stringify(selectedModel)}
</div>
</div>
{/if}
src/lib/components/icons/XMark.svelte
0 → 100644
View file @
d680d52b
<script lang="ts">
export let className = 'size-3.5';
export let strokeWidth = '2';
</script>
<svg
xmlns="http://www.w3.org/2000/svg"
fill="none"
viewBox="0 0 24 24"
stroke-width={strokeWidth}
stroke="currentColor"
class={className}
>
<path stroke-linecap="round" stroke-linejoin="round" d="M6 18 18 6M6 6l12 12" />
</svg>
src/routes/(app)/+page.svelte
View file @
d680d52b
...
@@ -51,7 +51,9 @@
...
@@ -51,7 +51,9 @@
let
currentRequestId
=
null
;
let
currentRequestId
=
null
;
let
showModelSelector
=
true
;
let
showModelSelector
=
true
;
let
selectedModels
=
[
''
];
let
selectedModels
=
[
''
];
let
atSelectedModel
=
''
;
let
selectedModelfile
=
null
;
let
selectedModelfile
=
null
;
$:
selectedModelfile
=
$:
selectedModelfile
=
...
@@ -145,7 +147,8 @@
...
@@ -145,7 +147,8 @@
setTimeout
(()
=>
chatInput
?.
focus
(),
0
);
setTimeout
(()
=>
chatInput
?.
focus
(),
0
);
};
};
const
scrollToBottom
=
()
=>
{
const
scrollToBottom
=
async
()
=>
{
await
tick
();
if
(
messagesContainerElement
)
{
if
(
messagesContainerElement
)
{
messagesContainerElement
.
scrollTop
=
messagesContainerElement
.
scrollHeight
;
messagesContainerElement
.
scrollTop
=
messagesContainerElement
.
scrollHeight
;
}
}
...
@@ -243,7 +246,8 @@
...
@@ -243,7 +246,8 @@
const
_chatId
=
JSON
.
parse
(
JSON
.
stringify
($
chatId
));
const
_chatId
=
JSON
.
parse
(
JSON
.
stringify
($
chatId
));
await
Promise
.
all
(
await
Promise
.
all
(
selectedModels
.
map
(
async
(
modelId
)
=>
{
(
atSelectedModel
!== '' ? [atSelectedModel.id] : selectedModels).map(async (modelId) => {
console
.
log
(
'modelId'
,
modelId
);
const
model
=
$
models
.
filter
((
m
)
=>
m
.
id
===
modelId
).
at
(
0
);
const
model
=
$
models
.
filter
((
m
)
=>
m
.
id
===
modelId
).
at
(
0
);
if
(
model
)
{
if
(
model
)
{
...
@@ -537,7 +541,7 @@
...
@@ -537,7 +541,7 @@
console.log(docs);
console.log(docs);
console.log(model
);
scrollToBottom(
);
const [res, controller] = await generateOpenAIChatCompletion(
const [res, controller] = await generateOpenAIChatCompletion(
localStorage.token,
localStorage.token,
...
@@ -884,4 +888,13 @@
...
@@ -884,4 +888,13 @@
</div>
</div>
</div>
</div>
</div>
</div>
<MessageInput bind:files bind:prompt bind:autoScroll {messages} {submitPrompt} {stopResponse} />
<MessageInput
bind:files
bind:prompt
bind:autoScroll
bind:selectedModel={atSelectedModel}
{messages}
{submitPrompt}
{stopResponse}
/>
src/routes/(app)/c/[id]/+page.svelte
View file @
d680d52b
...
@@ -57,6 +57,8 @@
...
@@ -57,6 +57,8 @@
//
let
chatId
=
$
page
.
params
.
id
;
//
let
chatId
=
$
page
.
params
.
id
;
let
showModelSelector
=
true
;
let
showModelSelector
=
true
;
let
selectedModels
=
[
''
];
let
selectedModels
=
[
''
];
let
atSelectedModel
=
''
;
let
selectedModelfile
=
null
;
let
selectedModelfile
=
null
;
$:
selectedModelfile
=
$:
selectedModelfile
=
...
@@ -167,7 +169,8 @@
...
@@ -167,7 +169,8 @@
}
}
};
};
const
scrollToBottom
=
()
=>
{
const
scrollToBottom
=
async
()
=>
{
await
tick
();
if
(
messagesContainerElement
)
{
if
(
messagesContainerElement
)
{
messagesContainerElement
.
scrollTop
=
messagesContainerElement
.
scrollHeight
;
messagesContainerElement
.
scrollTop
=
messagesContainerElement
.
scrollHeight
;
}
}
...
@@ -256,7 +259,7 @@
...
@@ -256,7 +259,7 @@
const
_chatId
=
JSON
.
parse
(
JSON
.
stringify
($
chatId
));
const
_chatId
=
JSON
.
parse
(
JSON
.
stringify
($
chatId
));
await
Promise
.
all
(
await
Promise
.
all
(
selectedModels
.
map
(
async
(
modelId
)
=>
{
(
atSelectedModel
!== '' ? [atSelectedModel.id] :
selectedModels
)
.map(async (modelId) => {
const
model
=
$
models
.
filter
((
m
)
=>
m
.
id
===
modelId
).
at
(
0
);
const
model
=
$
models
.
filter
((
m
)
=>
m
.
id
===
modelId
).
at
(
0
);
if
(
model
)
{
if
(
model
)
{
...
@@ -550,6 +553,8 @@
...
@@ -550,6 +553,8 @@
console.log(docs);
console.log(docs);
scrollToBottom();
const [res, controller] = await generateOpenAIChatCompletion(
const [res, controller] = await generateOpenAIChatCompletion(
localStorage.token,
localStorage.token,
{
{
...
@@ -911,6 +916,7 @@
...
@@ -911,6 +916,7 @@
bind:files
bind:files
bind:prompt
bind:prompt
bind:autoScroll
bind:autoScroll
bind:selectedModel={atSelectedModel}
suggestionPrompts={selectedModelfile?.suggestionPrompts ?? $config.default_prompt_suggestions}
suggestionPrompts={selectedModelfile?.suggestionPrompts ?? $config.default_prompt_suggestions}
{messages}
{messages}
{submitPrompt}
{submitPrompt}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment