mirror of
https://github.com/open-webui/open-webui
synced 2025-06-26 18:26:48 +00:00
feat: mermaid rendering support
This commit is contained in:
parent
a9e5003c4f
commit
3d74c04f50
@ -498,6 +498,8 @@ async def chat_completed(form_data: dict, user=Depends(get_verified_user)):
|
|||||||
]
|
]
|
||||||
sorted_filters = sorted(filters, key=lambda x: x["pipeline"]["priority"])
|
sorted_filters = sorted(filters, key=lambda x: x["pipeline"]["priority"])
|
||||||
|
|
||||||
|
print(model_id)
|
||||||
|
|
||||||
if model_id in app.state.MODELS:
|
if model_id in app.state.MODELS:
|
||||||
model = app.state.MODELS[model_id]
|
model = app.state.MODELS[model_id]
|
||||||
if "pipeline" in model:
|
if "pipeline" in model:
|
||||||
|
1118
package-lock.json
generated
1118
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -63,6 +63,7 @@
|
|||||||
"js-sha256": "^0.10.1",
|
"js-sha256": "^0.10.1",
|
||||||
"katex": "^0.16.9",
|
"katex": "^0.16.9",
|
||||||
"marked": "^9.1.0",
|
"marked": "^9.1.0",
|
||||||
|
"mermaid": "^10.9.1",
|
||||||
"pyodide": "^0.26.0-alpha.4",
|
"pyodide": "^0.26.0-alpha.4",
|
||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"svelte-sonner": "^0.3.19",
|
"svelte-sonner": "^0.3.19",
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
|
import mermaid from 'mermaid';
|
||||||
|
|
||||||
import { getContext, onMount, tick } from 'svelte';
|
import { getContext, onMount, tick } from 'svelte';
|
||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
@ -246,6 +247,39 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const chatCompletedHandler = async (model, messages) => {
|
||||||
|
await mermaid.run({
|
||||||
|
querySelector: '.mermaid'
|
||||||
|
});
|
||||||
|
|
||||||
|
const res = await chatCompleted(localStorage.token, {
|
||||||
|
model: model.id,
|
||||||
|
messages: messages.map((m) => ({
|
||||||
|
id: m.id,
|
||||||
|
role: m.role,
|
||||||
|
content: m.content,
|
||||||
|
timestamp: m.timestamp
|
||||||
|
})),
|
||||||
|
chat_id: $chatId
|
||||||
|
}).catch((error) => {
|
||||||
|
console.error(error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (res !== null) {
|
||||||
|
// Update chat history with the new messages
|
||||||
|
for (const message of res.messages) {
|
||||||
|
history.messages[message.id] = {
|
||||||
|
...history.messages[message.id],
|
||||||
|
...(history.messages[message.id].content !== message.content
|
||||||
|
? { originalContent: history.messages[message.id].content }
|
||||||
|
: {}),
|
||||||
|
...message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
// Ollama functions
|
// Ollama functions
|
||||||
//////////////////////////
|
//////////////////////////
|
||||||
@ -613,32 +647,7 @@
|
|||||||
controller.abort('User: Stop Response');
|
controller.abort('User: Stop Response');
|
||||||
} else {
|
} else {
|
||||||
const messages = createMessagesList(responseMessageId);
|
const messages = createMessagesList(responseMessageId);
|
||||||
const res = await chatCompleted(localStorage.token, {
|
await chatCompletedHandler(model, messages);
|
||||||
model: model,
|
|
||||||
messages: messages.map((m) => ({
|
|
||||||
id: m.id,
|
|
||||||
role: m.role,
|
|
||||||
content: m.content,
|
|
||||||
timestamp: m.timestamp
|
|
||||||
})),
|
|
||||||
chat_id: $chatId
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res !== null) {
|
|
||||||
// Update chat history with the new messages
|
|
||||||
for (const message of res.messages) {
|
|
||||||
history.messages[message.id] = {
|
|
||||||
...history.messages[message.id],
|
|
||||||
...(history.messages[message.id].content !== message.content
|
|
||||||
? { originalContent: history.messages[message.id].content }
|
|
||||||
: {}),
|
|
||||||
...message
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
@ -893,32 +902,7 @@
|
|||||||
} else {
|
} else {
|
||||||
const messages = createMessagesList(responseMessageId);
|
const messages = createMessagesList(responseMessageId);
|
||||||
|
|
||||||
const res = await chatCompleted(localStorage.token, {
|
await chatCompletedHandler(model, messages);
|
||||||
model: model.id,
|
|
||||||
messages: messages.map((m) => ({
|
|
||||||
id: m.id,
|
|
||||||
role: m.role,
|
|
||||||
content: m.content,
|
|
||||||
timestamp: m.timestamp
|
|
||||||
})),
|
|
||||||
chat_id: $chatId
|
|
||||||
}).catch((error) => {
|
|
||||||
console.error(error);
|
|
||||||
return null;
|
|
||||||
});
|
|
||||||
|
|
||||||
if (res !== null) {
|
|
||||||
// Update chat history with the new messages
|
|
||||||
for (const message of res.messages) {
|
|
||||||
history.messages[message.id] = {
|
|
||||||
...history.messages[message.id],
|
|
||||||
...(history.messages[message.id].content !== message.content
|
|
||||||
? { originalContent: history.messages[message.id].content }
|
|
||||||
: {}),
|
|
||||||
...message
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { v4 as uuidv4 } from 'uuid';
|
import { v4 as uuidv4 } from 'uuid';
|
||||||
|
|
||||||
import { chats, config, settings, user as _user, mobile } from '$lib/stores';
|
import { chats, config, settings, user as _user, mobile } from '$lib/stores';
|
||||||
import { tick, getContext } from 'svelte';
|
import { tick, getContext, onMount } from 'svelte';
|
||||||
|
|
||||||
import { toast } from 'svelte-sonner';
|
import { toast } from 'svelte-sonner';
|
||||||
import { getChatList, updateChatById } from '$lib/apis/chats';
|
import { getChatList, updateChatById } from '$lib/apis/chats';
|
||||||
|
@ -5,6 +5,7 @@
|
|||||||
import tippy from 'tippy.js';
|
import tippy from 'tippy.js';
|
||||||
import auto_render from 'katex/dist/contrib/auto-render.mjs';
|
import auto_render from 'katex/dist/contrib/auto-render.mjs';
|
||||||
import 'katex/dist/katex.min.css';
|
import 'katex/dist/katex.min.css';
|
||||||
|
import mermaid from 'mermaid';
|
||||||
|
|
||||||
import { fade } from 'svelte/transition';
|
import { fade } from 'svelte/transition';
|
||||||
import { createEventDispatcher } from 'svelte';
|
import { createEventDispatcher } from 'svelte';
|
||||||
@ -343,6 +344,10 @@
|
|||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
await tick();
|
await tick();
|
||||||
renderStyling();
|
renderStyling();
|
||||||
|
|
||||||
|
await mermaid.run({
|
||||||
|
querySelector: '.mermaid'
|
||||||
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@ -458,11 +463,15 @@
|
|||||||
<!-- unless message.error === true which is legacy error handling, where the error message is stored in message.content -->
|
<!-- unless message.error === true which is legacy error handling, where the error message is stored in message.content -->
|
||||||
{#each tokens as token, tokenIdx}
|
{#each tokens as token, tokenIdx}
|
||||||
{#if token.type === 'code'}
|
{#if token.type === 'code'}
|
||||||
|
{#if token.lang === 'mermaid'}
|
||||||
|
<pre class="mermaid">{revertSanitizedResponseContent(token.text)}</pre>
|
||||||
|
{:else}
|
||||||
<CodeBlock
|
<CodeBlock
|
||||||
id={`${message.id}-${tokenIdx}`}
|
id={`${message.id}-${tokenIdx}`}
|
||||||
lang={token?.lang ?? ''}
|
lang={token?.lang ?? ''}
|
||||||
code={revertSanitizedResponseContent(token?.text ?? '')}
|
code={revertSanitizedResponseContent(token?.text ?? '')}
|
||||||
/>
|
/>
|
||||||
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
{@html marked.parse(token.raw, {
|
{@html marked.parse(token.raw, {
|
||||||
...defaults,
|
...defaults,
|
||||||
|
Loading…
Reference in New Issue
Block a user