From 950073c1de6215e3d1d892d51e26d642f38aa12a Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Wed, 5 Jun 2024 09:52:58 -0700 Subject: [PATCH] feat: create modelfile from models --- src/lib/apis/ollama/index.ts | 34 ++-- .../components/chat/Settings/Models.svelte | 155 ++++++++++++++++++ 2 files changed, 176 insertions(+), 13 deletions(-) diff --git a/src/lib/apis/ollama/index.ts b/src/lib/apis/ollama/index.ts index aa1ac182b..084d2d5f1 100644 --- a/src/lib/apis/ollama/index.ts +++ b/src/lib/apis/ollama/index.ts @@ -369,21 +369,29 @@ export const generateChatCompletion = async (token: string = '', body: object) = 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; - const res = await fetch(`${OLLAMA_API_BASE_URL}/api/create`, { - method: 'POST', - headers: { - Accept: 'application/json', - 'Content-Type': 'application/json', - Authorization: `Bearer ${token}` - }, - body: JSON.stringify({ - name: tagName, - modelfile: content - }) - }).catch((err) => { + const res = await fetch( + `${OLLAMA_API_BASE_URL}/api/create${urlIdx !== null ? `/${urlIdx}` : ''}`, + { + method: 'POST', + headers: { + Accept: 'application/json', + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + name: tagName, + modelfile: content + }) + } + ).catch((err) => { error = err; return null; }); diff --git a/src/lib/components/chat/Settings/Models.svelte b/src/lib/components/chat/Settings/Models.svelte index 721db1743..36378d4d5 100644 --- a/src/lib/components/chat/Settings/Models.svelte +++ b/src/lib/components/chat/Settings/Models.svelte @@ -43,6 +43,13 @@ let modelTransferring = false; let modelTag = ''; + + let createModelLoading = false; + let createModelTag = ''; + let createModelContent = ''; + let createModelDigest = ''; + let createModelPullProgress = null; + let digest = ''; 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 () => { const ollamaConfig = await getOllamaConfig(localStorage.token); @@ -695,6 +779,77 @@ +
+
{$i18n.t('Create a model')}
+
+
+ + +