diff --git a/backend/open_webui/config.py b/backend/open_webui/config.py index e5b0cfcc5..3cc2d49bc 100644 --- a/backend/open_webui/config.py +++ b/backend/open_webui/config.py @@ -683,6 +683,17 @@ Path(UPLOAD_DIR).mkdir(parents=True, exist_ok=True) CACHE_DIR = f"{DATA_DIR}/cache" Path(CACHE_DIR).mkdir(parents=True, exist_ok=True) + +#################################### +# DIRECT API +#################################### + +ENABLE_DIRECT_API = PersistentConfig( + "ENABLE_DIRECT_API", + "direct.enable", + os.environ.get("ENABLE_DIRECT_API", "True").lower() == "true", +) + #################################### # OLLAMA_BASE_URL #################################### diff --git a/backend/open_webui/main.py b/backend/open_webui/main.py index f8f6bf95c..72a314c01 100644 --- a/backend/open_webui/main.py +++ b/backend/open_webui/main.py @@ -97,6 +97,8 @@ from open_webui.config import ( OPENAI_API_BASE_URLS, OPENAI_API_KEYS, OPENAI_API_CONFIGS, + # Direct API + ENABLE_DIRECT_API, # Code Interpreter ENABLE_CODE_INTERPRETER, CODE_INTERPRETER_ENGINE, @@ -403,6 +405,14 @@ app.state.config.OPENAI_API_CONFIGS = OPENAI_API_CONFIGS app.state.OPENAI_MODELS = {} +######################################## +# +# DIRECT API +# +######################################## + +app.state.config.ENABLE_DIRECT_API = ENABLE_DIRECT_API + ######################################## # # WEBUI @@ -1046,6 +1056,7 @@ async def get_app_config(request: Request): "enable_websocket": ENABLE_WEBSOCKET_SUPPORT, **( { + "enable_direct_api": app.state.config.ENABLE_DIRECT_API, "enable_channels": app.state.config.ENABLE_CHANNELS, "enable_web_search": app.state.config.ENABLE_RAG_WEB_SEARCH, "enable_code_interpreter": app.state.config.ENABLE_CODE_INTERPRETER, diff --git a/backend/open_webui/routers/configs.py b/backend/open_webui/routers/configs.py index 2700a941e..9156a99e6 100644 --- a/backend/open_webui/routers/configs.py +++ b/backend/open_webui/routers/configs.py @@ -36,6 +36,32 @@ async def export_config(user=Depends(get_admin_user)): return get_config() +############################ +# Direct API Config +############################ + + +class DirectAPIConfigForm(BaseModel): + ENABLE_DIRECT_API: bool + + +@router.get("/direct_api", response_model=DirectAPIConfigForm) +async def get_direct_api_config(request: Request, user=Depends(get_admin_user)): + return { + "ENABLE_DIRECT_API": request.app.state.config.ENABLE_DIRECT_API, + } + + +@router.post("/direct_api", response_model=DirectAPIConfigForm) +async def set_direct_api_config( + request: Request, form_data: DirectAPIConfigForm, user=Depends(get_admin_user) +): + request.app.state.config.ENABLE_DIRECT_API = form_data.ENABLE_DIRECT_API + return { + "ENABLE_DIRECT_API": request.app.state.config.ENABLE_DIRECT_API, + } + + ############################ # CodeInterpreterConfig ############################ diff --git a/src/lib/apis/configs/index.ts b/src/lib/apis/configs/index.ts index 999842b26..22620c0c3 100644 --- a/src/lib/apis/configs/index.ts +++ b/src/lib/apis/configs/index.ts @@ -58,6 +58,63 @@ export const exportConfig = async (token: string) => { return res; }; +export const getDirectApiConfig = async (token: string) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_api`, { + method: 'GET', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + } + }) + .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; +}; + +export const setDirectApiConfig = async (token: string, config: object) => { + let error = null; + + const res = await fetch(`${WEBUI_API_BASE_URL}/configs/direct_api`, { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${token}` + }, + body: JSON.stringify({ + ...config + }) + }) + .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; +}; + export const getCodeInterpreterConfig = async (token: string) => { let error = null; diff --git a/src/lib/components/admin/Settings/Connections.svelte b/src/lib/components/admin/Settings/Connections.svelte index 2d7c8675b..b2f2dfc8a 100644 --- a/src/lib/components/admin/Settings/Connections.svelte +++ b/src/lib/components/admin/Settings/Connections.svelte @@ -7,6 +7,7 @@ import { getOllamaConfig, updateOllamaConfig } from '$lib/apis/ollama'; import { getOpenAIConfig, updateOpenAIConfig, getOpenAIModels } from '$lib/apis/openai'; import { getModels as _getModels } from '$lib/apis'; + import { getDirectApiConfig, setDirectApiConfig } from '$lib/apis/configs'; import { models, user } from '$lib/stores'; @@ -37,6 +38,8 @@ let ENABLE_OPENAI_API: null | boolean = null; let ENABLE_OLLAMA_API: null | boolean = null; + let directApiConfig = null; + let pipelineUrls = {}; let showAddOpenAIConnectionModal = false; let showAddOllamaConnectionModal = false; @@ -127,6 +130,9 @@ })(), (async () => { openaiConfig = await getOpenAIConfig(localStorage.token); + })(), + (async () => { + directApiConfig = await getDirectApiConfig(localStorage.token); })() ]); @@ -170,6 +176,15 @@ } } }); + + const submitHandler = async () => { + updateOpenAIHandler(); + updateOllamaHandler(); + + setDirectApiConfig(localStorage.token, directApiConfig); + + dispatch('save'); + }; -
{ - updateOpenAIHandler(); - updateOllamaHandler(); - - dispatch('save'); - }} -> +
- {#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null} + {#if ENABLE_OPENAI_API !== null && ENABLE_OLLAMA_API !== null && directApiConfig !== null}
@@ -334,6 +341,31 @@
{/if}
+ +
+ +
+
+
{$i18n.t('Direct API')}
+ +
+
+ { + updateOpenAIHandler(); + }} + /> +
+
+
+ +
+
+ {$i18n.t('Direct API allows users to use the models directly from their browser.')} +
+
+
{:else}