feat: modelfiles to models

This commit is contained in:
Timothy J. Baek 2024-05-24 00:26:00 -07:00
parent 17e4be49c0
commit 4d57e08b38
18 changed files with 257 additions and 310 deletions

View File

@ -6,7 +6,7 @@ from apps.web.routers import (
users,
chats,
documents,
modelfiles,
models,
prompts,
configs,
memories,
@ -56,11 +56,10 @@ app.include_router(users.router, prefix="/users", tags=["users"])
app.include_router(chats.router, prefix="/chats", tags=["chats"])
app.include_router(documents.router, prefix="/documents", tags=["documents"])
app.include_router(modelfiles.router, prefix="/modelfiles", tags=["modelfiles"])
app.include_router(models.router, prefix="/models", tags=["models"])
app.include_router(prompts.router, prefix="/prompts", tags=["prompts"])
app.include_router(memories.router, prefix="/memories", tags=["memories"])
app.include_router(configs.router, prefix="/configs", tags=["configs"])
app.include_router(utils.router, prefix="/utils", tags=["utils"])

View File

@ -1,3 +1,11 @@
################################################################################
# DEPRECATION NOTICE #
# #
# This file has been deprecated since version 0.2.0. #
# #
################################################################################
from pydantic import BaseModel
from peewee import *
from playhouse.shortcuts import model_to_dict

View File

@ -3,13 +3,18 @@ import logging
from typing import Optional
import peewee as pw
from peewee import *
from playhouse.shortcuts import model_to_dict
from pydantic import BaseModel, ConfigDict
from apps.web.internal.db import DB, JSONField
from typing import List, Union, Optional
from config import SRC_LOG_LEVELS
import time
log = logging.getLogger(__name__)
log.setLevel(SRC_LOG_LEVELS["MODELS"])
@ -20,10 +25,8 @@ log.setLevel(SRC_LOG_LEVELS["MODELS"])
# ModelParams is a model for the data stored in the params field of the Model table
# It isn't currently used in the backend, but it's here as a reference
class ModelParams(BaseModel):
model_config = ConfigDict(extra="allow")
pass
@ -55,7 +58,6 @@ class Model(pw.Model):
base_model_id = pw.TextField(null=True)
"""
An optional pointer to the actual model that should be used when proxying requests.
Currently unused - but will be used to support Modelfile like behaviour in the future
"""
name = pw.TextField()
@ -73,8 +75,8 @@ class Model(pw.Model):
Holds a JSON encoded blob of metadata, see `ModelMeta`.
"""
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
updated_at = BigIntegerField()
created_at = BigIntegerField()
class Meta:
database = DB
@ -83,16 +85,36 @@ class Model(pw.Model):
class ModelModel(BaseModel):
id: str
base_model_id: Optional[str] = None
name: str
params: ModelParams
meta: ModelMeta
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
####################
# Forms
####################
class ModelResponse(BaseModel):
id: str
name: str
meta: ModelMeta
updated_at: int # timestamp in epoch
created_at: int # timestamp in epoch
class ModelForm(BaseModel):
id: str
base_model_id: Optional[str] = None
name: str
meta: ModelMeta
params: ModelParams
class ModelsTable:
def __init__(
self,
@ -101,44 +123,47 @@ class ModelsTable:
self.db = db
self.db.create_tables([Model])
def get_all_models(self) -> list[ModelModel]:
def insert_new_model(self, model: ModelForm, user_id: str) -> Optional[ModelModel]:
try:
model = Model.create(
**{
**model.model_dump(),
"user_id": user_id,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
return ModelModel(**model_to_dict(model))
except:
return None
def get_all_models(self) -> List[ModelModel]:
return [ModelModel(**model_to_dict(model)) for model in Model.select()]
def update_all_models(self, models: list[ModelModel]) -> bool:
def get_model_by_id(self, id: str) -> Optional[ModelModel]:
try:
with self.db.atomic():
# Fetch current models from the database
current_models = self.get_all_models()
current_model_dict = {model.id: model for model in current_models}
model = Model.get(Model.id == id)
return ModelModel(**model_to_dict(model))
except:
return None
# Create a set of model IDs from the current models and the new models
current_model_keys = set(current_model_dict.keys())
new_model_keys = set(model.id for model in models)
def update_model_by_id(self, id: str, model: ModelForm) -> Optional[ModelModel]:
try:
# update only the fields that are present in the model
query = Model.update(**model.model_dump()).where(Model.id == id)
query.execute()
# Determine which models need to be created, updated, or deleted
models_to_create = [
model for model in models if model.id not in current_model_keys
]
models_to_update = [
model for model in models if model.id in current_model_keys
]
models_to_delete = current_model_keys - new_model_keys
# Perform the necessary database operations
for model in models_to_create:
Model.create(**model.model_dump())
for model in models_to_update:
Model.update(**model.model_dump()).where(
Model.id == model.id
).execute()
for model_id, model_source in models_to_delete:
Model.delete().where(Model.id == model_id).execute()
model = Model.get(Model.id == id)
return ModelModel(**model_to_dict(model))
except:
return None
def delete_model_by_id(self, id: str) -> bool:
try:
query = Model.delete().where(Model.id == id)
query.execute()
return True
except Exception as e:
log.exception(e)
except:
return False

View File

@ -1,124 +0,0 @@
from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta
from typing import List, Union, Optional
from fastapi import APIRouter
from pydantic import BaseModel
import json
from apps.web.models.modelfiles import (
Modelfiles,
ModelfileForm,
ModelfileTagNameForm,
ModelfileUpdateForm,
ModelfileResponse,
)
from utils.utils import get_current_user, get_admin_user
from constants import ERROR_MESSAGES
router = APIRouter()
############################
# GetModelfiles
############################
@router.get("/", response_model=List[ModelfileResponse])
async def get_modelfiles(
skip: int = 0, limit: int = 50, user=Depends(get_current_user)
):
return Modelfiles.get_modelfiles(skip, limit)
############################
# CreateNewModelfile
############################
@router.post("/create", response_model=Optional[ModelfileResponse])
async def create_new_modelfile(form_data: ModelfileForm, user=Depends(get_admin_user)):
modelfile = Modelfiles.insert_new_modelfile(user.id, form_data)
if modelfile:
return ModelfileResponse(
**{
**modelfile.model_dump(),
"modelfile": json.loads(modelfile.modelfile),
}
)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.DEFAULT(),
)
############################
# GetModelfileByTagName
############################
@router.post("/", response_model=Optional[ModelfileResponse])
async def get_modelfile_by_tag_name(
form_data: ModelfileTagNameForm, user=Depends(get_current_user)
):
modelfile = Modelfiles.get_modelfile_by_tag_name(form_data.tag_name)
if modelfile:
return ModelfileResponse(
**{
**modelfile.model_dump(),
"modelfile": json.loads(modelfile.modelfile),
}
)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.NOT_FOUND,
)
############################
# UpdateModelfileByTagName
############################
@router.post("/update", response_model=Optional[ModelfileResponse])
async def update_modelfile_by_tag_name(
form_data: ModelfileUpdateForm, user=Depends(get_admin_user)
):
modelfile = Modelfiles.get_modelfile_by_tag_name(form_data.tag_name)
if modelfile:
updated_modelfile = {
**json.loads(modelfile.modelfile),
**form_data.modelfile,
}
modelfile = Modelfiles.update_modelfile_by_tag_name(
form_data.tag_name, updated_modelfile
)
return ModelfileResponse(
**{
**modelfile.model_dump(),
"modelfile": json.loads(modelfile.modelfile),
}
)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
############################
# DeleteModelfileByTagName
############################
@router.delete("/delete", response_model=bool)
async def delete_modelfile_by_tag_name(
form_data: ModelfileTagNameForm, user=Depends(get_admin_user)
):
result = Modelfiles.delete_modelfile_by_tag_name(form_data.tag_name)
return result

View File

@ -0,0 +1,89 @@
from fastapi import Depends, FastAPI, HTTPException, status
from datetime import datetime, timedelta
from typing import List, Union, Optional
from fastapi import APIRouter
from pydantic import BaseModel
import json
from apps.web.models.models import Models, ModelModel, ModelForm, ModelResponse
from utils.utils import get_verified_user, get_admin_user
from constants import ERROR_MESSAGES
router = APIRouter()
###########################
# getAllModels
###########################
@router.get("/", response_model=List[ModelResponse])
async def get_models(user=Depends(get_verified_user)):
return Models.get_all_models()
############################
# AddNewModel
############################
@router.post("/add", response_model=Optional[ModelModel])
async def add_new_model(form_data: ModelForm, user=Depends(get_admin_user)):
model = Models.insert_new_model(form_data, user.id)
if model:
return model
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.DEFAULT(),
)
############################
# GetModelById
############################
@router.get("/{id}", response_model=Optional[ModelModel])
async def get_model_by_id(id: str, user=Depends(get_verified_user)):
model = Models.get_model_by_id(id)
if model:
return model
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.NOT_FOUND,
)
############################
# UpdateModelById
############################
@router.post("/{id}/update", response_model=Optional[ModelModel])
async def update_model_by_id(
id: str, form_data: ModelForm, user=Depends(get_admin_user)
):
model = Models.get_model_by_id(id)
if model:
model = Models.update_model_by_id(id, form_data)
return model
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
)
############################
# DeleteModelById
############################
@router.delete("/{id}/delete", response_model=bool)
async def delete_model_by_id(id: str, user=Depends(get_admin_user)):
result = Models.delete_model_by_id(id)
return result

View File

@ -320,33 +320,6 @@ async def update_model_filter_config(
}
class SetModelConfigForm(BaseModel):
models: List[ModelModel]
@app.post("/api/config/models")
async def update_model_config(
form_data: SetModelConfigForm, user=Depends(get_admin_user)
):
if not Models.update_all_models(form_data.models):
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=ERROR_MESSAGES.DEFAULT("Failed to update model config"),
)
ollama_app.state.MODEL_CONFIG = form_data.models
openai_app.state.MODEL_CONFIG = form_data.models
litellm_app.state.MODEL_CONFIG = form_data.models
app.state.MODEL_CONFIG = form_data.models
return {"models": app.state.MODEL_CONFIG}
@app.get("/api/config/models")
async def get_model_config(user=Depends(get_admin_user)):
return {"models": app.state.MODEL_CONFIG}
@app.get("/api/webhook")
async def get_webhook_url(user=Depends(get_admin_user)):
return {

View File

@ -1,18 +1,16 @@
import { WEBUI_API_BASE_URL } from '$lib/constants';
export const createNewModelfile = async (token: string, modelfile: object) => {
export const addNewModel = async (token: string, model: object) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/modelfiles/create`, {
const res = await fetch(`${WEBUI_API_BASE_URL}/models/add`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
},
body: JSON.stringify({
modelfile: modelfile
})
body: JSON.stringify(model)
})
.then(async (res) => {
if (!res.ok) throw await res.json();
@ -31,10 +29,10 @@ export const createNewModelfile = async (token: string, modelfile: object) => {
return res;
};
export const getModelfiles = async (token: string = '') => {
export const getModels = async (token: string = '') => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/modelfiles/`, {
const res = await fetch(`${WEBUI_API_BASE_URL}/models/`, {
method: 'GET',
headers: {
Accept: 'application/json',
@ -59,62 +57,19 @@ export const getModelfiles = async (token: string = '') => {
throw error;
}
return res.map((modelfile) => modelfile.modelfile);
return res;
};
export const getModelfileByTagName = async (token: string, tagName: string) => {
export const getModelById = async (token: string, id: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/modelfiles/`, {
method: 'POST',
const res = await fetch(`${WEBUI_API_BASE_URL}/models/${id}`, {
method: 'GET',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
},
body: JSON.stringify({
tag_name: tagName
})
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.then((json) => {
return json;
})
.catch((err) => {
error = err;
console.log(err);
return null;
});
if (error) {
throw error;
}
return res.modelfile;
};
export const updateModelfileByTagName = async (
token: string,
tagName: string,
modelfile: object
) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/modelfiles/update`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
},
body: JSON.stringify({
tag_name: tagName,
modelfile: modelfile
})
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();
@ -137,19 +92,49 @@ export const updateModelfileByTagName = async (
return res;
};
export const deleteModelfileByTagName = async (token: string, tagName: string) => {
export const updateModelById = async (token: string, id: string, model: object) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/modelfiles/delete`, {
const res = await fetch(`${WEBUI_API_BASE_URL}/models/${id}/update`, {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
},
body: JSON.stringify(model)
})
.then(async (res) => {
if (!res.ok) throw await res.json();
return res.json();
})
.then((json) => {
return json;
})
.catch((err) => {
error = err;
console.log(err);
return null;
});
if (error) {
throw error;
}
return res;
};
export const deleteModelById = async (token: string, id: string) => {
let error = null;
const res = await fetch(`${WEBUI_API_BASE_URL}/models/${id}/delete`, {
method: 'DELETE',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
authorization: `Bearer ${token}`
},
body: JSON.stringify({
tag_name: tagName
})
}
})
.then(async (res) => {
if (!res.ok) throw await res.json();

View File

@ -14,7 +14,7 @@
import { toast } from 'svelte-sonner';
import {
capitalizeFirstLetter,
getModels,
getAllModels,
sanitizeResponseContent,
splitStream
} from '$lib/utils';
@ -159,7 +159,7 @@
})
);
models.set(await getModels(localStorage.token));
models.set(await getAllModels(localStorage.token));
} else {
toast.error($i18n.t('Download canceled'));
}

View File

@ -23,7 +23,7 @@
const i18n = getContext('i18n');
export let getModels: Function;
export let getAllModels: Function;
// External
let OLLAMA_BASE_URLS = [''];
@ -38,7 +38,7 @@
OPENAI_API_BASE_URLS = await updateOpenAIUrls(localStorage.token, OPENAI_API_BASE_URLS);
OPENAI_API_KEYS = await updateOpenAIKeys(localStorage.token, OPENAI_API_KEYS);
await models.set(await getModels());
await models.set(await getAllModels());
};
const updateOllamaUrlsHandler = async () => {
@ -51,7 +51,7 @@
if (ollamaVersion) {
toast.success($i18n.t('Server connection verified'));
await models.set(await getModels());
await models.set(await getAllModels());
}
};

View File

@ -11,7 +11,7 @@
import AdvancedParams from './Advanced/AdvancedParams.svelte';
export let saveSettings: Function;
export let getModels: Function;
export let getAllModels: Function;
// General
let themes = ['dark', 'light', 'rose-pine dark', 'rose-pine-dawn light', 'oled-dark'];

View File

@ -42,7 +42,7 @@
let imageSize = '';
let steps = 50;
const getModels = async () => {
const getAllModels = async () => {
models = await getImageGenerationModels(localStorage.token).catch((error) => {
toast.error(error);
return null;
@ -66,7 +66,7 @@
if (res) {
COMFYUI_BASE_URL = res.COMFYUI_BASE_URL;
await getModels();
await getAllModels();
if (models) {
toast.success($i18n.t('Server connection verified'));
@ -85,7 +85,7 @@
if (res) {
AUTOMATIC1111_BASE_URL = res.AUTOMATIC1111_BASE_URL;
await getModels();
await getAllModels();
if (models) {
toast.success($i18n.t('Server connection verified'));
@ -112,7 +112,7 @@
if (enableImageGeneration) {
config.set(await getBackendConfig(localStorage.token));
getModels();
getAllModels();
}
};
@ -141,7 +141,7 @@
steps = await getImageSteps(localStorage.token);
if (enableImageGeneration) {
getModels();
getAllModels();
}
}
});

View File

@ -22,7 +22,7 @@
const i18n = getContext('i18n');
export let getModels: Function;
export let getAllModels: Function;
let showLiteLLM = false;
let showLiteLLMParams = false;
@ -261,7 +261,7 @@
})
);
models.set(await getModels(localStorage.token));
models.set(await getAllModels(localStorage.token));
} else {
toast.error($i18n.t('Download canceled'));
}
@ -424,7 +424,7 @@
modelTransferring = false;
uploadProgress = null;
models.set(await getModels());
models.set(await getAllModels());
};
const deleteModelHandler = async () => {
@ -439,7 +439,7 @@
}
deleteModelTag = '';
models.set(await getModels());
models.set(await getAllModels());
};
const cancelModelPullHandler = async (model: string) => {
@ -488,7 +488,7 @@
liteLLMMaxTokens = '';
liteLLMModelInfo = await getLiteLLMModelInfo(localStorage.token);
models.set(await getModels());
models.set(await getAllModels());
};
const deleteLiteLLMModelHandler = async () => {
@ -507,7 +507,7 @@
deleteLiteLLMModelName = '';
liteLLMModelInfo = await getLiteLLMModelInfo(localStorage.token);
models.set(await getModels());
models.set(await getAllModels());
};
const addModelInfoHandler = async () => {
@ -519,9 +519,7 @@
return;
}
// Remove any existing config
modelConfig = modelConfig.filter(
(m) => !(m.id === selectedModelId)
);
modelConfig = modelConfig.filter((m) => !(m.id === selectedModelId));
// Add new config
modelConfig.push({
id: selectedModelId,
@ -536,7 +534,7 @@
toast.success(
$i18n.t('Model info for {{modelName}} added successfully', { modelName: selectedModelId })
);
models.set(await getModels());
models.set(await getAllModels());
};
const deleteModelInfoHandler = async () => {
@ -547,14 +545,12 @@
if (!model) {
return;
}
modelConfig = modelConfig.filter(
(m) => !(m.id === selectedModelId)
);
modelConfig = modelConfig.filter((m) => !(m.id === selectedModelId));
await updateModelConfig(localStorage.token, modelConfig);
toast.success(
$i18n.t('Model info for {{modelName}} deleted successfully', { modelName: selectedModelId })
);
models.set(await getModels());
models.set(await getAllModels());
};
const toggleIsVisionCapable = () => {

View File

@ -3,7 +3,7 @@
import { toast } from 'svelte-sonner';
import { models, settings, user } from '$lib/stores';
import { getModels as _getModels } from '$lib/utils';
import { getAllModels as _getAllModels } from '$lib/utils';
import Modal from '../common/Modal.svelte';
import Account from './Settings/Account.svelte';
@ -25,12 +25,12 @@
const saveSettings = async (updated) => {
console.log(updated);
await settings.set({ ...$settings, ...updated });
await models.set(await getModels());
await models.set(await getAllModels());
localStorage.setItem('settings', JSON.stringify($settings));
};
const getModels = async () => {
return await _getModels(localStorage.token);
const getAllModels = async () => {
return await _getAllModels(localStorage.token);
};
let selectedTab = 'general';
@ -318,17 +318,17 @@
<div class="flex-1 md:min-h-[28rem]">
{#if selectedTab === 'general'}
<General
{getModels}
{getAllModels}
{saveSettings}
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}
/>
{:else if selectedTab === 'models'}
<Models {getModels} />
<Models {getAllModels} />
{:else if selectedTab === 'connections'}
<Connections
{getModels}
{getAllModels}
on:save={() => {
toast.success($i18n.t('Settings saved successfully!'));
}}

View File

@ -7,11 +7,7 @@
import { WEBUI_NAME, modelfiles, settings, user } from '$lib/stores';
import { createModel, deleteModel } from '$lib/apis/ollama';
import {
createNewModelfile,
deleteModelfileByTagName,
getModelfiles
} from '$lib/apis/modelfiles';
import { addNewModel, deleteModelById, getModels } from '$lib/apis/models';
import { goto } from '$app/navigation';
const i18n = getContext('i18n');
@ -36,8 +32,8 @@
const deleteModelfile = async (tagName) => {
await deleteModelHandler(tagName);
await deleteModelfileByTagName(localStorage.token, tagName);
await modelfiles.set(await getModelfiles(localStorage.token));
await deleteModelById(localStorage.token, tagName);
await modelfiles.set(await getModels(localStorage.token));
};
const shareModelfile = async (modelfile) => {
@ -246,12 +242,12 @@
console.log(savedModelfiles);
for (const modelfile of savedModelfiles) {
await createNewModelfile(localStorage.token, modelfile).catch((error) => {
await addNewModel(localStorage.token, modelfile).catch((error) => {
return null;
});
}
await modelfiles.set(await getModelfiles(localStorage.token));
await modelfiles.set(await getModels(localStorage.token));
};
reader.readAsText(importFiles[0]);
@ -318,7 +314,7 @@
class="self-center w-fit text-sm px-3 py-1 border dark:border-gray-600 rounded-xl flex"
on:click={async () => {
for (const modelfile of localModelfiles) {
await createNewModelfile(localStorage.token, modelfile).catch((error) => {
await addNewModel(localStorage.token, modelfile).catch((error) => {
return null;
});
}
@ -326,7 +322,7 @@
saveModelfiles(localModelfiles);
localStorage.removeItem('modelfiles');
localModelfiles = JSON.parse(localStorage.getItem('modelfiles') ?? '[]');
await modelfiles.set(await getModelfiles(localStorage.token));
await modelfiles.set(await getModels(localStorage.token));
}}
>
<div class=" self-center mr-2 font-medium">{$i18n.t('Sync All')}</div>
@ -354,7 +350,7 @@
localStorage.removeItem('modelfiles');
localModelfiles = JSON.parse(localStorage.getItem('modelfiles') ?? '[]');
await modelfiles.set(await getModelfiles(localStorage.token));
await modelfiles.set(await getModels(localStorage.token));
}}
>
<div class=" self-center">

View File

@ -4,7 +4,7 @@ import { getOllamaModels } from '$lib/apis/ollama';
import { getOpenAIModels } from '$lib/apis/openai';
import { getLiteLLMModels } from '$lib/apis/litellm';
export const getModels = async (token: string) => {
export const getAllModels = async (token: string) => {
let models = await Promise.all([
getOllamaModels(token).catch((error) => {
console.log(error);

View File

@ -7,9 +7,9 @@
import { goto } from '$app/navigation';
import { getModels as _getModels } from '$lib/utils';
import { getAllModels as _getAllModels } from '$lib/utils';
import { getOllamaVersion } from '$lib/apis/ollama';
import { getModelfiles } from '$lib/apis/modelfiles';
import { getModels } from '$lib/apis/models';
import { getPrompts } from '$lib/apis/prompts';
import { getDocs } from '$lib/apis/documents';
@ -46,8 +46,8 @@
let showShortcuts = false;
const getModels = async () => {
return _getModels(localStorage.token);
const getAllModels = async () => {
return _getAllModels(localStorage.token);
};
const setOllamaVersion = async (version: string = '') => {
@ -91,10 +91,10 @@
await Promise.all([
(async () => {
models.set(await getModels());
models.set(await getAllModels());
})(),
(async () => {
modelfiles.set(await getModelfiles(localStorage.token));
modelfiles.set(await getModels(localStorage.token));
})(),
(async () => {
prompts.set(await getPrompts(localStorage.token));
@ -109,7 +109,7 @@
modelfiles.subscribe(async () => {
// should fetch models
models.set(await getModels());
models.set(await getAllModels());
});
document.addEventListener('keydown', function (event) {

View File

@ -8,7 +8,7 @@
import { splitStream } from '$lib/utils';
import { onMount, tick, getContext } from 'svelte';
import { createModel } from '$lib/apis/ollama';
import { createNewModelfile, getModelfileByTagName, getModelfiles } from '$lib/apis/modelfiles';
import { addNewModel, getModelById, getModels } from '$lib/apis/models';
const i18n = getContext('i18n');
@ -98,8 +98,8 @@ SYSTEM """${system}"""`.replace(/^\s*\n/gm, '');
};
const saveModelfile = async (modelfile) => {
await createNewModelfile(localStorage.token, modelfile);
await modelfiles.set(await getModelfiles(localStorage.token));
await addNewModel(localStorage.token, modelfile);
await modelfiles.set(await getModels(localStorage.token));
};
const submitHandler = async () => {
@ -116,7 +116,7 @@ SYSTEM """${system}"""`.replace(/^\s*\n/gm, '');
if (
$models.map((model) => model.name).includes(tagName) ||
(await getModelfileByTagName(localStorage.token, tagName).catch(() => false))
(await getModelById(localStorage.token, tagName).catch(() => false))
) {
toast.error(
`Uh-oh! It looks like you already have a model named '${tagName}'. Please choose a different name to complete your modelfile.`

View File

@ -10,7 +10,7 @@
import { splitStream } from '$lib/utils';
import { createModel } from '$lib/apis/ollama';
import { getModelfiles, updateModelfileByTagName } from '$lib/apis/modelfiles';
import { getModels, updateModelById } from '$lib/apis/models';
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
@ -85,8 +85,8 @@
});
const updateModelfile = async (modelfile) => {
await updateModelfileByTagName(localStorage.token, modelfile.tagName, modelfile);
await modelfiles.set(await getModelfiles(localStorage.token));
await updateModelById(localStorage.token, modelfile.tagName, modelfile);
await modelfiles.set(await getModels(localStorage.token));
};
const updateHandler = async () => {