mirror of
https://github.com/open-webui/open-webui
synced 2024-11-25 05:18:15 +00:00
feat: create modelfile from models
This commit is contained in:
parent
ec7c5a3f07
commit
950073c1de
@ -369,21 +369,29 @@ export const generateChatCompletion = async (token: string = '', body: object) =
|
|||||||
return [res, controller];
|
return [res, controller];
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createModel = async (token: string, tagName: string, content: string) => {
|
export const createModel = async (
|
||||||
|
token: string,
|
||||||
|
tagName: string,
|
||||||
|
content: string,
|
||||||
|
urlIdx: string | null = null
|
||||||
|
) => {
|
||||||
let error = null;
|
let error = null;
|
||||||
|
|
||||||
const res = await fetch(`${OLLAMA_API_BASE_URL}/api/create`, {
|
const res = await fetch(
|
||||||
method: 'POST',
|
`${OLLAMA_API_BASE_URL}/api/create${urlIdx !== null ? `/${urlIdx}` : ''}`,
|
||||||
headers: {
|
{
|
||||||
Accept: 'application/json',
|
method: 'POST',
|
||||||
'Content-Type': 'application/json',
|
headers: {
|
||||||
Authorization: `Bearer ${token}`
|
Accept: 'application/json',
|
||||||
},
|
'Content-Type': 'application/json',
|
||||||
body: JSON.stringify({
|
Authorization: `Bearer ${token}`
|
||||||
name: tagName,
|
},
|
||||||
modelfile: content
|
body: JSON.stringify({
|
||||||
})
|
name: tagName,
|
||||||
}).catch((err) => {
|
modelfile: content
|
||||||
|
})
|
||||||
|
}
|
||||||
|
).catch((err) => {
|
||||||
error = err;
|
error = err;
|
||||||
return null;
|
return null;
|
||||||
});
|
});
|
||||||
|
@ -43,6 +43,13 @@
|
|||||||
|
|
||||||
let modelTransferring = false;
|
let modelTransferring = false;
|
||||||
let modelTag = '';
|
let modelTag = '';
|
||||||
|
|
||||||
|
let createModelLoading = false;
|
||||||
|
let createModelTag = '';
|
||||||
|
let createModelContent = '';
|
||||||
|
let createModelDigest = '';
|
||||||
|
let createModelPullProgress = null;
|
||||||
|
|
||||||
let digest = '';
|
let digest = '';
|
||||||
let pullProgress = null;
|
let pullProgress = null;
|
||||||
|
|
||||||
@ -434,6 +441,83 @@
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const createModelHandler = async () => {
|
||||||
|
createModelLoading = true;
|
||||||
|
const res = await createModel(
|
||||||
|
localStorage.token,
|
||||||
|
createModelTag,
|
||||||
|
createModelContent,
|
||||||
|
selectedOllamaUrlIdx
|
||||||
|
).catch((error) => {
|
||||||
|
toast.error(error);
|
||||||
|
return null;
|
||||||
|
});
|
||||||
|
|
||||||
|
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);
|
||||||
|
console.log(data);
|
||||||
|
|
||||||
|
if (data.error) {
|
||||||
|
throw data.error;
|
||||||
|
}
|
||||||
|
if (data.detail) {
|
||||||
|
throw data.detail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (data.status) {
|
||||||
|
if (
|
||||||
|
!data.digest &&
|
||||||
|
!data.status.includes('writing') &&
|
||||||
|
!data.status.includes('sha256')
|
||||||
|
) {
|
||||||
|
toast.success(data.status);
|
||||||
|
} else {
|
||||||
|
if (data.digest) {
|
||||||
|
createModelDigest = data.digest;
|
||||||
|
|
||||||
|
if (data.completed) {
|
||||||
|
createModelPullProgress =
|
||||||
|
Math.round((data.completed / data.total) * 1000) / 10;
|
||||||
|
} else {
|
||||||
|
createModelPullProgress = 100;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.log(error);
|
||||||
|
toast.error(error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
models.set(await getModels());
|
||||||
|
|
||||||
|
createModelLoading = false;
|
||||||
|
|
||||||
|
createModelTag = '';
|
||||||
|
createModelContent = '';
|
||||||
|
createModelDigest = '';
|
||||||
|
createModelPullProgress = null;
|
||||||
|
};
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
const ollamaConfig = await getOllamaConfig(localStorage.token);
|
const ollamaConfig = await getOllamaConfig(localStorage.token);
|
||||||
|
|
||||||
@ -695,6 +779,77 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<div class=" mb-2 text-sm font-medium">{$i18n.t('Create a model')}</div>
|
||||||
|
<div class="flex w-full">
|
||||||
|
<div class="flex-1 mr-2 flex flex-col gap-2">
|
||||||
|
<input
|
||||||
|
class="w-full rounded-lg py-2 px-4 text-sm dark:text-gray-300 dark:bg-gray-850 outline-none"
|
||||||
|
placeholder={$i18n.t('Enter model tag (e.g. {{modelTag}})', {
|
||||||
|
modelTag: 'my-modelfile'
|
||||||
|
})}
|
||||||
|
bind:value={createModelTag}
|
||||||
|
disabled={createModelLoading}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<textarea
|
||||||
|
bind:value={createModelContent}
|
||||||
|
class="w-full rounded-lg py-2 px-4 text-sm bg-gray-100 dark:text-gray-100 dark:bg-gray-850 outline-none resize-none scrollbar-hidden"
|
||||||
|
rows="6"
|
||||||
|
placeholder={`TEMPLATE """{{ .System }}\nUSER: {{ .Prompt }}\nASSISTANT: """\nPARAMETER num_ctx 4096\nPARAMETER stop "</s>"\nPARAMETER stop "USER:"\nPARAMETER stop "ASSISTANT:"`}
|
||||||
|
disabled={createModelLoading}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex self-start">
|
||||||
|
<button
|
||||||
|
class="px-2.5 py-2.5 bg-gray-100 hover:bg-gray-200 text-gray-800 dark:bg-gray-850 dark:hover:bg-gray-800 dark:text-gray-100 rounded-lg transition disabled:cursor-not-allowed"
|
||||||
|
on:click={() => {
|
||||||
|
createModelHandler();
|
||||||
|
}}
|
||||||
|
disabled={createModelLoading}
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
fill="currentColor"
|
||||||
|
class="size-4"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M7.25 10.25a.75.75 0 0 0 1.5 0V4.56l2.22 2.22a.75.75 0 1 0 1.06-1.06l-3.5-3.5a.75.75 0 0 0-1.06 0l-3.5 3.5a.75.75 0 0 0 1.06 1.06l2.22-2.22v5.69Z"
|
||||||
|
/>
|
||||||
|
<path
|
||||||
|
d="M3.5 9.75a.75.75 0 0 0-1.5 0v1.5A2.75 2.75 0 0 0 4.75 14h6.5A2.75 2.75 0 0 0 14 11.25v-1.5a.75.75 0 0 0-1.5 0v1.5c0 .69-.56 1.25-1.25 1.25h-6.5c-.69 0-1.25-.56-1.25-1.25v-1.5Z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{#if createModelDigest !== ''}
|
||||||
|
<div class="flex flex-col mt-1">
|
||||||
|
<div class="font-medium mb-1">{createModelTag}</div>
|
||||||
|
<div class="">
|
||||||
|
<div class="flex flex-row justify-between space-x-4 pr-2">
|
||||||
|
<div class=" flex-1">
|
||||||
|
<div
|
||||||
|
class="dark:bg-gray-600 bg-gray-500 text-xs font-medium text-gray-100 text-center p-0.5 leading-none rounded-full"
|
||||||
|
style="width: {Math.max(15, createModelPullProgress ?? 0)}%"
|
||||||
|
>
|
||||||
|
{createModelPullProgress ?? 0}%
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{#if createModelDigest}
|
||||||
|
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
|
||||||
|
{createModelDigest}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="pt-1">
|
<div class="pt-1">
|
||||||
<div class="flex justify-between items-center text-xs">
|
<div class="flex justify-between items-center text-xs">
|
||||||
<div class=" text-sm font-medium">{$i18n.t('Experimental')}</div>
|
<div class=" text-sm font-medium">{$i18n.t('Experimental')}</div>
|
||||||
|
Loading…
Reference in New Issue
Block a user