forked from open-webui/open-webui
		
	feat: @model group convo
This commit is contained in:
		
							parent
							
								
									358f79f533
								
							
						
					
					
						commit
						70029d9bed
					
				
					 7 changed files with 261 additions and 15 deletions
				
			
		|  | @ -167,6 +167,45 @@ export const generateTitle = async (token: string = '', model: string, prompt: s | ||||||
| 	return res?.response ?? 'New Chat'; | 	return res?.response ?? 'New Chat'; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
|  | export const generatePrompt = async (token: string = '', model: string, conversation: string) => { | ||||||
|  | 	let error = null; | ||||||
|  | 
 | ||||||
|  | 	if (conversation === '') { | ||||||
|  | 		conversation = '[You need to start the conversation]'; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	const res = await fetch(`${OLLAMA_API_BASE_URL}/generate`, { | ||||||
|  | 		method: 'POST', | ||||||
|  | 		headers: { | ||||||
|  | 			'Content-Type': 'text/event-stream', | ||||||
|  | 			Authorization: `Bearer ${token}` | ||||||
|  | 		}, | ||||||
|  | 		body: JSON.stringify({ | ||||||
|  | 			model: model, | ||||||
|  | 			prompt: `Based on the following conversation, you are playing the role of 'USER.' Your task is to provide a thoughtful and appropriate response to the last message in the conversation, taking into account the context and tone of the discussion.
 | ||||||
|  | 
 | ||||||
|  | 			Conversation: | ||||||
|  | 			${conversation} | ||||||
|  | 
 | ||||||
|  | 			As USER, how would you respond to the latest message? If no previous conversation is provided, start a new conversation with a common, friendly greeting or a relevant question. If there is an existing conversation, continue it by providing a thoughtful, relevant, and engaging response. | ||||||
|  | 			Response: | ||||||
|  | 			` | ||||||
|  | 		}) | ||||||
|  | 	}).catch((err) => { | ||||||
|  | 		console.log(err); | ||||||
|  | 		if ('detail' in err) { | ||||||
|  | 			error = err.detail; | ||||||
|  | 		} | ||||||
|  | 		return null; | ||||||
|  | 	}); | ||||||
|  | 
 | ||||||
|  | 	if (error) { | ||||||
|  | 		throw error; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	return res; | ||||||
|  | }; | ||||||
|  | 
 | ||||||
| export const generateChatCompletion = async (token: string = '', body: object) => { | export const generateChatCompletion = async (token: string = '', body: object) => { | ||||||
| 	let error = null; | 	let error = null; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -10,6 +10,7 @@ | ||||||
| 	import AddFilesPlaceholder from '../AddFilesPlaceholder.svelte'; | 	import AddFilesPlaceholder from '../AddFilesPlaceholder.svelte'; | ||||||
| 	import { SUPPORTED_FILE_TYPE } from '$lib/constants'; | 	import { SUPPORTED_FILE_TYPE } from '$lib/constants'; | ||||||
| 	import Documents from './MessageInput/Documents.svelte'; | 	import Documents from './MessageInput/Documents.svelte'; | ||||||
|  | 	import Models from './MessageInput/Models.svelte'; | ||||||
| 
 | 
 | ||||||
| 	export let submitPrompt: Function; | 	export let submitPrompt: Function; | ||||||
| 	export let stopResponse: Function; | 	export let stopResponse: Function; | ||||||
|  | @ -18,12 +19,17 @@ | ||||||
| 	export let autoScroll = true; | 	export let autoScroll = true; | ||||||
| 
 | 
 | ||||||
| 	let filesInputElement; | 	let filesInputElement; | ||||||
|  | 
 | ||||||
| 	let promptsElement; | 	let promptsElement; | ||||||
| 	let documentsElement; | 	let documentsElement; | ||||||
|  | 	let modelsElement; | ||||||
| 
 | 
 | ||||||
| 	let inputFiles; | 	let inputFiles; | ||||||
| 	let dragged = false; | 	let dragged = false; | ||||||
| 
 | 
 | ||||||
|  | 	let user = null; | ||||||
|  | 	let chatInputPlaceholder = ''; | ||||||
|  | 
 | ||||||
| 	export let files = []; | 	export let files = []; | ||||||
| 
 | 
 | ||||||
| 	export let fileUploadEnabled = true; | 	export let fileUploadEnabled = true; | ||||||
|  | @ -35,6 +41,15 @@ | ||||||
| 
 | 
 | ||||||
| 	let speechRecognition; | 	let speechRecognition; | ||||||
| 
 | 
 | ||||||
|  | 	$: if (prompt) { | ||||||
|  | 		const chatInput = document.getElementById('chat-textarea'); | ||||||
|  | 
 | ||||||
|  | 		if (chatInput) { | ||||||
|  | 			chatInput.style.height = ''; | ||||||
|  | 			chatInput.style.height = Math.min(chatInput.scrollHeight, 200) + 'px'; | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
| 	const speechRecognitionHandler = () => { | 	const speechRecognitionHandler = () => { | ||||||
| 		// Check if SpeechRecognition is supported | 		// Check if SpeechRecognition is supported | ||||||
| 
 | 
 | ||||||
|  | @ -79,7 +94,7 @@ | ||||||
| 					console.log('recognition ended'); | 					console.log('recognition ended'); | ||||||
| 					speechRecognitionListening = false; | 					speechRecognitionListening = false; | ||||||
| 					if (prompt !== '' && $settings?.speechAutoSend === true) { | 					if (prompt !== '' && $settings?.speechAutoSend === true) { | ||||||
| 						submitPrompt(prompt); | 						submitPrompt(prompt, user); | ||||||
| 					} | 					} | ||||||
| 				}; | 				}; | ||||||
| 
 | 
 | ||||||
|  | @ -242,6 +257,14 @@ | ||||||
| 							]; | 							]; | ||||||
| 						}} | 						}} | ||||||
| 					/> | 					/> | ||||||
|  | 				{:else if prompt.charAt(0) === '@'} | ||||||
|  | 					<Models | ||||||
|  | 						bind:this={modelsElement} | ||||||
|  | 						bind:prompt | ||||||
|  | 						bind:user | ||||||
|  | 						bind:chatInputPlaceholder | ||||||
|  | 						{messages} | ||||||
|  | 					/> | ||||||
| 				{:else if messages.length == 0 && suggestionPrompts.length !== 0} | 				{:else if messages.length == 0 && suggestionPrompts.length !== 0} | ||||||
| 					<Suggestions {suggestionPrompts} {submitPrompt} /> | 					<Suggestions {suggestionPrompts} {submitPrompt} /> | ||||||
| 				{/if} | 				{/if} | ||||||
|  | @ -289,7 +312,7 @@ | ||||||
| 				<form | 				<form | ||||||
| 					class=" flex flex-col relative w-full rounded-xl border dark:border-gray-600 bg-white dark:bg-gray-800 dark:text-gray-100" | 					class=" flex flex-col relative w-full rounded-xl border dark:border-gray-600 bg-white dark:bg-gray-800 dark:text-gray-100" | ||||||
| 					on:submit|preventDefault={() => { | 					on:submit|preventDefault={() => { | ||||||
| 						submitPrompt(prompt); | 						submitPrompt(prompt, user); | ||||||
| 					}} | 					}} | ||||||
| 				> | 				> | ||||||
| 					{#if files.length > 0} | 					{#if files.length > 0} | ||||||
|  | @ -431,14 +454,18 @@ | ||||||
| 							class=" dark:bg-gray-800 dark:text-gray-100 outline-none w-full py-3 px-2 {fileUploadEnabled | 							class=" dark:bg-gray-800 dark:text-gray-100 outline-none w-full py-3 px-2 {fileUploadEnabled | ||||||
| 								? '' | 								? '' | ||||||
| 								: ' pl-4'} rounded-xl resize-none h-[48px]" | 								: ' pl-4'} rounded-xl resize-none h-[48px]" | ||||||
| 							placeholder={speechRecognitionListening ? 'Listening...' : 'Send a message'} | 							placeholder={chatInputPlaceholder !== '' | ||||||
|  | 								? chatInputPlaceholder | ||||||
|  | 								: speechRecognitionListening | ||||||
|  | 								? 'Listening...' | ||||||
|  | 								: 'Send a message'} | ||||||
| 							bind:value={prompt} | 							bind:value={prompt} | ||||||
| 							on:keypress={(e) => { | 							on:keypress={(e) => { | ||||||
| 								if (e.keyCode == 13 && !e.shiftKey) { | 								if (e.keyCode == 13 && !e.shiftKey) { | ||||||
| 									e.preventDefault(); | 									e.preventDefault(); | ||||||
| 								} | 								} | ||||||
| 								if (prompt !== '' && e.keyCode == 13 && !e.shiftKey) { | 								if (prompt !== '' && e.keyCode == 13 && !e.shiftKey) { | ||||||
| 									submitPrompt(prompt); | 									submitPrompt(prompt, user); | ||||||
| 								} | 								} | ||||||
| 							}} | 							}} | ||||||
| 							on:keydown={async (e) => { | 							on:keydown={async (e) => { | ||||||
|  | @ -473,10 +500,10 @@ | ||||||
| 									editButton?.click(); | 									editButton?.click(); | ||||||
| 								} | 								} | ||||||
| 
 | 
 | ||||||
| 								if (['/', '#'].includes(prompt.charAt(0)) && e.key === 'ArrowUp') { | 								if (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowUp') { | ||||||
| 									e.preventDefault(); | 									e.preventDefault(); | ||||||
| 
 | 
 | ||||||
| 									(promptsElement || documentsElement).selectUp(); | 									(promptsElement || documentsElement || modelsElement).selectUp(); | ||||||
| 
 | 
 | ||||||
| 									const commandOptionButton = [ | 									const commandOptionButton = [ | ||||||
| 										...document.getElementsByClassName('selected-command-option-button') | 										...document.getElementsByClassName('selected-command-option-button') | ||||||
|  | @ -484,10 +511,10 @@ | ||||||
| 									commandOptionButton.scrollIntoView({ block: 'center' }); | 									commandOptionButton.scrollIntoView({ block: 'center' }); | ||||||
| 								} | 								} | ||||||
| 
 | 
 | ||||||
| 								if (['/', '#'].includes(prompt.charAt(0)) && e.key === 'ArrowDown') { | 								if (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'ArrowDown') { | ||||||
| 									e.preventDefault(); | 									e.preventDefault(); | ||||||
| 
 | 
 | ||||||
| 									(promptsElement || documentsElement).selectDown(); | 									(promptsElement || documentsElement || modelsElement).selectDown(); | ||||||
| 
 | 
 | ||||||
| 									const commandOptionButton = [ | 									const commandOptionButton = [ | ||||||
| 										...document.getElementsByClassName('selected-command-option-button') | 										...document.getElementsByClassName('selected-command-option-button') | ||||||
|  | @ -495,7 +522,7 @@ | ||||||
| 									commandOptionButton.scrollIntoView({ block: 'center' }); | 									commandOptionButton.scrollIntoView({ block: 'center' }); | ||||||
| 								} | 								} | ||||||
| 
 | 
 | ||||||
| 								if (['/', '#'].includes(prompt.charAt(0)) && e.key === 'Enter') { | 								if (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'Enter') { | ||||||
| 									e.preventDefault(); | 									e.preventDefault(); | ||||||
| 
 | 
 | ||||||
| 									const commandOptionButton = [ | 									const commandOptionButton = [ | ||||||
|  | @ -505,7 +532,7 @@ | ||||||
| 									commandOptionButton?.click(); | 									commandOptionButton?.click(); | ||||||
| 								} | 								} | ||||||
| 
 | 
 | ||||||
| 								if (['/', '#'].includes(prompt.charAt(0)) && e.key === 'Tab') { | 								if (['/', '#', '@'].includes(prompt.charAt(0)) && e.key === 'Tab') { | ||||||
| 									e.preventDefault(); | 									e.preventDefault(); | ||||||
| 
 | 
 | ||||||
| 									const commandOptionButton = [ | 									const commandOptionButton = [ | ||||||
|  | @ -536,6 +563,7 @@ | ||||||
| 							on:input={(e) => { | 							on:input={(e) => { | ||||||
| 								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'; | ||||||
|  | 								user = null; | ||||||
| 							}} | 							}} | ||||||
| 							on:paste={(e) => { | 							on:paste={(e) => { | ||||||
| 								const clipboardData = e.clipboardData || window.clipboardData; | 								const clipboardData = e.clipboardData || window.clipboardData; | ||||||
|  |  | ||||||
							
								
								
									
										153
									
								
								src/lib/components/chat/MessageInput/Models.svelte
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								src/lib/components/chat/MessageInput/Models.svelte
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,153 @@ | ||||||
|  | <script lang="ts"> | ||||||
|  | 	import { generatePrompt } from '$lib/apis/ollama'; | ||||||
|  | 	import { models } from '$lib/stores'; | ||||||
|  | 	import { splitStream } from '$lib/utils'; | ||||||
|  | 	import { tick } from 'svelte'; | ||||||
|  | 	import toast from 'svelte-french-toast'; | ||||||
|  | 
 | ||||||
|  | 	export let prompt = ''; | ||||||
|  | 	export let user = null; | ||||||
|  | 
 | ||||||
|  | 	export let chatInputPlaceholder = ''; | ||||||
|  | 	export let messages = []; | ||||||
|  | 
 | ||||||
|  | 	let selectedIdx = 0; | ||||||
|  | 	let filteredModels = []; | ||||||
|  | 
 | ||||||
|  | 	$: filteredModels = $models | ||||||
|  | 		.filter((p) => p.name !== 'hr' && p.name.includes(prompt.split(' ')?.at(0)?.substring(1) ?? '')) | ||||||
|  | 		.sort((a, b) => a.name.localeCompare(b.name)); | ||||||
|  | 
 | ||||||
|  | 	$: if (prompt) { | ||||||
|  | 		selectedIdx = 0; | ||||||
|  | 	} | ||||||
|  | 
 | ||||||
|  | 	export const selectUp = () => { | ||||||
|  | 		selectedIdx = Math.max(0, selectedIdx - 1); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	export const selectDown = () => { | ||||||
|  | 		selectedIdx = Math.min(selectedIdx + 1, filteredModels.length - 1); | ||||||
|  | 	}; | ||||||
|  | 
 | ||||||
|  | 	const confirmSelect = async (model) => { | ||||||
|  | 		// dispatch('select', model); | ||||||
|  | 		prompt = ''; | ||||||
|  | 		user = JSON.parse(JSON.stringify(model.name)); | ||||||
|  | 		await tick(); | ||||||
|  | 
 | ||||||
|  | 		chatInputPlaceholder = `'${model.name}' is thinking...`; | ||||||
|  | 
 | ||||||
|  | 		const chatInputElement = document.getElementById('chat-textarea'); | ||||||
|  | 
 | ||||||
|  | 		await tick(); | ||||||
|  | 		chatInputElement?.focus(); | ||||||
|  | 		await tick(); | ||||||
|  | 
 | ||||||
|  | 		const convoText = messages.reduce((a, message, i, arr) => { | ||||||
|  | 			return `${a}### ${message.role.toUpperCase()}\n${message.content}\n\n`; | ||||||
|  | 		}, ''); | ||||||
|  | 
 | ||||||
|  | 		const res = await generatePrompt(localStorage.token, model.name, convoText); | ||||||
|  | 
 | ||||||
|  | 		if (res && res.ok) { | ||||||
|  | 			const reader = res.body | ||||||
|  | 				.pipeThrough(new TextDecoderStream()) | ||||||
|  | 				.pipeThrough(splitStream('\n')) | ||||||
|  | 				.getReader(); | ||||||
|  | 
 | ||||||
|  | 			while (true) { | ||||||
|  | 				const { value, done } = await reader.read(); | ||||||
|  | 				if (done) { | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 
 | ||||||
|  | 				try { | ||||||
|  | 					let lines = value.split('\n'); | ||||||
|  | 
 | ||||||
|  | 					for (const line of lines) { | ||||||
|  | 						if (line !== '') { | ||||||
|  | 							console.log(line); | ||||||
|  | 							let data = JSON.parse(line); | ||||||
|  | 
 | ||||||
|  | 							if ('detail' in data) { | ||||||
|  | 								throw data; | ||||||
|  | 							} | ||||||
|  | 
 | ||||||
|  | 							if (data.done == false) { | ||||||
|  | 								if (prompt == '' && data.response == '\n') { | ||||||
|  | 									continue; | ||||||
|  | 								} else { | ||||||
|  | 									prompt += data.response; | ||||||
|  | 									console.log(data.response); | ||||||
|  | 									chatInputElement.scrollTop = chatInputElement.scrollHeight; | ||||||
|  | 									await tick(); | ||||||
|  | 								} | ||||||
|  | 							} | ||||||
|  | 						} | ||||||
|  | 					} | ||||||
|  | 				} catch (error) { | ||||||
|  | 					console.log(error); | ||||||
|  | 					if ('detail' in error) { | ||||||
|  | 						toast.error(error.detail); | ||||||
|  | 					} | ||||||
|  | 					break; | ||||||
|  | 				} | ||||||
|  | 			} | ||||||
|  | 		} else { | ||||||
|  | 			if (res !== null) { | ||||||
|  | 				const error = await res.json(); | ||||||
|  | 				console.log(error); | ||||||
|  | 				if ('detail' in error) { | ||||||
|  | 					toast.error(error.detail); | ||||||
|  | 				} else { | ||||||
|  | 					toast.error(error.error); | ||||||
|  | 				} | ||||||
|  | 			} else { | ||||||
|  | 				toast.error(`Uh-oh! There was an issue connecting to Ollama.`); | ||||||
|  | 			} | ||||||
|  | 		} | ||||||
|  | 
 | ||||||
|  | 		chatInputPlaceholder = ''; | ||||||
|  | 
 | ||||||
|  | 		console.log(user); | ||||||
|  | 	}; | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | {#if filteredModels.length > 0} | ||||||
|  | 	<div class="md:px-2 mb-3 text-left w-full"> | ||||||
|  | 		<div class="flex w-full rounded-lg border border-gray-100 dark:border-gray-700"> | ||||||
|  | 			<div class=" bg-gray-100 dark:bg-gray-700 w-10 rounded-l-lg text-center"> | ||||||
|  | 				<div class=" text-lg font-semibold mt-2">@</div> | ||||||
|  | 			</div> | ||||||
|  | 
 | ||||||
|  | 			<div class="max-h-60 flex flex-col w-full rounded-r-lg"> | ||||||
|  | 				<div class=" overflow-y-auto bg-white p-2 rounded-tr-lg space-y-0.5"> | ||||||
|  | 					{#each filteredModels as model, modelIdx} | ||||||
|  | 						<button | ||||||
|  | 							class=" px-3 py-1.5 rounded-lg w-full text-left {modelIdx === selectedIdx | ||||||
|  | 								? ' bg-gray-100 selected-command-option-button' | ||||||
|  | 								: ''}" | ||||||
|  | 							type="button" | ||||||
|  | 							on:click={() => { | ||||||
|  | 								confirmSelect(model); | ||||||
|  | 							}} | ||||||
|  | 							on:mousemove={() => { | ||||||
|  | 								selectedIdx = modelIdx; | ||||||
|  | 							}} | ||||||
|  | 							on:focus={() => {}} | ||||||
|  | 						> | ||||||
|  | 							<div class=" font-medium text-black line-clamp-1"> | ||||||
|  | 								{model.name} | ||||||
|  | 							</div> | ||||||
|  | 
 | ||||||
|  | 							<!-- <div class=" text-xs text-gray-600 line-clamp-1"> | ||||||
|  | 								{doc.title} | ||||||
|  | 							</div> --> | ||||||
|  | 						</button> | ||||||
|  | 					{/each} | ||||||
|  | 				</div> | ||||||
|  | 			</div> | ||||||
|  | 		</div> | ||||||
|  | 	</div> | ||||||
|  | {/if} | ||||||
|  | @ -9,7 +9,7 @@ | ||||||
| 			<button | 			<button | ||||||
| 				class=" flex-1 flex justify-between w-full h-full px-4 py-2.5 bg-white hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg transition group" | 				class=" flex-1 flex justify-between w-full h-full px-4 py-2.5 bg-white hover:bg-gray-50 dark:bg-gray-800 dark:hover:bg-gray-700 outline outline-1 outline-gray-200 dark:outline-gray-600 rounded-lg transition group" | ||||||
| 				on:click={() => { | 				on:click={() => { | ||||||
| 					submitPrompt(prompt.content); | 					submitPrompt(prompt.content, ''); | ||||||
| 				}} | 				}} | ||||||
| 			> | 			> | ||||||
| 				<div class="flex flex-col text-left self-center"> | 				<div class="flex flex-col text-left self-center"> | ||||||
|  |  | ||||||
|  | @ -2,6 +2,8 @@ | ||||||
| 	import { tick } from 'svelte'; | 	import { tick } from 'svelte'; | ||||||
| 	import Name from './Name.svelte'; | 	import Name from './Name.svelte'; | ||||||
| 	import ProfileImage from './ProfileImage.svelte'; | 	import ProfileImage from './ProfileImage.svelte'; | ||||||
|  | 	import { modelfiles } from '$lib/stores'; | ||||||
|  | 	import { stringify } from 'postcss'; | ||||||
| 
 | 
 | ||||||
| 	export let user; | 	export let user; | ||||||
| 	export let message; | 	export let message; | ||||||
|  | @ -42,11 +44,25 @@ | ||||||
| </script> | </script> | ||||||
| 
 | 
 | ||||||
| <div class=" flex w-full"> | <div class=" flex w-full"> | ||||||
| 	<ProfileImage src={user?.profile_image_url ?? '/user.png'} /> | 	<ProfileImage | ||||||
|  | 		src={message.user | ||||||
|  | 			? $modelfiles.find((modelfile) => modelfile.tagName === message.user)?.imageUrl ?? '/user.png' | ||||||
|  | 			: user?.profile_image_url ?? '/user.png'} | ||||||
|  | 	/> | ||||||
| 
 | 
 | ||||||
| 	<div class="w-full overflow-hidden"> | 	<div class="w-full overflow-hidden"> | ||||||
| 		<div class="user-message"> | 		<div class="user-message"> | ||||||
| 			<Name>You</Name> | 			<Name> | ||||||
|  | 				{#if message.user} | ||||||
|  | 					{#if $modelfiles.map((modelfile) => modelfile.tagName).includes(message.user)} | ||||||
|  | 						{$modelfiles.find((modelfile) => modelfile.tagName === message.user)?.title} | ||||||
|  | 					{:else} | ||||||
|  | 						You <span class=" text-gray-500 text-sm font-medium">{message?.user ?? ''}</span> | ||||||
|  | 					{/if} | ||||||
|  | 				{:else} | ||||||
|  | 					You | ||||||
|  | 				{/if} | ||||||
|  | 			</Name> | ||||||
| 		</div> | 		</div> | ||||||
| 
 | 
 | ||||||
| 		<div | 		<div | ||||||
|  |  | ||||||
|  | @ -116,7 +116,7 @@ | ||||||
| 	// Ollama functions | 	// Ollama functions | ||||||
| 	////////////////////////// | 	////////////////////////// | ||||||
| 
 | 
 | ||||||
| 	const submitPrompt = async (userPrompt) => { | 	const submitPrompt = async (userPrompt, _user = null) => { | ||||||
| 		console.log('submitPrompt', $chatId); | 		console.log('submitPrompt', $chatId); | ||||||
| 
 | 
 | ||||||
| 		if (selectedModels.includes('')) { | 		if (selectedModels.includes('')) { | ||||||
|  | @ -143,6 +143,7 @@ | ||||||
| 				parentId: messages.length !== 0 ? messages.at(-1).id : null, | 				parentId: messages.length !== 0 ? messages.at(-1).id : null, | ||||||
| 				childrenIds: [], | 				childrenIds: [], | ||||||
| 				role: 'user', | 				role: 'user', | ||||||
|  | 				user: _user ?? undefined, | ||||||
| 				content: userPrompt, | 				content: userPrompt, | ||||||
| 				files: files.length > 0 ? files : undefined | 				files: files.length > 0 ? files : undefined | ||||||
| 			}; | 			}; | ||||||
|  |  | ||||||
|  | @ -135,7 +135,8 @@ | ||||||
| 	// Ollama functions | 	// Ollama functions | ||||||
| 	////////////////////////// | 	////////////////////////// | ||||||
| 
 | 
 | ||||||
| 	const submitPrompt = async (userPrompt) => { | 	const submitPrompt = async (userPrompt, user) => { | ||||||
|  | 		console.log(userPrompt, user); | ||||||
| 		console.log('submitPrompt', $chatId); | 		console.log('submitPrompt', $chatId); | ||||||
| 
 | 
 | ||||||
| 		if (selectedModels.includes('')) { | 		if (selectedModels.includes('')) { | ||||||
|  | @ -143,6 +144,14 @@ | ||||||
| 		} else if (messages.length != 0 && messages.at(-1).done != true) { | 		} else if (messages.length != 0 && messages.at(-1).done != true) { | ||||||
| 			// Response not done | 			// Response not done | ||||||
| 			console.log('wait'); | 			console.log('wait'); | ||||||
|  | 		} else if ( | ||||||
|  | 			files.length > 0 && | ||||||
|  | 			files.filter((file) => file.upload_status === false).length > 0 | ||||||
|  | 		) { | ||||||
|  | 			// Upload not done | ||||||
|  | 			toast.error( | ||||||
|  | 				`Oops! Hold tight! Your files are still in the processing oven. We're cooking them up to perfection. Please be patient and we'll let you know once they're ready.` | ||||||
|  | 			); | ||||||
| 		} else { | 		} else { | ||||||
| 			// Reset chat message textarea height | 			// Reset chat message textarea height | ||||||
| 			document.getElementById('chat-textarea').style.height = ''; | 			document.getElementById('chat-textarea').style.height = ''; | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Timothy J. Baek
						Timothy J. Baek