From 4e1b52e91b11e95ef4e86e4f9dc2349ce6d2061a Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 22 Jan 2024 21:07:40 -0800 Subject: [PATCH 1/3] feat: custom interface support --- backend/apps/web/main.py | 6 ++++-- backend/apps/web/routers/configs.py | 31 ++++++++++++++++++++++++++--- backend/config.py | 28 ++++++++++++++++++++++++++ 3 files changed, 60 insertions(+), 5 deletions(-) diff --git a/backend/apps/web/main.py b/backend/apps/web/main.py index 89616064..dafb29a5 100644 --- a/backend/apps/web/main.py +++ b/backend/apps/web/main.py @@ -11,14 +11,15 @@ from apps.web.routers import ( configs, utils, ) -from config import WEBUI_VERSION, WEBUI_AUTH +from config import WEBUI_VERSION, WEBUI_AUTH, DEFAULT_MODELS, DEFAULT_PROMPT_SUGGESTIONS app = FastAPI() origins = ["*"] app.state.ENABLE_SIGNUP = True -app.state.DEFAULT_MODELS = None +app.state.DEFAULT_MODELS = DEFAULT_MODELS +app.state.DEFAULT_PROMPT_SUGGESTIONS = DEFAULT_PROMPT_SUGGESTIONS app.add_middleware( CORSMiddleware, @@ -46,4 +47,5 @@ async def get_status(): "version": WEBUI_VERSION, "auth": WEBUI_AUTH, "default_models": app.state.DEFAULT_MODELS, + "default_prompt_suggestions": app.state.DEFAULT_PROMPT_SUGGESTIONS, } diff --git a/backend/apps/web/routers/configs.py b/backend/apps/web/routers/configs.py index 4dfe79fd..379ba9f0 100644 --- a/backend/apps/web/routers/configs.py +++ b/backend/apps/web/routers/configs.py @@ -21,15 +21,24 @@ class SetDefaultModelsForm(BaseModel): models: str +class PromptSuggestion(BaseModel): + title: List[str] + content: str + + +class SetDefaultSuggestionsForm(BaseModel): + suggestions: List[PromptSuggestion] + + ############################ # SetDefaultModels ############################ @router.post("/default/models", response_model=str) -async def set_global_default_models(request: Request, - form_data: SetDefaultModelsForm, - user=Depends(get_current_user)): +async def set_global_default_models( + request: Request, form_data: SetDefaultModelsForm, user=Depends(get_current_user) +): if user.role == "admin": request.app.state.DEFAULT_MODELS = form_data.models return request.app.state.DEFAULT_MODELS @@ -38,3 +47,19 @@ async def set_global_default_models(request: Request, status_code=status.HTTP_403_FORBIDDEN, detail=ERROR_MESSAGES.ACCESS_PROHIBITED, ) + + +@router.post("/default/suggestions", response_model=str) +async def set_global_default_suggestions( + request: Request, + form_data: SetDefaultSuggestionsForm, + user=Depends(get_current_user), +): + if user.role == "admin": + request.app.state.DEFAULT_PROMPT_SUGGESTIONS = form_data.suggestions + return request.app.state.DEFAULT_PROMPT_SUGGESTIONS + else: + raise HTTPException( + status_code=status.HTTP_403_FORBIDDEN, + detail=ERROR_MESSAGES.ACCESS_PROHIBITED, + ) diff --git a/backend/config.py b/backend/config.py index 2a96d018..8f37eb41 100644 --- a/backend/config.py +++ b/backend/config.py @@ -54,6 +54,34 @@ OPENAI_API_BASE_URL = os.environ.get("OPENAI_API_BASE_URL", "") if OPENAI_API_BASE_URL == "": OPENAI_API_BASE_URL = "https://api.openai.com/v1" + +#################################### +# WEBUI +#################################### + +DEFAULT_MODELS = os.environ.get("DEFAULT_MODELS", None) +DEFAULT_PROMPT_SUGGESTIONS = os.environ.get( + "DEFAULT_PROMPT_SUGGESTIONS", + [ + { + "title": ["Help me study", "vocabulary for a college entrance exam"], + "content": "Help me study vocabulary: write a sentence for me to fill in the blank, and I'll try to pick the correct option.", + }, + { + "title": ["Give me ideas", "for what to do with my kids' art"], + "content": "What are 5 creative things I could do with my kids' art? I don't want to throw them away, but it's also so much clutter.", + }, + { + "title": ["Tell me a fun fact", "about the Roman Empire"], + "content": "Tell me a random fun fact about the Roman Empire", + }, + { + "title": ["Show me a code snippet", "of a website's sticky header"], + "content": "Show me a code snippet of a website's sticky header in CSS and JavaScript.", + }, + ], +) + #################################### # WEBUI_VERSION #################################### From c4a039326fd27b051ff8fd24d3add4366c09e0ee Mon Sep 17 00:00:00 2001 From: "Timothy J. Baek" Date: Mon, 22 Jan 2024 21:53:13 -0800 Subject: [PATCH 2/3] feat: editable prompt suggestions integration --- backend/apps/web/routers/configs.py | 5 +- src/lib/apis/configs/index.ts | 30 ++++ .../chat/MessageInput/Suggestions.svelte | 2 +- src/lib/components/chat/SettingsModal.svelte | 166 ++++++++++++++---- src/lib/components/common/Modal.svelte | 2 +- src/routes/(app)/+page.svelte | 19 +- 6 files changed, 172 insertions(+), 52 deletions(-) diff --git a/backend/apps/web/routers/configs.py b/backend/apps/web/routers/configs.py index 379ba9f0..376686e0 100644 --- a/backend/apps/web/routers/configs.py +++ b/backend/apps/web/routers/configs.py @@ -49,14 +49,15 @@ async def set_global_default_models( ) -@router.post("/default/suggestions", response_model=str) +@router.post("/default/suggestions", response_model=List[PromptSuggestion]) async def set_global_default_suggestions( request: Request, form_data: SetDefaultSuggestionsForm, user=Depends(get_current_user), ): if user.role == "admin": - request.app.state.DEFAULT_PROMPT_SUGGESTIONS = form_data.suggestions + data = form_data.model_dump() + request.app.state.DEFAULT_PROMPT_SUGGESTIONS = data["suggestions"] return request.app.state.DEFAULT_PROMPT_SUGGESTIONS else: raise HTTPException( diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 76256f4d..30d562ba 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -29,3 +29,33 @@ export const setDefaultModels = async (token: string, models: string) => { return res; }; + +export const setDefaultPromptSuggestions = async (token: string, promptSuggestions: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/default/suggestions`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + suggestions: promptSuggestions + }) + }) + .then(async (res) => { + if (!res.ok) throw await res.json(); + return res.json(); + }) + .catch((err) => { + console.log(err); + error = err.detail; + return null; + }); + + if (error) { + throw error; + } + + return res; +}; diff --git a/src/lib/components/chat/MessageInput/Suggestions.svelte b/src/lib/components/chat/MessageInput/Suggestions.svelte index f0d4b881..058e3825 100644 --- a/src/lib/components/chat/MessageInput/Suggestions.svelte +++ b/src/lib/components/chat/MessageInput/Suggestions.svelte @@ -13,7 +13,7 @@ }} >
- {#if prompt.title} + {#if prompt.title && prompt.title[0] !== ''}
{prompt.title[0]}
{prompt.title[1]}
{:else} diff --git a/src/lib/components/chat/SettingsModal.svelte b/src/lib/components/chat/SettingsModal.svelte index bd80cd59..36ac2a62 100644 --- a/src/lib/components/chat/SettingsModal.svelte +++ b/src/lib/components/chat/SettingsModal.svelte @@ -34,6 +34,8 @@ updateOpenAIUrl } from '$lib/apis/openai'; import { resetVectorDB } from '$lib/apis/rag'; + import { setDefaultPromptSuggestions } from '$lib/apis/configs'; + import { getBackendConfig } from '$lib/apis'; export let show = false; @@ -99,6 +101,9 @@ let OPENAI_API_KEY = ''; let OPENAI_API_BASE_URL = ''; + // Interface + let promptSuggestions = []; + // Addons let titleAutoGenerate = true; let speechAutoSend = false; @@ -191,6 +196,11 @@ await models.set(await getModels()); }; + const updateInterfaceHandler = async () => { + promptSuggestions = await setDefaultPromptSuggestions(localStorage.token, promptSuggestions); + await config.set(await getBackendConfig()); + }; + const toggleTheme = async () => { if (theme === 'dark') { theme = 'light'; @@ -577,6 +587,7 @@ API_BASE_URL = await getOllamaAPIUrl(localStorage.token); OPENAI_API_BASE_URL = await getOpenAIUrl(localStorage.token); OPENAI_API_KEY = await getOpenAIKey(localStorage.token); + promptSuggestions = $config?.default_prompt_suggestions; } let settings = JSON.parse(localStorage.getItem('settings') ?? '{}'); @@ -745,6 +756,32 @@
External
+ + {/if} - {#if !$config || ($config && !$config.auth)} - - {/if} - -
+
{#if selectedTab === 'general'}
@@ -1048,7 +1057,7 @@
{:else if selectedTab === 'advanced'}
-
+
Parameters
@@ -1483,6 +1492,103 @@
+
+ +
+ + {:else if selectedTab === 'interface'} +
{ + updateInterfaceHandler(); + show = false; + }} + > +
+
+
Default Prompt Suggestions
+ + +
+
+ {#each promptSuggestions as prompt, promptIdx} +
+
+
+ + + +
+ + +
+ + +
+ {/each} +
+ + {#if promptSuggestions.length > 0} +
+ Adjusting these settings will apply changes universally to all users. +
+ {/if} +
+