Support for Images in Prompt Suggestions

This commit is contained in:
Luca Gutzeit 2025-03-31 11:13:55 +02:00
parent 5ce6c8ced3
commit 81f239849a
5 changed files with 34 additions and 9 deletions

View File

@ -206,6 +206,7 @@ async def set_models_config(
class PromptSuggestion(BaseModel):
title: list[str]
content: str
imageUrl: str = ""
class SetDefaultSuggestionsForm(BaseModel):

View File

@ -2015,6 +2015,7 @@
bind:history
bind:autoScroll
bind:prompt
bind:files
{selectedModels}
{atSelectedModel}
{sendPrompt}

View File

@ -30,6 +30,7 @@
export let user = $_user;
export let prompt;
export let files = [];
export let history = {};
export let selectedModels;
export let atSelectedModel;
@ -394,15 +395,22 @@
modelIds={selectedModels}
{atSelectedModel}
submitPrompt={async (p) => {
let text = p;
const {content, imageUrl} = p;
let text = content;
if (p.includes('{{CLIPBOARD}}')) {
if (content.includes('{{CLIPBOARD}}')) {
const clipboardText = await navigator.clipboard.readText().catch((err) => {
toast.error($i18n.t('Failed to read clipboard contents'));
return '{{CLIPBOARD}}';
});
text = p.replaceAll('{{CLIPBOARD}}', clipboardText);
text = content.replaceAll('{{CLIPBOARD}}', clipboardText);
console.log('Clipboard text:', clipboardText, text);
}
if (imageUrl !== "") {
files = [{ type: 'image', url: imageUrl }]
}
prompt = text;

View File

@ -43,18 +43,23 @@
let models = [];
const selectSuggestionPrompt = async (p) => {
let text = p;
const {content, imageUrl} = p;
let text = content;
if (p.includes('{{CLIPBOARD}}')) {
if (content.includes('{{CLIPBOARD}}')) {
const clipboardText = await navigator.clipboard.readText().catch((err) => {
toast.error($i18n.t('Failed to read clipboard contents'));
return '{{CLIPBOARD}}';
});
text = p.replaceAll('{{CLIPBOARD}}', clipboardText);
text = content.replaceAll('{{CLIPBOARD}}', clipboardText);
console.log('Clipboard text:', clipboardText, text);
}
if (imageUrl !== "") {
files = [{ type: 'image', url: imageUrl }]
}
prompt = text;

View File

@ -5,6 +5,8 @@
import { WEBUI_NAME } from '$lib/stores';
import { WEBUI_VERSION } from '$lib/constants';
import Image from '../common/Image.svelte';
const i18n = getContext('i18n');
const dispatch = createEventDispatcher();
@ -83,11 +85,11 @@
{#if filteredPrompts.length > 0}
{#each filteredPrompts as prompt, idx (prompt.id || prompt.content)}
<button
class="waterfall flex flex-col flex-1 shrink-0 w-full justify-between
px-3 py-2 rounded-xl bg-transparent hover:bg-black/5
class="waterfall flex flex-row flex-1 shrink-0 w-full justify-between
pl-3 pr-2 py-2 rounded-xl bg-transparent hover:bg-black/5
dark:hover:bg-white/5 transition group"
style="animation-delay: {idx * 60}ms"
on:click={() => dispatch('select', prompt.content)}
on:click={() => dispatch('select', {content: prompt.content, imageUrl: prompt.imageUrl})}
>
<div class="flex flex-col text-left">
{#if prompt.title && prompt.title[0] !== ''}
@ -108,6 +110,14 @@
<div class="text-xs text-gray-500 font-normal line-clamp-1">{$i18n.t('Prompt')}</div>
{/if}
</div>
{#if prompt.imageUrl && prompt.imageUrl !== ''}
<Image
src={prompt.imageUrl}
alt="input"
className="outline-hidden focus:outline-hidden pointer-events-none"
imageClassName=" size-10 rounded-lg object-cover"
/>
{/if}
</button>
{/each}
{/if}