@@ -94,19 +97,7 @@
setSortKey('created_at')}
- >
- {$i18n.t('Created at')}
- {#if sortKey === 'created_at'}
- {sortOrder === 'asc' ? '▲' : '▼'}
- {:else}
- ▲
- {/if}
- |
-
setSortKey('updated_at')}
>
{$i18n.t('Updated at')}
@@ -131,19 +122,14 @@
>
|
- |
-
-
- {dayjs(chat.created_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
-
- |
-
-
+
+
{dayjs(chat.updated_at * 1000).format($i18n.t('MMMM DD, YYYY HH:mm'))}
|
@@ -192,7 +178,9 @@
{$i18n.t('has no conversations.')}
{/if}
-
+ {:else}
+
+ {/if}
diff --git a/src/lib/components/chat/Chat.svelte b/src/lib/components/chat/Chat.svelte
index 65b1f7fc1..d7ced45a6 100644
--- a/src/lib/components/chat/Chat.svelte
+++ b/src/lib/components/chat/Chat.svelte
@@ -34,7 +34,8 @@
mobile,
showOverview,
chatTitle,
- showArtifacts
+ showArtifacts,
+ tools
} from '$lib/stores';
import {
convertMessagesToHistory,
@@ -65,7 +66,7 @@
import {
chatCompleted,
generateTitle,
- generateSearchQuery,
+ generateQueries,
chatAction,
generateMoACompletion,
generateTags
@@ -78,6 +79,7 @@
import ChatControls from './ChatControls.svelte';
import EventConfirmDialog from '../common/ConfirmDialog.svelte';
import Placeholder from './Placeholder.svelte';
+ import { getTools } from '$lib/apis/tools';
export let chatIdProp = '';
@@ -141,6 +143,38 @@
})();
}
+ $: if (selectedModels && chatIdProp !== '') {
+ saveSessionSelectedModels();
+ }
+
+ const saveSessionSelectedModels = () => {
+ if (selectedModels.length === 0 || (selectedModels.length === 1 && selectedModels[0] === '')) {
+ return;
+ }
+ sessionStorage.selectedModels = JSON.stringify(selectedModels);
+ console.log('saveSessionSelectedModels', selectedModels, sessionStorage.selectedModels);
+ };
+
+ $: if (selectedModels) {
+ setToolIds();
+ }
+
+ const setToolIds = async () => {
+ if (!$tools) {
+ tools.set(await getTools(localStorage.token));
+ }
+
+ if (selectedModels.length !== 1) {
+ return;
+ }
+ const model = $models.find((m) => m.id === selectedModels[0]);
+ if (model) {
+ selectedToolIds = (model?.info?.meta?.toolIds ?? []).filter((id) =>
+ $tools.find((t) => t.id === id)
+ );
+ }
+ };
+
const showMessage = async (message) => {
const _chatId = JSON.parse(JSON.stringify($chatId));
let _messageId = JSON.parse(JSON.stringify(message.id));
@@ -182,7 +216,7 @@
} else {
message.statusHistory = [data];
}
- } else if (type === 'citation') {
+ } else if (type === 'source' || type === 'citation') {
if (data?.type === 'code_execution') {
// Code execution; update existing code execution by ID, or add new one.
if (!message?.code_executions) {
@@ -201,11 +235,11 @@
message.code_executions = message.code_executions;
} else {
- // Regular citation.
- if (message?.citations) {
- message.citations.push(data);
+ // Regular source.
+ if (message?.sources) {
+ message.sources.push(data);
} else {
- message.citations = [data];
+ message.sources = [data];
}
}
} else if (type === 'message') {
@@ -300,6 +334,7 @@
};
onMount(async () => {
+ console.log('mounted');
window.addEventListener('message', onMessageHandler);
$socket?.on('chat-events', chatEventHandler);
@@ -545,28 +580,6 @@
//////////////////////////
const initNewChat = async () => {
- await showControls.set(false);
- await showCallOverlay.set(false);
- await showOverview.set(false);
- await showArtifacts.set(false);
-
- if ($page.url.pathname.includes('/c/')) {
- window.history.replaceState(history.state, '', `/`);
- }
-
- autoScroll = true;
-
- await chatId.set('');
- await chatTitle.set('');
-
- history = {
- messages: {},
- currentId: null
- };
-
- chatFiles = [];
- params = {};
-
if ($page.url.searchParams.get('models')) {
selectedModels = $page.url.searchParams.get('models')?.split(',');
} else if ($page.url.searchParams.get('model')) {
@@ -593,15 +606,21 @@
} else {
selectedModels = urlModels;
}
- } else if ($settings?.models) {
- selectedModels = $settings?.models;
- } else if ($config?.default_models) {
- console.log($config?.default_models.split(',') ?? '');
- selectedModels = $config?.default_models.split(',');
+ } else {
+ if (sessionStorage.selectedModels) {
+ selectedModels = JSON.parse(sessionStorage.selectedModels);
+ sessionStorage.removeItem('selectedModels');
+ } else {
+ if ($settings?.models) {
+ selectedModels = $settings?.models;
+ } else if ($config?.default_models) {
+ console.log($config?.default_models.split(',') ?? '');
+ selectedModels = $config?.default_models.split(',');
+ }
+ }
}
selectedModels = selectedModels.filter((modelId) => $models.map((m) => m.id).includes(modelId));
-
if (selectedModels.length === 0 || (selectedModels.length === 1 && selectedModels[0] === '')) {
if ($models.length > 0) {
selectedModels = [$models[0].id];
@@ -610,7 +629,27 @@
}
}
- console.log(selectedModels);
+ await showControls.set(false);
+ await showCallOverlay.set(false);
+ await showOverview.set(false);
+ await showArtifacts.set(false);
+
+ if ($page.url.pathname.includes('/c/')) {
+ window.history.replaceState(history.state, '', `/`);
+ }
+
+ autoScroll = true;
+
+ await chatId.set('');
+ await chatTitle.set('');
+
+ history = {
+ messages: {},
+ currentId: null
+ };
+
+ chatFiles = [];
+ params = {};
if ($page.url.searchParams.get('youtube')) {
uploadYoutubeTranscription(
@@ -751,7 +790,8 @@
role: m.role,
content: m.content,
info: m.info ? m.info : undefined,
- timestamp: m.timestamp
+ timestamp: m.timestamp,
+ ...(m.sources ? { sources: m.sources } : {})
})),
chat_id: chatId,
session_id: $socket?.id,
@@ -804,7 +844,8 @@
role: m.role,
content: m.content,
info: m.info ? m.info : undefined,
- timestamp: m.timestamp
+ timestamp: m.timestamp,
+ ...(m.sources ? { sources: m.sources } : {})
})),
...(event ? { event: event } : {}),
chat_id: chatId,
@@ -923,9 +964,12 @@
console.log('submitPrompt', userPrompt, $chatId);
const messages = createMessagesList(history.currentId);
- selectedModels = selectedModels.map((modelId) =>
+ const _selectedModels = selectedModels.map((modelId) =>
$models.map((m) => m.id).includes(modelId) ? modelId : ''
);
+ if (JSON.stringify(selectedModels) !== JSON.stringify(_selectedModels)) {
+ selectedModels = _selectedModels;
+ }
if (userPrompt === '') {
toast.error($i18n.t('Please enter a prompt'));
@@ -971,11 +1015,10 @@
await tick();
// Reset chat input textarea
- const chatInputContainer = document.getElementById('chat-input-container');
+ const chatInputElement = document.getElementById('chat-input');
- if (chatInputContainer) {
- chatInputContainer.value = '';
- chatInputContainer.style.height = '';
+ if (chatInputElement) {
+ chatInputElement.style.height = '';
}
const _files = JSON.parse(JSON.stringify(files));
@@ -1018,6 +1061,7 @@
const chatInput = document.getElementById('chat-input');
chatInput?.focus();
+ saveSessionSelectedModels();
_responses = await sendPrompt(userPrompt, userMessageId, { newChat: true });
return _responses;
@@ -1139,11 +1183,14 @@
}
let _response = null;
- if (model?.owned_by === 'ollama') {
- _response = await sendPromptOllama(model, prompt, responseMessageId, _chatId);
- } else if (model) {
- _response = await sendPromptOpenAI(model, prompt, responseMessageId, _chatId);
- }
+
+ // if (model?.owned_by === 'ollama') {
+ // _response = await sendPromptOllama(model, prompt, responseMessageId, _chatId);
+ // } else if (model) {
+ // }
+
+ _response = await sendPromptOpenAI(model, prompt, responseMessageId, _chatId);
+
_responses.push(_response);
if (chatEventEmitter) clearInterval(chatEventEmitter);
@@ -1290,24 +1337,14 @@
$settings?.params?.stream_response ??
params?.stream_response ??
true;
+
const [res, controller] = await generateChatCompletion(localStorage.token, {
stream: stream,
model: model.id,
messages: messagesBody,
- options: {
- ...{ ...($settings?.params ?? {}), ...params },
- stop:
- (params?.stop ?? $settings?.params?.stop ?? undefined)
- ? (params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop).map(
- (str) => decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"'))
- )
- : undefined,
- num_predict: params?.max_tokens ?? $settings?.params?.max_tokens ?? undefined,
- repeat_penalty:
- params?.frequency_penalty ?? $settings?.params?.frequency_penalty ?? undefined
- },
format: $settings.requestFormat ?? undefined,
keep_alive: $settings.keepAlive ?? undefined,
+
tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
files: files.length > 0 ? files : undefined,
session_id: $socket?.id,
@@ -1360,8 +1397,8 @@
console.log(line);
let data = JSON.parse(line);
- if ('citations' in data) {
- responseMessage.citations = data.citations;
+ if ('sources' in data) {
+ responseMessage.sources = data.sources;
// Only remove status if it was initially set
if (model?.info?.meta?.knowledge ?? false) {
responseMessage.statusHistory = responseMessage.statusHistory.filter(
@@ -1625,13 +1662,6 @@
{
stream: stream,
model: model.id,
- ...(stream && (model.info?.meta?.capabilities?.usage ?? false)
- ? {
- stream_options: {
- include_usage: true
- }
- }
- : {}),
messages: [
params?.system || $settings.system || (responseMessage?.userContext ?? null)
? {
@@ -1676,23 +1706,36 @@
content: message?.merged?.content ?? message.content
})
})),
- seed: params?.seed ?? $settings?.params?.seed ?? undefined,
- stop:
- (params?.stop ?? $settings?.params?.stop ?? undefined)
- ? (params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop).map(
- (str) => decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"'))
- )
- : undefined,
- temperature: params?.temperature ?? $settings?.params?.temperature ?? undefined,
- top_p: params?.top_p ?? $settings?.params?.top_p ?? undefined,
- frequency_penalty:
- params?.frequency_penalty ?? $settings?.params?.frequency_penalty ?? undefined,
- max_tokens: params?.max_tokens ?? $settings?.params?.max_tokens ?? undefined,
+
+ // params: {
+ // ...$settings?.params,
+ // ...params,
+
+ // format: $settings.requestFormat ?? undefined,
+ // keep_alive: $settings.keepAlive ?? undefined,
+ // stop:
+ // (params?.stop ?? $settings?.params?.stop ?? undefined)
+ // ? (
+ // params?.stop.split(',').map((token) => token.trim()) ?? $settings.params.stop
+ // ).map((str) =>
+ // decodeURIComponent(JSON.parse('"' + str.replace(/\"/g, '\\"') + '"'))
+ // )
+ // : undefined
+ // },
+
tool_ids: selectedToolIds.length > 0 ? selectedToolIds : undefined,
files: files.length > 0 ? files : undefined,
session_id: $socket?.id,
chat_id: $chatId,
- id: responseMessageId
+ id: responseMessageId,
+
+ ...(stream && (model.info?.meta?.capabilities?.usage ?? false)
+ ? {
+ stream_options: {
+ include_usage: true
+ }
+ }
+ : {})
},
`${WEBUI_BASE_URL}/api`
);
@@ -1714,11 +1757,12 @@
const textStream = await createOpenAITextStream(res.body, $settings.splitLargeChunks);
for await (const update of textStream) {
- const { value, done, citations, selectedModelId, error, usage } = update;
+ const { value, done, sources, selectedModelId, error, usage } = update;
if (error) {
await handleOpenAIError(error, null, model, responseMessage);
break;
}
+
if (done || stopResponseFlag || _chatId !== $chatId) {
responseMessage.done = true;
history.messages[responseMessageId] = responseMessage;
@@ -1731,7 +1775,7 @@
}
if (usage) {
- responseMessage.info = { ...usage, openai: true, usage };
+ responseMessage.usage = usage;
}
if (selectedModelId) {
@@ -1740,8 +1784,8 @@
continue;
}
- if (citations) {
- responseMessage.citations = citations;
+ if (sources) {
+ responseMessage.sources = sources;
// Only remove status if it was initially set
if (model?.info?.meta?.knowledge ?? false) {
responseMessage.statusHistory = responseMessage.statusHistory.filter(
@@ -1919,6 +1963,33 @@
console.log('stopResponse');
};
+ const submitMessage = async (parentId, prompt) => {
+ let userPrompt = prompt;
+ let userMessageId = uuidv4();
+
+ let userMessage = {
+ id: userMessageId,
+ parentId: parentId,
+ childrenIds: [],
+ role: 'user',
+ content: userPrompt,
+ models: selectedModels
+ };
+
+ if (parentId !== null) {
+ history.messages[parentId].childrenIds = [
+ ...history.messages[parentId].childrenIds,
+ userMessageId
+ ];
+ }
+
+ history.messages[userMessageId] = userMessage;
+ history.currentId = userMessageId;
+
+ await tick();
+ await sendPrompt(userPrompt, userMessageId);
+ };
+
const regenerateResponse = async (message) => {
console.log('regenerateResponse');
@@ -1949,7 +2020,9 @@
responseMessage.done = false;
await tick();
- const model = $models.filter((m) => m.id === responseMessage.model).at(0);
+ const model = $models
+ .filter((m) => m.id === (responseMessage?.selectedModelId ?? responseMessage.model))
+ .at(0);
if (model) {
if (model?.owned_by === 'openai') {
@@ -1967,8 +2040,6 @@
_chatId
);
}
- } else {
- toast.error($i18n.t(`Model {{modelId}} not found`, { modelId }));
}
};
@@ -1993,7 +2064,7 @@
if (res && res.ok && res.body) {
const textStream = await createOpenAITextStream(res.body, $settings.splitLargeChunks);
for await (const update of textStream) {
- const { value, done, citations, error, usage } = update;
+ const { value, done, sources, error, usage } = update;
if (error || done) {
break;
}
@@ -2020,20 +2091,21 @@
};
const generateChatTitle = async (messages) => {
+ const lastUserMessage = messages.filter((message) => message.role === 'user').at(-1);
+
if ($settings?.title?.auto ?? true) {
- const lastMessage = messages.at(-1);
const modelId = selectedModels[0];
const title = await generateTitle(localStorage.token, modelId, messages, $chatId).catch(
(error) => {
console.error(error);
- return 'New Chat';
+ return lastUserMessage?.content ?? 'New Chat';
}
);
- return title;
+ return title ? title : (lastUserMessage?.content ?? 'New Chat');
} else {
- return 'New Chat';
+ return lastUserMessage?.content ?? 'New Chat';
}
};
@@ -2089,6 +2161,7 @@
parentId: string,
responseMessageId: string
) => {
+ // TODO: move this to the backend
const responseMessage = history.messages[responseMessageId];
const userMessage = history.messages[parentId];
const messages = createMessagesList(history.currentId);
@@ -2103,17 +2176,17 @@
history.messages[responseMessageId] = responseMessage;
const prompt = userMessage.content;
- let searchQuery = await generateSearchQuery(
+ let queries = await generateQueries(
localStorage.token,
model,
messages.filter((message) => message?.content?.trim()),
prompt
).catch((error) => {
console.log(error);
- return prompt;
+ return [prompt];
});
- if (!searchQuery || searchQuery == '') {
+ if (queries.length === 0) {
responseMessage.statusHistory.push({
done: true,
error: true,
@@ -2124,6 +2197,8 @@
return;
}
+ const searchQuery = queries[0];
+
responseMessage.statusHistory.push({
done: false,
action: 'web_search',
@@ -2326,47 +2401,17 @@
{selectedModels}
{sendPrompt}
{showMessage}
+ {submitMessage}
{continueResponse}
{regenerateResponse}
{mergeResponses}
{chatActionHandler}
bottomPadding={files.length > 0}
- on:submit={async (e) => {
- if (e.detail) {
- // New user message
- let userPrompt = e.detail.prompt;
- let userMessageId = uuidv4();
-
- let userMessage = {
- id: userMessageId,
- parentId: e.detail.parentId,
- childrenIds: [],
- role: 'user',
- content: userPrompt,
- models: selectedModels
- };
-
- let messageParentId = e.detail.parentId;
-
- if (messageParentId !== null) {
- history.messages[messageParentId].childrenIds = [
- ...history.messages[messageParentId].childrenIds,
- userMessageId
- ];
- }
-
- history.messages[userMessageId] = userMessage;
- history.currentId = userMessageId;
-
- await tick();
- await sendPrompt(userPrompt, userMessageId);
- }
- }}
/>
-
+
{
- const model = $models.find((m) => m.id === e);
- if (model?.info?.meta?.toolIds ?? false) {
- return [...new Set([...a, ...model.info.meta.toolIds])];
- }
- return a;
- }, [])}
transparentBackground={$settings?.backgroundImageUrl ?? false}
{stopResponse}
{createMessagePair}
@@ -2400,15 +2438,19 @@
on:submit={async (e) => {
if (e.detail) {
await tick();
- submitPrompt(e.detail.replaceAll('\n\n', '\n'));
+ submitPrompt(
+ ($settings?.richTextInput ?? true)
+ ? e.detail.replaceAll('\n\n', '\n')
+ : e.detail
+ );
}
}}
/>
- {$i18n.t('LLMs can make mistakes. Verify important information.')}
+
{:else}
@@ -2422,13 +2464,6 @@
bind:selectedToolIds
bind:webSearchEnabled
bind:atSelectedModel
- availableToolIds={selectedModelIds.reduce((a, e, i, arr) => {
- const model = $models.find((m) => m.id === e);
- if (model?.info?.meta?.toolIds ?? false) {
- return [...new Set([...a, ...model.info.meta.toolIds])];
- }
- return a;
- }, [])}
transparentBackground={$settings?.backgroundImageUrl ?? false}
{stopResponse}
{createMessagePair}
@@ -2444,7 +2479,11 @@
on:submit={async (e) => {
if (e.detail) {
await tick();
- submitPrompt(e.detail.replaceAll('\n\n', '\n'));
+ submitPrompt(
+ ($settings?.richTextInput ?? true)
+ ? e.detail.replaceAll('\n\n', '\n')
+ : e.detail
+ );
}
}}
/>
diff --git a/src/lib/components/chat/Controls/Controls.svelte b/src/lib/components/chat/Controls/Controls.svelte
index e2b166fb3..4ae63f77e 100644
--- a/src/lib/components/chat/Controls/Controls.svelte
+++ b/src/lib/components/chat/Controls/Controls.svelte
@@ -13,6 +13,8 @@
export let models = [];
export let chatFiles = [];
export let params = {};
+
+ let showValves = false;
@@ -59,9 +61,9 @@
{/if}
-
+
-
+
diff --git a/src/lib/components/chat/Controls/Valves.svelte b/src/lib/components/chat/Controls/Valves.svelte
index 8cf7ac39b..45e504081 100644
--- a/src/lib/components/chat/Controls/Valves.svelte
+++ b/src/lib/components/chat/Controls/Valves.svelte
@@ -7,12 +7,14 @@
import {
getUserValvesSpecById as getToolUserValvesSpecById,
getUserValvesById as getToolUserValvesById,
- updateUserValvesById as updateToolUserValvesById
+ updateUserValvesById as updateToolUserValvesById,
+ getTools
} from '$lib/apis/tools';
import {
getUserValvesSpecById as getFunctionUserValvesSpecById,
getUserValvesById as getFunctionUserValvesById,
- updateUserValvesById as updateFunctionUserValvesById
+ updateUserValvesById as updateFunctionUserValvesById,
+ getFunctions
} from '$lib/apis/functions';
import Tooltip from '$lib/components/common/Tooltip.svelte';
@@ -23,6 +25,8 @@
const i18n = getContext('i18n');
+ export let show = false;
+
let tab = 'tools';
let selectedId = '';
@@ -112,77 +116,98 @@
$: if (selectedId) {
getUserValves();
}
+
+ $: if (show) {
+ init();
+ }
+
+ const init = async () => {
+ loading = true;
+
+ if ($functions === null) {
+ functions.set(await getFunctions(localStorage.token));
+ }
+ if ($tools === null) {
+ tools.set(await getTools(localStorage.token));
+ }
+
+ loading = false;
+ };
- |