"...git@developer.sourcefind.cn:chenpangpang/open-webui.git" did not exist on "79615f26da1b20d90e20036a32ff3d9322b2efe2"
Commit 708d755e authored by Timothy J. Baek's avatar Timothy J. Baek
Browse files

feat: model update

parent 0a48114b
...@@ -40,6 +40,9 @@ app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS ...@@ -40,6 +40,9 @@ app.state.config.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS
app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE app.state.config.DEFAULT_USER_ROLE = DEFAULT_USER_ROLE
app.state.config.USER_PERMISSIONS = USER_PERMISSIONS app.state.config.USER_PERMISSIONS = USER_PERMISSIONS
app.state.config.WEBHOOK_URL = WEBHOOK_URL app.state.config.WEBHOOK_URL = WEBHOOK_URL
app.state.MODELS = {}
app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER app.state.AUTH_TRUSTED_EMAIL_HEADER = WEBUI_AUTH_TRUSTED_EMAIL_HEADER
......
...@@ -33,6 +33,8 @@ class ModelParams(BaseModel): ...@@ -33,6 +33,8 @@ class ModelParams(BaseModel):
# ModelMeta is a model for the data stored in the meta field of the Model table # ModelMeta is a model for the data stored in the meta field of the Model table
# It isn't currently used in the backend, but it's here as a reference # It isn't currently used in the backend, but it's here as a reference
class ModelMeta(BaseModel): class ModelMeta(BaseModel):
profile_image_url: Optional[str] = "/favicon.png"
description: Optional[str] = None description: Optional[str] = None
""" """
User-facing description of the model. User-facing description of the model.
...@@ -84,6 +86,7 @@ class Model(pw.Model): ...@@ -84,6 +86,7 @@ class Model(pw.Model):
class ModelModel(BaseModel): class ModelModel(BaseModel):
id: str id: str
user_id: str
base_model_id: Optional[str] = None base_model_id: Optional[str] = None
name: str name: str
...@@ -123,18 +126,26 @@ class ModelsTable: ...@@ -123,18 +126,26 @@ class ModelsTable:
self.db = db self.db = db
self.db.create_tables([Model]) self.db.create_tables([Model])
def insert_new_model(self, model: ModelForm, user_id: str) -> Optional[ModelModel]: def insert_new_model(
self, form_data: ModelForm, user_id: str
) -> Optional[ModelModel]:
model = ModelModel(
**{
**form_data.model_dump(),
"user_id": user_id,
"created_at": int(time.time()),
"updated_at": int(time.time()),
}
)
try: try:
model = Model.create( result = Model.create(**model.model_dump())
**{
**model.model_dump(), if result:
"user_id": user_id, return model
"created_at": int(time.time()), else:
"updated_at": int(time.time()), return None
} except Exception as e:
) print(e)
return ModelModel(**model_to_dict(model))
except:
return None return None
def get_all_models(self) -> List[ModelModel]: def get_all_models(self) -> List[ModelModel]:
......
from fastapi import Depends, FastAPI, HTTPException, status from fastapi import Depends, FastAPI, HTTPException, status, Request
from datetime import datetime, timedelta from datetime import datetime, timedelta
from typing import List, Union, Optional from typing import List, Union, Optional
...@@ -65,17 +65,28 @@ async def get_model_by_id(id: str, user=Depends(get_verified_user)): ...@@ -65,17 +65,28 @@ async def get_model_by_id(id: str, user=Depends(get_verified_user)):
@router.post("/{id}/update", response_model=Optional[ModelModel]) @router.post("/{id}/update", response_model=Optional[ModelModel])
async def update_model_by_id( async def update_model_by_id(
id: str, form_data: ModelForm, user=Depends(get_admin_user) request: Request, id: str, form_data: ModelForm, user=Depends(get_admin_user)
): ):
model = Models.get_model_by_id(id) model = Models.get_model_by_id(id)
if model: if model:
model = Models.update_model_by_id(id, form_data) model = Models.update_model_by_id(id, form_data)
return model return model
else: else:
raise HTTPException( if form_data.id in request.app.state.MODELS:
status_code=status.HTTP_401_UNAUTHORIZED, model = Models.insert_new_model(form_data, user.id)
detail=ERROR_MESSAGES.ACCESS_PROHIBITED, print(model)
) if model:
return model
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.DEFAULT(),
)
else:
raise HTTPException(
status_code=status.HTTP_401_UNAUTHORIZED,
detail=ERROR_MESSAGES.DEFAULT(),
)
############################ ############################
......
...@@ -122,6 +122,9 @@ app.state.config.MODEL_FILTER_LIST = MODEL_FILTER_LIST ...@@ -122,6 +122,9 @@ app.state.config.MODEL_FILTER_LIST = MODEL_FILTER_LIST
app.state.config.WEBHOOK_URL = WEBHOOK_URL app.state.config.WEBHOOK_URL = WEBHOOK_URL
app.state.MODELS = {}
origins = ["*"] origins = ["*"]
...@@ -238,6 +241,11 @@ app.add_middleware( ...@@ -238,6 +241,11 @@ app.add_middleware(
@app.middleware("http") @app.middleware("http")
async def check_url(request: Request, call_next): async def check_url(request: Request, call_next):
if len(app.state.MODELS) == 0:
await get_all_models()
else:
pass
start_time = int(time.time()) start_time = int(time.time())
response = await call_next(request) response = await call_next(request)
process_time = int(time.time()) - start_time process_time = int(time.time()) - start_time
...@@ -269,8 +277,7 @@ app.mount("/api/v1", webui_app) ...@@ -269,8 +277,7 @@ app.mount("/api/v1", webui_app)
webui_app.state.EMBEDDING_FUNCTION = rag_app.state.EMBEDDING_FUNCTION webui_app.state.EMBEDDING_FUNCTION = rag_app.state.EMBEDDING_FUNCTION
@app.get("/api/models") async def get_all_models():
async def get_models(user=Depends(get_verified_user)):
openai_models = [] openai_models = []
ollama_models = [] ollama_models = []
...@@ -282,8 +289,6 @@ async def get_models(user=Depends(get_verified_user)): ...@@ -282,8 +289,6 @@ async def get_models(user=Depends(get_verified_user)):
if app.state.config.ENABLE_OLLAMA_API: if app.state.config.ENABLE_OLLAMA_API:
ollama_models = await get_ollama_models() ollama_models = await get_ollama_models()
print(ollama_models)
ollama_models = [ ollama_models = [
{ {
"id": model["model"], "id": model["model"],
...@@ -296,9 +301,6 @@ async def get_models(user=Depends(get_verified_user)): ...@@ -296,9 +301,6 @@ async def get_models(user=Depends(get_verified_user)):
for model in ollama_models["models"] for model in ollama_models["models"]
] ]
print("openai", openai_models)
print("ollama", ollama_models)
models = openai_models + ollama_models models = openai_models + ollama_models
custom_models = Models.get_all_models() custom_models = Models.get_all_models()
...@@ -330,6 +332,16 @@ async def get_models(user=Depends(get_verified_user)): ...@@ -330,6 +332,16 @@ async def get_models(user=Depends(get_verified_user)):
} }
) )
app.state.MODELS = {model["id"]: model for model in models}
webui_app.state.MODELS = app.state.MODELS
return models
@app.get("/api/models")
async def get_models(user=Depends(get_verified_user)):
models = await get_all_models()
if app.state.config.ENABLE_MODEL_FILTER: if app.state.config.ENABLE_MODEL_FILTER:
if user.role == "user": if user.role == "user":
models = list( models = list(
......
...@@ -7,6 +7,8 @@ ...@@ -7,6 +7,8 @@
import { WEBUI_NAME, modelfiles, models, settings, user } from '$lib/stores'; import { WEBUI_NAME, modelfiles, models, settings, user } from '$lib/stores';
import { addNewModel, deleteModelById, getModelInfos } from '$lib/apis/models'; import { addNewModel, deleteModelById, getModelInfos } from '$lib/apis/models';
import { deleteModel } from '$lib/apis/ollama';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { getModels } from '$lib/apis'; import { getModels } from '$lib/apis';
...@@ -17,13 +19,42 @@ ...@@ -17,13 +19,42 @@
let importFiles; let importFiles;
let modelfilesImportInputElement: HTMLInputElement; let modelfilesImportInputElement: HTMLInputElement;
const deleteModelHandler = async (id) => { const deleteModelHandler = async (model) => {
const res = await deleteModelById(localStorage.token, id); if (model?.info?.base_model_id) {
const res = await deleteModelById(localStorage.token, model.id);
if (res) {
toast.success($i18n.t(`Deleted {{name}}`, { name: model.id }));
}
await models.set(await getModels(localStorage.token));
} else if (model?.owned_by === 'ollama') {
const res = await deleteModel(localStorage.token, model.id);
if (res) {
toast.success($i18n.t(`Deleted {{name}}`, { name: model.id }));
}
await models.set(await getModels(localStorage.token));
} else {
toast.error(
$i18n.t('{{ owner }}: You cannot delete this model', {
owner: model.owned_by.toUpperCase()
})
);
}
};
if (res) { const cloneModelHandler = async (model) => {
toast.success($i18n.t(`Deleted {{tagName}}`, { id })); if ((model?.info?.base_model_id ?? null) === null) {
toast.error($i18n.t('You cannot clone a base model'));
return;
} else {
sessionStorage.model = JSON.stringify({
...model,
id: `${model.id}-clone`,
name: `${model.name} (Clone)`
});
goto('/workspace/models/create');
} }
await models.set(await getModels(localStorage.token));
}; };
const shareModelHandler = async (model) => { const shareModelHandler = async (model) => {
...@@ -104,7 +135,7 @@ ...@@ -104,7 +135,7 @@
<div class=" self-center w-10"> <div class=" self-center w-10">
<div class=" rounded-full bg-stone-700"> <div class=" rounded-full bg-stone-700">
<img <img
src={model?.meta?.profile_image_url ?? '/favicon.png'} src={model?.info?.meta?.profile_image_url ?? '/favicon.png'}
alt="modelfile profile" alt="modelfile profile"
class=" rounded-full w-full h-auto object-cover" class=" rounded-full w-full h-auto object-cover"
/> />
...@@ -114,7 +145,7 @@ ...@@ -114,7 +145,7 @@
<div class=" flex-1 self-center"> <div class=" flex-1 self-center">
<div class=" font-bold capitalize">{model.name}</div> <div class=" font-bold capitalize">{model.name}</div>
<div class=" text-sm overflow-hidden text-ellipsis line-clamp-1"> <div class=" text-sm overflow-hidden text-ellipsis line-clamp-1">
{model?.meta?.description ?? 'No description'} {model?.info?.meta?.description ?? model.id}
</div> </div>
</div> </div>
</a> </a>
...@@ -122,7 +153,7 @@ ...@@ -122,7 +153,7 @@
<a <a
class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl" class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button" type="button"
href={`/workspace/models/edit?tag=${encodeURIComponent(model.id)}`} href={`/workspace/models/edit?id=${encodeURIComponent(model.id)}`}
> >
<svg <svg
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
...@@ -144,8 +175,7 @@ ...@@ -144,8 +175,7 @@
class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl" class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button" type="button"
on:click={() => { on:click={() => {
sessionStorage.model = JSON.stringify(model); cloneModelHandler(model);
goto('/workspace/models/create');
}} }}
> >
<svg <svg
...@@ -191,7 +221,7 @@ ...@@ -191,7 +221,7 @@
class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl" class="self-center w-fit text-sm px-2 py-2 dark:text-gray-300 dark:hover:text-white hover:bg-black/5 dark:hover:bg-white/5 rounded-xl"
type="button" type="button"
on:click={() => { on:click={() => {
deleteModelHandler(model.id); deleteModelHandler(model);
}} }}
> >
<svg <svg
......
...@@ -48,7 +48,7 @@ export type Model = OpenAIModel | OllamaModel; ...@@ -48,7 +48,7 @@ export type Model = OpenAIModel | OllamaModel;
type BaseModel = { type BaseModel = {
id: string; id: string;
name: string; name: string;
custom_info?: ModelConfig; info?: ModelConfig;
}; };
export interface OpenAIModel extends BaseModel { export interface OpenAIModel extends BaseModel {
......
...@@ -5,181 +5,83 @@ ...@@ -5,181 +5,83 @@
import { onMount, getContext } from 'svelte'; import { onMount, getContext } from 'svelte';
import { page } from '$app/stores'; import { page } from '$app/stores';
import { settings, user, config, models } from '$lib/stores';
import { settings, user, config, modelfiles } from '$lib/stores';
import { splitStream } from '$lib/utils'; import { splitStream } from '$lib/utils';
import { createModel } from '$lib/apis/ollama';
import { getModelInfos, updateModelById } from '$lib/apis/models'; import { getModelInfos, updateModelById } from '$lib/apis/models';
import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte'; import AdvancedParams from '$lib/components/chat/Settings/Advanced/AdvancedParams.svelte';
import { getModels } from '$lib/apis';
const i18n = getContext('i18n'); const i18n = getContext('i18n');
let loading = false; let loading = false;
let success = false;
let filesInputElement; let filesInputElement;
let inputFiles; let inputFiles;
let imageUrl = null;
let digest = ''; let digest = '';
let pullProgress = null; let pullProgress = null;
let success = false;
let modelfile = null;
// /////////// // ///////////
// Modelfile // model
// /////////// // ///////////
let title = ''; let model = null;
let tagName = ''; let info = {
let desc = ''; id: '',
base_model_id: null,
// Raw Mode name: '',
let content = ''; meta: {
profile_image_url: '/favicon.png',
let suggestions = [ description: '',
{ content: '',
content: '' suggestion_prompts: []
} },
]; params: {}
let categories = {
character: false,
assistant: false,
writing: false,
productivity: false,
programming: false,
'data analysis': false,
lifestyle: false,
education: false,
business: false
};
onMount(() => {
tagName = $page.url.searchParams.get('tag');
if (tagName) {
modelfile = $modelfiles.filter((modelfile) => modelfile.tagName === tagName)[0];
console.log(modelfile);
imageUrl = modelfile.imageUrl;
title = modelfile.title;
desc = modelfile.desc;
content = modelfile.content;
suggestions =
modelfile.suggestionPrompts.length != 0
? modelfile.suggestionPrompts
: [
{
content: ''
}
];
for (const category of modelfile.categories) {
categories[category.toLowerCase()] = true;
}
} else {
goto('/workspace/modelfiles');
}
});
const updateModelfile = async (modelfile) => {
await updateModelById(localStorage.token, modelfile.tagName, modelfile);
await modelfiles.set(await getModelInfos(localStorage.token));
}; };
const updateHandler = async () => { const updateHandler = async () => {
loading = true; loading = true;
const res = await updateModelById(localStorage.token, info.id, info);
if (Object.keys(categories).filter((category) => categories[category]).length == 0) { if (res) {
toast.error( await goto('/workspace/models');
'Uh-oh! It looks like you missed selecting a category. Please choose one to complete your modelfile.' await models.set(await getModels(localStorage.token));
);
} }
if (
title !== '' &&
desc !== '' &&
content !== '' &&
Object.keys(categories).filter((category) => categories[category]).length > 0
) {
const res = await createModel(localStorage.token, tagName, content);
if (res) {
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);
if (data.status === 'success') {
success = true;
}
} else {
if (data.digest) {
digest = data.digest;
if (data.completed) {
pullProgress = Math.round((data.completed / data.total) * 1000) / 10;
} else {
pullProgress = 100;
}
}
}
}
}
}
} catch (error) {
console.log(error);
toast.error(error);
}
}
}
if (success) {
await updateModelfile({
tagName: tagName,
imageUrl: imageUrl,
title: title,
desc: desc,
content: content,
suggestionPrompts: suggestions.filter((prompt) => prompt.content !== ''),
categories: Object.keys(categories).filter((category) => categories[category])
});
await goto('/workspace/modelfiles');
}
}
loading = false; loading = false;
success = false; success = false;
}; };
onMount(() => {
const id = $page.url.searchParams.get('id');
if (id) {
model = $models.find((m) => m.id === id);
if (model) {
info = {
...info,
...JSON.parse(
JSON.stringify(
model?.info
? model?.info
: {
id: model.id,
name: model.name
}
)
)
};
console.log(model);
} else {
goto('/workspace/models');
}
} else {
goto('/workspace/models');
}
});
</script> </script>
<div class="w-full max-h-full"> <div class="w-full max-h-full">
...@@ -229,7 +131,7 @@ ...@@ -229,7 +131,7 @@
const compressedSrc = canvas.toDataURL('image/jpeg'); const compressedSrc = canvas.toDataURL('image/jpeg');
// Display the compressed image // Display the compressed image
imageUrl = compressedSrc; info.meta.profile_image_url = compressedSrc;
inputFiles = null; inputFiles = null;
}; };
...@@ -270,238 +172,230 @@ ...@@ -270,238 +172,230 @@
</div> </div>
<div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div> <div class=" self-center font-medium text-sm">{$i18n.t('Back')}</div>
</button> </button>
<form
class="flex flex-col max-w-2xl mx-auto mt-4 mb-10"
on:submit|preventDefault={() => {
updateHandler();
}}
>
<div class="flex justify-center my-4">
<div class="self-center">
<button
class=" {imageUrl
? ''
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200"
type="button"
on:click={() => {
filesInputElement.click();
}}
>
{#if imageUrl}
<img
src={imageUrl}
alt="modelfile profile"
class=" rounded-full w-20 h-20 object-cover"
/>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-8"
>
<path
fill-rule="evenodd"
d="M12 3.75a.75.75 0 01.75.75v6.75h6.75a.75.75 0 010 1.5h-6.75v6.75a.75.75 0 01-1.5 0v-6.75H4.5a.75.75 0 010-1.5h6.75V4.5a.75.75 0 01.75-.75z"
clip-rule="evenodd"
/>
</svg>
{/if}
</button>
</div>
</div>
<div class="my-2 flex space-x-2">
<div class="flex-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Name')}*</div>
<div> {#if model}
<input <form
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg" class="flex flex-col max-w-2xl mx-auto mt-4 mb-10"
placeholder={$i18n.t('Name your modelfile')} on:submit|preventDefault={() => {
bind:value={title} updateHandler();
required }}
/> >
<div class="flex justify-center my-4">
<div class="self-center">
<button
class=" {info?.meta?.profile_image_url
? ''
: 'p-6'} rounded-full dark:bg-gray-700 border border-dashed border-gray-200"
type="button"
on:click={() => {
filesInputElement.click();
}}
>
{#if info?.meta?.profile_image_url}
<img
src={info?.meta?.profile_image_url}
alt="modelfile profile"
class=" rounded-full w-20 h-20 object-cover"
/>
{:else}
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
fill="currentColor"
class="w-8"
>
<path
fill-rule="evenodd"
d="M12 3.75a.75.75 0 01.75.75v6.75h6.75a.75.75 0 010 1.5h-6.75v6.75a.75.75 0 01-1.5 0v-6.75H4.5a.75.75 0 010-1.5h6.75V4.5a.75.75 0 01.75-.75z"
clip-rule="evenodd"
/>
</svg>
{/if}
</button>
</div> </div>
</div> </div>
<div class="flex-1"> <div class="my-2 flex space-x-2">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Model Tag Name')}*</div> <div class="flex-1">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Name')}*</div>
<div> <div>
<input <input
class="px-3 py-1.5 text-sm w-full bg-transparent disabled:text-gray-500 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 model tag name')} placeholder={$i18n.t('Name your model')}
value={tagName} bind:value={info.name}
disabled required
required />
/> </div>
</div> </div>
</div>
</div>
<div class="my-2">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Description')}*</div>
<div> <div class="flex-1">
<input <div class=" text-sm font-semibold mb-2">{$i18n.t('Model ID')}*</div>
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 modelfile does')}
bind:value={desc}
required
/>
</div>
</div>
<div class="my-2"> <div>
<div class="flex w-full justify-between"> <input
<div class=" self-center text-sm font-semibold">{$i18n.t('Modelfile')}</div> class="px-3 py-1.5 text-sm w-full bg-transparent disabled:text-gray-500 border dark:border-gray-600 outline-none rounded-lg"
placeholder={$i18n.t('Add a model id')}
value={info.id}
disabled
required
/>
</div>
</div>
</div> </div>
<!-- <div class=" text-sm font-semibold mb-2"></div> --> <div class="my-2">
<div class=" text-sm font-semibold mb-2">{$i18n.t('description')}*</div>
<div class="mt-2">
<div class=" text-xs font-semibold mb-2">{$i18n.t('Content')}*</div>
<div> <div>
<textarea <input
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={`FROM llama2\nPARAMETER temperature 1\nSYSTEM """\nYou are Mario from Super Mario Bros, acting as an assistant.\n"""`} placeholder={$i18n.t('Add a short description about what this model does')}
rows="6" bind:value={info.meta.description}
bind:value={content}
required required
/> />
</div> </div>
</div> </div>
</div>
<div class="my-2">
<div class="flex w-full justify-between mb-2">
<div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
<button
class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (suggestions.length === 0 || suggestions.at(-1).content !== '') {
suggestions = [...suggestions, { content: '' }];
}
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div>
<div class="flex flex-col space-y-1">
{#each suggestions as prompt, promptIdx}
<div class=" flex border dark:border-gray-600 rounded-lg">
<input
class="px-3 py-1.5 text-sm w-full bg-transparent outline-none border-r dark:border-gray-600"
placeholder={$i18n.t('Write a prompt suggestion (e.g. Who are you?)')}
bind:value={prompt.content}
/>
<button <div class="my-2">
class="px-2" <div class="flex w-full justify-between">
type="button" <div class=" self-center text-sm font-semibold">{$i18n.t('Model')}</div>
on:click={() => { </div>
suggestions.splice(promptIdx, 1);
suggestions = suggestions;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div>
</div>
<div class="my-2"> <!-- <div class=" text-sm font-semibold mb-2"></div> -->
<div class=" text-sm font-semibold mb-2">{$i18n.t('Categories')}</div>
<div class="grid grid-cols-4"> <div class="mt-2">
{#each Object.keys(categories) as category} <div class=" text-xs font-semibold mb-2">{$i18n.t('Params')}*</div>
<div class="flex space-x-2 text-sm">
<input type="checkbox" bind:checked={categories[category]} />
<div class=" capitalize">{category}</div> <div>
<!-- <textarea
class="px-3 py-1.5 text-sm w-full bg-transparent border dark:border-gray-600 outline-none rounded-lg"
placeholder={`FROM llama2\nPARAMETER temperature 1\nSYSTEM """\nYou are Mario from Super Mario Bros, acting as an assistant.\n"""`}
rows="6"
bind:value={content}
required
/> -->
</div> </div>
{/each} </div>
</div> </div>
</div>
{#if pullProgress !== null}
<div class="my-2"> <div class="my-2">
<div class=" text-sm font-semibold mb-2">{$i18n.t('Pull Progress')}</div> <div class="flex w-full justify-between mb-2">
<div class="w-full rounded-full dark:bg-gray-800"> <div class=" self-center text-sm font-semibold">{$i18n.t('Prompt suggestions')}</div>
<div
class="dark:bg-gray-600 text-xs font-medium text-blue-100 text-center p-0.5 leading-none rounded-full" <button
style="width: {Math.max(15, pullProgress ?? 0)}%" class="p-1 px-3 text-xs flex rounded transition"
type="button"
on:click={() => {
if (
info.meta.suggestion_prompts.length === 0 ||
info.meta.suggestion_prompts.at(-1).content !== ''
) {
info.meta.suggestion_prompts = [...info.meta.suggestion_prompts, { content: '' }];
}
}}
> >
{pullProgress ?? 0}% <svg
</div> xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"
/>
</svg>
</button>
</div> </div>
<div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;"> <div class="flex flex-col space-y-1">
{digest} {#each info.meta.suggestion_prompts as prompt, promptIdx}
<div class=" flex border dark:border-gray-600 rounded-lg">
<input
class="px-3 py-1.5 text-sm w-full bg-transparent outline-none border-r dark:border-gray-600"
placeholder={$i18n.t('Write a prompt suggestion (e.g. Who are you?)')}
bind:value={prompt.content}
/>
<button
class="px-2"
type="button"
on:click={() => {
info.meta.suggestion_prompts.splice(promptIdx, 1);
info.meta.suggestion_prompts = info.meta.suggestion_prompts;
}}
>
<svg
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 20 20"
fill="currentColor"
class="w-4 h-4"
>
<path
d="M6.28 5.22a.75.75 0 00-1.06 1.06L8.94 10l-3.72 3.72a.75.75 0 101.06 1.06L10 11.06l3.72 3.72a.75.75 0 101.06-1.06L11.06 10l3.72-3.72a.75.75 0 00-1.06-1.06L10 8.94 6.28 5.22z"
/>
</svg>
</button>
</div>
{/each}
</div> </div>
</div> </div>
{/if}
<div class="my-2 flex justify-end">
<button
class=" text-sm px-3 py-2 transition rounded-xl {loading
? ' cursor-not-allowed bg-gray-100 dark:bg-gray-800'
: ' bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-800'} flex"
type="submit"
disabled={loading}
>
<div class=" self-center font-medium">{$i18n.t('Save & Update')}</div>
{#if loading} {#if pullProgress !== null}
<div class="ml-1.5 self-center"> <div class="my-2">
<svg <div class=" text-sm font-semibold mb-2">{$i18n.t('Pull Progress')}</div>
class=" w-4 h-4" <div class="w-full rounded-full dark:bg-gray-800">
viewBox="0 0 24 24" <div
fill="currentColor" class="dark:bg-gray-600 text-xs font-medium text-blue-100 text-center p-0.5 leading-none rounded-full"
xmlns="http://www.w3.org/2000/svg" style="width: {Math.max(15, pullProgress ?? 0)}%"
><style>
.spinner_ajPY {
transform-origin: center;
animation: spinner_AtaB 0.75s infinite linear;
}
@keyframes spinner_AtaB {
100% {
transform: rotate(360deg);
}
}
</style><path
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
opacity=".25"
/><path
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
class="spinner_ajPY"
/></svg
> >
{pullProgress ?? 0}%
</div>
</div> </div>
{/if} <div class="mt-1 text-xs dark:text-gray-500" style="font-size: 0.5rem;">
</button> {digest}
</div> </div>
</form> </div>
{/if}
<div class="my-2 flex justify-end">
<button
class=" text-sm px-3 py-2 transition rounded-xl {loading
? ' cursor-not-allowed bg-gray-100 dark:bg-gray-800'
: ' bg-gray-50 hover:bg-gray-100 dark:bg-gray-700 dark:hover:bg-gray-800'} flex"
type="submit"
disabled={loading}
>
<div class=" self-center font-medium">{$i18n.t('Save & Update')}</div>
{#if loading}
<div class="ml-1.5 self-center">
<svg
class=" w-4 h-4"
viewBox="0 0 24 24"
fill="currentColor"
xmlns="http://www.w3.org/2000/svg"
><style>
.spinner_ajPY {
transform-origin: center;
animation: spinner_AtaB 0.75s infinite linear;
}
@keyframes spinner_AtaB {
100% {
transform: rotate(360deg);
}
}
</style><path
d="M12,1A11,11,0,1,0,23,12,11,11,0,0,0,12,1Zm0,19a8,8,0,1,1,8-8A8,8,0,0,1,12,20Z"
opacity=".25"
/><path
d="M10.14,1.16a11,11,0,0,0-9,8.92A1.59,1.59,0,0,0,2.46,12,1.52,1.52,0,0,0,4.11,10.7a8,8,0,0,1,6.66-6.61A1.42,1.42,0,0,0,12,2.69h0A1.57,1.57,0,0,0,10.14,1.16Z"
class="spinner_ajPY"
/></svg
>
</div>
{/if}
</button>
</div>
</form>
{/if}
</div> </div>
{
"description": "Developer lead assistant with no code explanation",
"profile_image_url": "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/4gHYSUNDX1BST0ZJTEUAAQEAAAHIAAAAAAQwAABtbnRyUkdCIFhZWiAH4AABAAEAAAAAAABhY3NwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAA9tYAAQAAAADTLQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAlkZXNjAAAA8AAAACRyWFlaAAABFAAAABRnWFlaAAABKAAAABRiWFlaAAABPAAAABR3dHB0AAABUAAAABRyVFJDAAABZAAAAChnVFJDAAABZAAAAChiVFJDAAABZAAAAChjcHJ0AAABjAAAADxtbHVjAAAAAAAAAAEAAAAMZW5VUwAAAAgAAAAcAHMAUgBHAEJYWVogAAAAAAAAb6IAADj1AAADkFhZWiAAAAAAAABimQAAt4UAABjaWFlaIAAAAAAAACSgAAAPhAAAts9YWVogAAAAAAAA9tYAAQAAAADTLXBhcmEAAAAAAAQAAAACZmYAAPKnAAANWQAAE9AAAApbAAAAAAAAAABtbHVjAAAAAAAAAAEAAAAMZW5VUwAAACAAAAAcAEcAbwBvAGcAbABlACAASQBuAGMALgAgADIAMAAxADb/2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCgsOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD/2wBDAQMDAwQDBAgEBAgQCwkLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBD/wAARCABkAGQDASIAAhEBAxEB/8QAHQAAAQQDAQEAAAAAAAAAAAAAAAUGBwgCBAkBA//EADkQAAEDAwMCBQEGBAUFAAAAAAECAwQFBhEAEiEHMQgTIkFRYRQjMnGBkRUzQlIXJHKh0RaCkrHB/8QAGwEAAQUBAQAAAAAAAAAAAAAABgABAwQFAgf/xAA0EQABAgUCBAQEBAcAAAAAAAABAhEAAwQFIRIxQVFxgQYTImGRsfDxMkKhwQcUFSRSYtH/2gAMAwEAAhEDEQA/AOcQA9zrIJyeDrHHGdbENnzl7QMn2HydbccEtmFCn0tchtLinmGvMVsb8xe3er4+g7DccJ+vfSvCo77bi25TSmVtEpWlxJSUqHsQeQfodOG3bZqLsih0yW81AclLSuKuW0kt+U6cFe1Q5OQcDueNvJGn7bVuUiNcM1lVbXVGfMC26lFSpPnHOc+o7hnOc5ByMHToUkr0Hdn4/PbtGJX1aZUrzSfTt9cYZFHt9+a4lmOyST8+2nnD6S3JMfRFYpshxxz8KG2FqKvy451eTw2eDGnVqInqB1JRIiQHSJMSC4va4tkDKVuqP4Qe+Pg6tWzaApVrGBY1EplMKSoluMUJ80J7J3gElXyT++kqtkS1CW+XZ3YCBoS7hVjz5YZDEgM6ldB+5+EcfKt0KvCmRzJnUSpREdtz8Nbaf3I7ajyv2vIpii26EnvlSRxrtNNpt5UaiyKxU5FOVBjJUouhw7lp2nB38cFWAM98/vFN9dBenF9uqkVCkUiJUlJw1LjFpIW+RnYtKSEqyM+rHcjnJGbSDLmg6SDFNNVXUagqckkbswB+Z5YjkLNgqb5CTj2OMZ0mVKmyYLnlyWS2vaFhOedpGR/tq8vU3pbbvS+JVoV3WymQphRkQE7TtUtQKQQocgEhI+MgDvjVY6/07rcyS/VKhCYgtPBCmQ2coKVJyNuCckDv3OfbUM2WqWpjBRaLmK9BIBDcf2iOptHYaYklhb/mw2m33vMSAlSFKQkFOD/c4n9NI4GdONyAXG3qbT3VSJCf5risgqbTztQD/TkZP+lPAwdN5xCmXFNrGCDqKCNJcRho0aNKHjJOCDz7cDUo9FLZrdTrqpVEpqJzsJhUl5h5KSy4yAVEOJc9KhgE8/GRzqO6YYwQ4l1kvLcSUpSBgp4Pqz9Dz29u+rjeFjw31G5LLk9S3qk4mG04YyEMqwHCMBQUDwUjcARj99D/AImvCbFbl1jsRtgn9B7fDeNeyWuVd6xNLUfgO+W3x84QlWtP6j30xK/hbjCqktLLBQdiWlpQAAOwSjCTntgasf0L6JUCtX+uoV12RPjW1/mZrklwrEh/OEIJUTlO4Ek9iEnPfTOvV6g0KS1bdLq7LNYiNqkIbaUUEZHG44x9SBzjPtqc/DDWmKP0qui6lPQ33JD/AKVKUMY8kkJyfqc//dWvDVzm3mgTVrlspTM4Z0k4PQtHm/jqxos13FHKmvIRu2cpGQejjEWrplEduijQZlZVIitrQV/Y2XChCknsV45OR7fXTauZHTXpKpm47jveTSGUPF1lh+WpSXAkEqSGwCpSQkq47dtJsfxBwYEOnRahbkl+RIp5luOQnm1MpbSg5UCSMYKQCCeM++Ma5eeIrxEV6/LvlVhxEp4uuSG48QhTyUtJWoBCMcbex5JBP0I1VrF1tGsy1+kKfHBn+t8wU2W30F2HmpZRQzlsu31tiOltu+L7w1XDcTFkUy5EpdqEpuKyXac43GekLUNidxTgEkjlQGpsi0Gjwpbk2JTYzLruNy0NJSSeecgd+e+uElsdJ/EjdtErN3ROn77dLpiBIccSpCFbQ4hX3baDlSglC/btz7Z12G8JnUif1O6CW7dVSkLkyg25GceUoqW8WiUhRzySQNZyZoyELfmxjYraBEgJmaWbmMwzvF10ohXJ03rRpsNs1GNEeqELekrCy2NzrXzhSRkDP4kp1yNotHuaqThDp6JbEZ9fBAOwEJOSn9M9tdtbsmiXVVNKdfeaMYlQWMpQHAfQBjjgjIPPtrlxWLc6fUq37ouaBeNShXfTKo5Fp9BQz9y5FCglR3gcZBcUDkJBQAeVDJ1bkhcuUmpyMP0jzhFVKpaqeiSNOS3Xb66RDlZtagUSrtrbnyP4hFUlzzXAkp3DHO33Go9vB+LImyHH0BuoeafMQ2kBAOeSPgH204a9MfVLVKktOLyrncgg/ue2mbXl/aJiprqlb5Hrxjt+vx/xq1cpUlCgZQA6coKKATglpp3HGEzRo0azIvwo0iFMnlbcFlTi2x5hwCeB9ANXD8PfiQqHT6hvdPY9KcqNHkPeamMhX3zDpQN2Rjtxn8xqp1k1mqUSoKdpjnlqfSWFHcPwkcjHvxqx9PsqHavTo3dKUqVJjoRLfW02ltKWk7XHkn33lreE59wOw1UuVno7zRqpq1GpG5HHHI4LwkXKfa5yZ1ORqdg+R3hW6l31Kk3G/dESlNwU1SKmHIQ+nKwoA7HM+xwRhQ+n5iefCLf0aq2lcdoVNtiVFp7jNXQwpoLEhls4cST7gENgkn8KvjUWUO0rav20qqic5Lrk9qA69AVHc9SVMY3DgY8vy1NOAr4wrjSt0RoMDp46q5FVZyl1+DUZUV1ie+y3AnQG1FtzygpQW4FoKk5BzuHAJB1H4dqrZNQaSgQUkADO7J9Iy5JZmgc8Sy7lUJFVXkEpLsNgV+rYAYJx2bhEzdRaI3QJEdulNNi36l5lQpUxj0ulhw48pageNispKTz3+dV3qvT65qJfkS7LD6ZU64JDrzsmUZtWSHHN52koQVYbOC5kkkEjkDIBs3GoNQuRul1W1Cudbcqol1K3gsR2N5QFNuHGQMp7AZIIIByNQd0369IrPWK++nlctSiuMwnnkUdctoNtQkIkJjuNvPHKlbvu1j2UoYOMjC8YVEpFJLkvqWMluI2z77Rf/h1S1Jq50/TplkAZwX/1HEb54YESDJ8SvV0R4dn9MvDpEptEjMtJqzlaqjZcPmp3FTaWVblIKQSlZB3gpIAyNTr4OZQ6eeGWZKepqmmaK/UZyo4WCoDcp3ywc44BCc8DjVdLv6pu2fYteuO7WrUuCqRIDsSm/YWigpU02fKaWkoAW2jJO48ZxtznX28Ht9Vy4ujkrpq9VnG3avMdY2vqShc5v7OjzEtPr4UQUuZ9ikKGcjBDrPKRPmGW2l+OWxz37Yg88Ry5lLR+ekamIJHEu4wMdSHdtotdNvplVhS76q0hhQbivSnW9oQlB2DY2k+/Khj3yrVC7bpVp1e+KS9crcppUqqMInPSWQ2wmIcFxSlk8EZ+exzpx9W/EhelEkf4QQLAnUSU+r7O3/GYzrS9vBD/AJZTgp2jeCQpJwkg++o46q9VZRgU3pLYS5M+rONIgPupkArc5SFMb92BnykhROMJQrn7xWS2nrRQyxTqLgAkqJGBwzj7Z4GPMbj4ZNbUCtSdIJACW34qfMW88VXTzofP6FVKu0GgW4ZbTbblNm09hkFxe8J2hafx5Tu9z8+2uUt6KrlRVEpri5U2HQ4YYjpQjKY7ZUVEZA7ZPc6sj1BHUe0en9JoNWr0wuyEqQ+l8q8tACQfLZ/pUnKuVA8beeeNQMbqrlIYqtHgRm3xW2G2pG5lO9KUqyAkqHHIH6ampqrzJIMs6gcjLj4wWSaQJYzT6Rx+8RkQQSCCCO4OjX0klYfWFoAVuOR9dGrgdsxFG7QyszEtskh08tEDOFf84z+uNXEsu4XplKRCmYUxLgIjSI76DtSvZsGQASAPxfkCPcaqTaMeQ3UGapHfhJMZalbZK8JVtTnB/PsNSlbXV+sSruauebTZU1C1Bx1LbatpAONvGRwAeeM6h8yf5umWzNvxfpxjuZIkTad1uVPtzHXnE29JbL64Wk9Wadbdhu1SmPNhFMfFUhtpcABbxtdfQvaWlkjcB6mm8jA19ha9+xuq9BpvValOMU6DHNUqsVE9hzzkNpAbTllxQAW55aFdjsK8YJzpO6pTZKrybj0ev1WHRqnFadp70WS422lCgHUghKuSU4BOe24540jW5X5lChVm9qRVqk1MqJaprK5MkydvkukOoSXd3Csg/BwdC9Db6mnrEzULSNTHAIPqA98e45xt3SdLVIUZ6HOkd86gQeh368otM/1oRVLer0OHJShyMw7Gjw0uFOxCGwpK0IwNuCeCMcpz9TTvqBdVIg3nDr0Btxut1hmQmoodSoMSmMt7dytpBO5KvlQ2jv7uun9UL0SpTgrmFOApWpMVgFQIwQfRzwSP11sm4pdVWHpwiPuJAAWuCxkAHIx6OOdb86xmdLUAoOebwNUfiKXQT0zCgkDgGhlUut23eNzRrPXTDBpU6PMNQdRJVveDUZ14Np83BCXFtJTnv6u27BEw9H58KkrqFajx0xIzKEMx20pCQlA3cgADk8/ofqdJFOdeckoltiI283yl37I0FJ9iQdvwSNLaZciOyoCYooPJQltsAn57aalsK6eXoKgT3hXTxZKr5oWhCgANnEPO97u/xasiqUWDTWnbppDD7lr1B47nmJaEBXlA8ZS4UhI3HalSkL9lAwH0O6CeJK25zl9sdMpsoS4RaantXBTEO7FkFZBVJylSilPqIztChj1HT6oNzmj1WpTHGQ6ptkMRGQnG5agn0pwAO53KJPpSD7kai2NIuCRVLkji+q9QoLTqks4qDq47SyEkjalQG0E4SEkZJHfWFeJq7WkzUsySHwTttgHh0MbNopRfAKcfmBI4Y3I9nhz+I+T1OqjlPi1hxqAxFKj9gkTGJD4KgPUox9yP6f7s/Q99V0vC170okGLctUp62IU8FEZ9LiD5m3vwklQxj+oDU1TqHV6VWKXS25KbiaeRh59TTiFrcUDkklak4T3xj2+un74iOiVnWv4e6Lf6r+W7W0tNsqiJWlxhxThyWkgDIIAA79kEkZ11ZL8LkEB3d8tvjHTvG3d/D8qz0oDEKB24e/P9Giju4k5zydGg9zjRosgSjYp7AlTY8VbvlJedQhTg7oBIGf076vH4ZL8tayukdSbnU9ksR1vq2vgLUtRVtwrtnIGce2qRQaXImJDqcpQVbQe+T8asp0W6YVG4oX8BuK9IlMhywl9tnJdfeSe5SrIQCP7T6vbA76yL35Uum11EzQk47sflBBYFDzCnytZBBOAcAgkZ4H23iR7OofTC5en9Fr9zTquXac1uaS1KG8OsuLLZTtThCQSQd2RjgnSJIhx5nR6uSbbkF+l0VyKt1by0p2qcfSlAQnaVE4c7qUODnvxqykZ7o94c+nbNs9PqHMu+sVaMWJrbzaVJllaSFBRwQkZUTwM5HCe4FTuoTVlUuzpc2w+odLZZqKmV1S3iuUtZc88DZGcS35CkIWpJ8tZSpCU8KWcZilr82YmbIONQz7PnpA/KlT5fnIr5qlgvpBDaf8U9uO5hpxJwSAErPbn89O+zv4fU7kpVKqlUECFNnR40iYpvcI7S3EpU6U5GQkEqxkdvbUWxKoxxmQgf9w0twqxEBSFSmhjn+YBopSoEbwNTqdXLMWO6wUyxrTuSFB6eXEmsU5UJtTrwRt++BIOQSTkgAn2z24xpss1za2UOsIWT2I1GcSvQxyZjA5zw4Mf+9LEa4acB97PZAxn+YnUydIDPGcqnmPkZ6Q+4NsVNih1S+luOM01x9uC8422hQaJLe0LKgopClKTgpTgkYJyUpKWOmVOv+5pMB6qqH2iKKnuiJCvOU2tpK0+tSEg5UjOTjgYHvpY6XRXOotRes+pXCyu23FokOU9M9TBWpO0l0lA5AIQACR6u2cEibHrZ8PViPCmW1GuhutMpLiJqFsvbUlOxSUh13btPHHf0j40I3O31NSFhaCsKJbTuE9Txg1td9orcqUlK9KkpD6tnbOOUJthdLLQgWLXanWai1TI9IcShbtQfaSre9wnG1SgMkYGCSTqmvW+lVRFUmmLOZVDjKWpSA+FAKxjeUA+kkE4J576tXcUfp5cVmVuyq/HrK1VB5E9morQ0XUyWcloqShzG0ZIwO3++qS3za67ckzanIq7Mwy38rQvcHFEZI3pIAI5PYn8hnQ/YfDFVaKlc4lSUqOArOPY9IMrj4tk3um/lnC2Y49LYAx7OHiLjgEjPbjRrJxZccUsAJBJICRgD6AfGjR1AazRsQ6hJhg+U6QPgak/pr1BqseZHptRc+0Q8pQhxWSWxn3Sn1HGe6efodRNrbp9SfgOhTfKcglO7H7H2OqtfRy6+SZM0OIu0FZMoZwmyy0XpoPVagQIsyK9b8qtU5/PlyJLCo62CPTvS4tad6ce/BHfB5GmRdnhqo101pLtkR36eiQjz3XX8MxcYzuRkE5xz6AofUd9QXVurVSlwIcBFRLwSwho7g4G2U8A7iSpSiByQPT8acnTvxC3bbduS7aerjkWK+2ChJRu49wgkFSM8/h5PtoQ/o1ba5YVQl/bj9doLZN0ttxm/36W9xgd9/mI1bh6KSLLqq4kx8yUpOAWVBLavy3AnWIslFIDU2o0f+JU93nLeIrwB/tUpKkr/APHPzjTjtW8qHc8iXOqt6tUtceO6827IYU84++kehtPqyncT+I5GB254njw4zeklxvy5N3uw5stsAtGc5lLh/qGcjkccY+f0JqWqrhITLny0Jzv+b/g+BjAu67X6zShSm5DHbiYrbPm9OkM+Xa3Tp5BQoNuza9N8wIcI9mmQkEDvkk/6de23SLGrK3kXzVZ0RkHDSafT0fZ1A4yBsyeD/dgY+upt68w+nzFekvWmqjNwJP8AMZUk7EOpIOG3U5KQPfIV2+uq+V6bbMRIapbP+ZUCRKjvqSsnOVAFJwpPB5W3u79tSqKqlJSSR7j7MfhGXTaKZSZwQDjZQJ+OXHYxMVFpFoW+hc+074tyqsNM+UmBVYSktlGQSCU4IPHdIzyfnSo11u6QyWG/+peky6M/CUcVSgz1OMq+QY76kkpOO3mZxnGDqsa7zqMF8sy0olhslG15oBxGMdzj6/7aRavX5dTXhb61IByMnj9B2GuU0JIJmrUo8/wkd0s/eJZ9TKmKBlSUoHFiog9lEt2iwnVTrN04XTY83p+mS5NlJUHGy48luOQSAobznJHO3kD+49hXitV2q1t9L9TnrlLCeCr2B5xpOKlK7nXmrcmV5CNDk9STFZagouAB0g0aNGpo4g9gdGjRpjtDwayyQeFEYweONGjShHePNyknKSQe3GtqnVip0xS0wJjjIWkhQSe4PB0aNIwhkiM5lZqlQaSxLmuuNo5CN3pB/L9v21poUps5QtSSTtJBwcEHRo0oQMeKUpR3LUVE9yTk680aNPDQaNGjShQaNGjTiFH/2Q==",
"ollama": {
"modelfile": "FROM llama3\nPARAMETER temperature 1\nSYSTEM \"\"\"\nI want you to act as a senior full-stack tech leader and top-tier brilliant software developer, you embody technical excellence and a deep understanding of a wide range of technologies. Your expertise covers not just coding, but also algorithm design, system architecture, and technology strategy. for every question there is no need to explain, only give the solution.\n\nCoding Mastery: Possess exceptional skills in programming languages including Python, JavaScript, SQL, NoSQL, mySQL, C++, C, Rust, Groovy, Go, and Java. Your proficiency goes beyond mere syntax; you explore and master the nuances and complexities of each language, crafting code that is both highly efficient and robust. Your capability to optimize performance and manage complex codebases sets the benchmark in software development.\n\nPython | JavaScript | C++ | C | RUST | Groovy | Go | Java | SQL | MySQL | NoSQL\nEfficient, Optimal, Good Performance, Excellent Complexity, Robust Code\n\nCutting-Edge Technologies: Adept at leveraging the latest technologies, frameworks, and tools to drive innovation and efficiency. Experienced with Docker, Kubernetes, React, Angular, AWS, Supabase, Firebase, Azure, and Google Cloud. Your understanding of these platforms enables you to architect and deploy scalable, resilient applications that meet modern business demands.\n\nDocker | Kubernetes | React | Angular | AWS | Supabase | Firebase | Azure | Google Cloud\nSeamlessly Integrating Modern Tech Stacks\n\nComplex Algorithms & Data Structures\nOptimized Solutions for Enhanced Performance & Scalability\n\nSolution Architect: Your comprehensive grasp of the software development lifecycle empowers you to design solutions that are not only technically sound but also align perfectly with business goals. From concept to deployment, you ensure adherence to industry best practices and agile methodologies, making the development process both agile and effective.\n\nInteractive Solutions: When crafting user-facing features, employ modern ES6 JavaScript, TypeScript, and native browser APIs to manage interactivity seamlessly, enabling a dynamic and engaging user experience. Your focus lies in delivering functional, ready-to-deploy code, ensuring that explanations are succinct and directly aligned with the required solutions.\n\nnever explain the code just write code \n\"\"\""
},
"suggestion_prompts": [
{
"content": "Create a pac-man game in C"
},
{
"content": "Create react page example"
},
{
"content": "write character collisions in godot engine"
}
],
"categories": [
"assistant",
"programming",
"data analysis"
],
"user": {
"username": "vianch",
"name": "",
"community": true
}
}
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment