mirror of
https://git.mirrors.martin98.com/https://github.com/open-webui/open-webui
synced 2025-08-19 20:29:10 +08:00
enh: generate title
This commit is contained in:
parent
aa374823ce
commit
9e1400f055
@ -539,7 +539,7 @@ export const updateTaskConfig = async (token: string, config: object) => {
|
|||||||
export const generateTitle = async (
|
export const generateTitle = async (
|
||||||
token: string = '',
|
token: string = '',
|
||||||
model: string,
|
model: string,
|
||||||
messages: string[],
|
messages: object[],
|
||||||
chat_id?: string
|
chat_id?: string
|
||||||
) => {
|
) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
@ -573,7 +573,39 @@ export const generateTitle = async (
|
|||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
return res?.choices[0]?.message?.content.replace(/["']/g, '') ?? 'New Chat';
|
try {
|
||||||
|
// Step 1: Safely extract the response string
|
||||||
|
const response = res?.choices[0]?.message?.content ?? '';
|
||||||
|
|
||||||
|
// Step 2: Attempt to fix common JSON format issues like single quotes
|
||||||
|
const sanitizedResponse = response.replace(/['‘’`]/g, '"'); // Convert single quotes to double quotes for valid JSON
|
||||||
|
|
||||||
|
// Step 3: Find the relevant JSON block within the response
|
||||||
|
const jsonStartIndex = sanitizedResponse.indexOf('{');
|
||||||
|
const jsonEndIndex = sanitizedResponse.lastIndexOf('}');
|
||||||
|
|
||||||
|
// Step 4: Check if we found a valid JSON block (with both `{` and `}`)
|
||||||
|
if (jsonStartIndex !== -1 && jsonEndIndex !== -1) {
|
||||||
|
const jsonResponse = sanitizedResponse.substring(jsonStartIndex, jsonEndIndex + 1);
|
||||||
|
|
||||||
|
// Step 5: Parse the JSON block
|
||||||
|
const parsed = JSON.parse(jsonResponse);
|
||||||
|
|
||||||
|
// Step 6: If there's a "tags" key, return the tags array; otherwise, return an empty array
|
||||||
|
if (parsed && parsed.title) {
|
||||||
|
return parsed.title;
|
||||||
|
} else {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If no valid JSON block found, return an empty array
|
||||||
|
return null;
|
||||||
|
} catch (e) {
|
||||||
|
// Catch and safely return empty array on any parsing errors
|
||||||
|
console.error('Failed to parse response: ', e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateTags = async (
|
export const generateTags = async (
|
||||||
|
@ -39,6 +39,7 @@
|
|||||||
import XMark from '$lib/components/icons/XMark.svelte';
|
import XMark from '$lib/components/icons/XMark.svelte';
|
||||||
import Document from '$lib/components/icons/Document.svelte';
|
import Document from '$lib/components/icons/Document.svelte';
|
||||||
import Sparkles from '$lib/components/icons/Sparkles.svelte';
|
import Sparkles from '$lib/components/icons/Sparkles.svelte';
|
||||||
|
import { generateTitle } from '$lib/apis';
|
||||||
|
|
||||||
export let className = '';
|
export let className = '';
|
||||||
|
|
||||||
@ -136,6 +137,7 @@
|
|||||||
|
|
||||||
let itemElement;
|
let itemElement;
|
||||||
|
|
||||||
|
let generating = false;
|
||||||
let doubleClicked = false;
|
let doubleClicked = false;
|
||||||
let dragged = false;
|
let dragged = false;
|
||||||
let x = 0;
|
let x = 0;
|
||||||
@ -223,6 +225,40 @@
|
|||||||
if (input) input.focus();
|
if (input) input.focus();
|
||||||
}, 0);
|
}, 0);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const generateTitleHandler = async () => {
|
||||||
|
generating = true;
|
||||||
|
if (!chat) {
|
||||||
|
chat = await getChatById(localStorage.token, id);
|
||||||
|
}
|
||||||
|
|
||||||
|
const messages = (chat.chat?.messages ?? []).map((message) => {
|
||||||
|
return {
|
||||||
|
role: message.role,
|
||||||
|
content: message.content
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
const model = chat.chat.models.at(0) ?? chat.models.at(0) ?? '';
|
||||||
|
|
||||||
|
chatTitle = '';
|
||||||
|
|
||||||
|
const generatedTitle = await generateTitle(localStorage.token, model, messages).catch(
|
||||||
|
(error) => {
|
||||||
|
toast.error(`${error}`);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
if (generatedTitle) {
|
||||||
|
if (generatedTitle !== title) {
|
||||||
|
editChatTitle(id, generatedTitle);
|
||||||
|
}
|
||||||
|
|
||||||
|
confirmEdit = false;
|
||||||
|
}
|
||||||
|
generating = false;
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ShareChatModal bind:show={showShareChatModal} chatId={id} />
|
<ShareChatModal bind:show={showShareChatModal} chatId={id} />
|
||||||
@ -264,14 +300,22 @@
|
|||||||
? 'bg-gray-200 dark:bg-gray-900'
|
? 'bg-gray-200 dark:bg-gray-900'
|
||||||
: selected
|
: selected
|
||||||
? 'bg-gray-100 dark:bg-gray-950'
|
? 'bg-gray-100 dark:bg-gray-950'
|
||||||
: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis"
|
: 'group-hover:bg-gray-100 dark:group-hover:bg-gray-950'} whitespace-nowrap text-ellipsis relative {generating
|
||||||
|
? 'cursor-not-allowed'
|
||||||
|
: ''}"
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="chat-title-input-{id}"
|
id="chat-title-input-{id}"
|
||||||
bind:value={chatTitle}
|
bind:value={chatTitle}
|
||||||
class=" bg-transparent w-full outline-hidden mr-10"
|
class=" bg-transparent w-full outline-hidden mr-10"
|
||||||
|
placeholder={generating ? $i18n.t('Generating...') : ''}
|
||||||
on:keydown={chatTitleInputKeydownHandler}
|
on:keydown={chatTitleInputKeydownHandler}
|
||||||
on:blur={async (e) => {
|
on:blur={async (e) => {
|
||||||
|
// check if target is generate button
|
||||||
|
if (e.relatedTarget?.id === 'generate-title-button') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (doubleClicked) {
|
if (doubleClicked) {
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
e.stopPropagation();
|
e.stopPropagation();
|
||||||
@ -360,7 +404,17 @@
|
|||||||
class="flex self-center items-center space-x-1.5 z-10 translate-y-[0.5px] -translate-x-[0.5px]"
|
class="flex self-center items-center space-x-1.5 z-10 translate-y-[0.5px] -translate-x-[0.5px]"
|
||||||
>
|
>
|
||||||
<Tooltip content={$i18n.t('Generate')}>
|
<Tooltip content={$i18n.t('Generate')}>
|
||||||
<button class=" self-center dark:hover:text-white transition" on:click={() => {}}>
|
<button
|
||||||
|
class=" self-center dark:hover:text-white transition"
|
||||||
|
id="generate-title-button"
|
||||||
|
on:click={(e) => {
|
||||||
|
e.preventDefault();
|
||||||
|
e.stopImmediatePropagation();
|
||||||
|
e.stopPropagation();
|
||||||
|
|
||||||
|
generateTitleHandler();
|
||||||
|
}}
|
||||||
|
>
|
||||||
<Sparkles strokeWidth="2" />
|
<Sparkles strokeWidth="2" />
|
||||||
</button>
|
</button>
|
||||||
</Tooltip>
|
</Tooltip>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user