mirror of
https://github.com/open-webui/open-webui
synced 2024-11-24 21:13:59 +00:00
feat: character card support
This commit is contained in:
parent
f1b350cbe6
commit
ab62228877
14
package-lock.json
generated
14
package-lock.json
generated
@ -34,6 +34,7 @@
|
|||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"svelte-sonner": "^0.3.19",
|
"svelte-sonner": "^0.3.19",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
|
"turndown": "^7.2.0",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
@ -1000,6 +1001,11 @@
|
|||||||
"svelte": ">=3 <5"
|
"svelte": ">=3 <5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@mixmark-io/domino": {
|
||||||
|
"version": "2.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz",
|
||||||
|
"integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw=="
|
||||||
|
},
|
||||||
"node_modules/@nodelib/fs.scandir": {
|
"node_modules/@nodelib/fs.scandir": {
|
||||||
"version": "2.1.5",
|
"version": "2.1.5",
|
||||||
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
|
||||||
@ -9077,6 +9083,14 @@
|
|||||||
"node": "*"
|
"node": "*"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/turndown": {
|
||||||
|
"version": "7.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz",
|
||||||
|
"integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==",
|
||||||
|
"dependencies": {
|
||||||
|
"@mixmark-io/domino": "^2.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tweetnacl": {
|
"node_modules/tweetnacl": {
|
||||||
"version": "0.14.5",
|
"version": "0.14.5",
|
||||||
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
"resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
|
||||||
|
@ -74,6 +74,7 @@
|
|||||||
"sortablejs": "^1.15.2",
|
"sortablejs": "^1.15.2",
|
||||||
"svelte-sonner": "^0.3.19",
|
"svelte-sonner": "^0.3.19",
|
||||||
"tippy.js": "^6.3.7",
|
"tippy.js": "^6.3.7",
|
||||||
|
"turndown": "^7.2.0",
|
||||||
"uuid": "^9.0.1"
|
"uuid": "^9.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
|
|
||||||
import Suggestions from '../MessageInput/Suggestions.svelte';
|
import Suggestions from '../MessageInput/Suggestions.svelte';
|
||||||
import { sanitizeResponseContent } from '$lib/utils';
|
import { sanitizeResponseContent } from '$lib/utils';
|
||||||
|
import Tooltip from '$lib/components/common/Tooltip.svelte';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -41,14 +42,23 @@
|
|||||||
selectedModelIdx = modelIdx;
|
selectedModelIdx = modelIdx;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<img
|
<Tooltip
|
||||||
crossorigin="anonymous"
|
content={marked.parse(
|
||||||
src={model?.info?.meta?.profile_image_url ??
|
sanitizeResponseContent(models[selectedModelIdx]?.info?.meta?.description)
|
||||||
($i18n.language === 'dg-DG' ? `/doge.png` : `${WEBUI_BASE_URL}/static/favicon.png`)}
|
)}
|
||||||
class=" size-[2.7rem] rounded-full border-[1px] border-gray-200 dark:border-none"
|
placement="right"
|
||||||
alt="logo"
|
>
|
||||||
draggable="false"
|
<img
|
||||||
/>
|
crossorigin="anonymous"
|
||||||
|
src={model?.info?.meta?.profile_image_url ??
|
||||||
|
($i18n.language === 'dg-DG'
|
||||||
|
? `/doge.png`
|
||||||
|
: `${WEBUI_BASE_URL}/static/favicon.png`)}
|
||||||
|
class=" size-[2.7rem] rounded-full border-[1px] border-gray-200 dark:border-none"
|
||||||
|
alt="logo"
|
||||||
|
draggable="false"
|
||||||
|
/>
|
||||||
|
</Tooltip>
|
||||||
</button>
|
</button>
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
@ -126,7 +126,7 @@
|
|||||||
: selected
|
: selected
|
||||||
? 'from-gray-100 dark:from-gray-950'
|
? 'from-gray-100 dark:from-gray-950'
|
||||||
: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
|
: 'invisible group-hover:visible from-gray-100 dark:from-gray-950'}
|
||||||
absolute right-[10px] top-[10px] pr-2 pl-5 bg-gradient-to-l from-80%
|
absolute right-[10px] top-[6px] py-1 pr-2 pl-5 bg-gradient-to-l from-80%
|
||||||
|
|
||||||
to-transparent"
|
to-transparent"
|
||||||
on:mouseenter={(e) => {
|
on:mouseenter={(e) => {
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
import { goto } from '$app/navigation';
|
import { goto } from '$app/navigation';
|
||||||
import { settings, user, config, models, tools } from '$lib/stores';
|
import { settings, user, config, models, tools } from '$lib/stores';
|
||||||
|
|
||||||
|
import TurndownService from 'turndown';
|
||||||
|
|
||||||
import { onMount, tick, getContext } from 'svelte';
|
import { onMount, tick, getContext } from 'svelte';
|
||||||
import { addNewModel, getModelById, getModelInfos } from '$lib/apis/models';
|
import { addNewModel, getModelById, getModelInfos } from '$lib/apis/models';
|
||||||
import { getModels } from '$lib/apis';
|
import { getModels } from '$lib/apis';
|
||||||
@ -14,6 +16,7 @@
|
|||||||
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
|
import Knowledge from '$lib/components/workspace/Models/Knowledge.svelte';
|
||||||
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
|
import ToolsSelector from '$lib/components/workspace/Models/ToolsSelector.svelte';
|
||||||
import { stringify } from 'postcss';
|
import { stringify } from 'postcss';
|
||||||
|
import { parseFile } from '$lib/utils/characters';
|
||||||
|
|
||||||
const i18n = getContext('i18n');
|
const i18n = getContext('i18n');
|
||||||
|
|
||||||
@ -60,7 +63,10 @@
|
|||||||
let knowledge = [];
|
let knowledge = [];
|
||||||
|
|
||||||
$: if (name) {
|
$: if (name) {
|
||||||
id = name.replace(/\s+/g, '-').toLowerCase();
|
id = name
|
||||||
|
.replace(/\s+/g, '-')
|
||||||
|
.replace(/[^a-zA-Z0-9-]/g, '')
|
||||||
|
.toLowerCase();
|
||||||
}
|
}
|
||||||
|
|
||||||
const addUsage = (base_model_id) => {
|
const addUsage = (base_model_id) => {
|
||||||
@ -213,9 +219,29 @@
|
|||||||
accept="image/*"
|
accept="image/*"
|
||||||
on:change={() => {
|
on:change={() => {
|
||||||
let reader = new FileReader();
|
let reader = new FileReader();
|
||||||
reader.onload = (event) => {
|
reader.onload = async (event) => {
|
||||||
let originalImageUrl = `${event.target.result}`;
|
let originalImageUrl = `${event.target.result}`;
|
||||||
|
|
||||||
|
let character = await parseFile(inputFiles[0]).catch((error) => {
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
if (character && character.character) {
|
||||||
|
character = character.character;
|
||||||
|
console.log(character);
|
||||||
|
|
||||||
|
name = character.name;
|
||||||
|
|
||||||
|
const turndownService = new TurndownService();
|
||||||
|
info.meta.description = turndownService.turndown(character.summary);
|
||||||
|
|
||||||
|
info.params.system = `Personality: ${character.personality}${
|
||||||
|
character?.scenario ? `\nScenario: ${character.scenario}` : ''
|
||||||
|
}${character?.greeting ? `\First Message: ${character.greeting}` : ''}${
|
||||||
|
character?.examples ? `\nExamples: ${character.examples}` : ''
|
||||||
|
}`;
|
||||||
|
}
|
||||||
|
|
||||||
const img = new Image();
|
const img = new Image();
|
||||||
img.src = originalImageUrl;
|
img.src = originalImageUrl;
|
||||||
|
|
||||||
@ -408,10 +434,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if info.meta.description !== null}
|
{#if info.meta.description !== null}
|
||||||
<input
|
<textarea
|
||||||
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||||
placeholder={$i18n.t('Add a short description about what this model does')}
|
placeholder={$i18n.t('Add a short description about what this model does')}
|
||||||
bind:value={info.meta.description}
|
bind:value={info.meta.description}
|
||||||
|
row="3"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
@ -369,10 +369,11 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{#if info.meta.description !== null}
|
{#if info.meta.description !== null}
|
||||||
<input
|
<textarea
|
||||||
class="mt-1 px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
class="mt-1 px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
|
||||||
placeholder={$i18n.t('Add a short description about what this model does')}
|
placeholder={$i18n.t('Add a short description about what this model does')}
|
||||||
bind:value={info.meta.description}
|
bind:value={info.meta.description}
|
||||||
|
row="3"
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user