Merge pull request #880 from open-webui/custom-name

feat: sponsor custom name support
This commit is contained in:
Timothy Jaeryang Baek 2024-02-23 20:16:47 -05:00 committed by GitHub
commit 9e287262f0
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 94 additions and 44 deletions

View file

@ -1,13 +1,17 @@
import os import os
import chromadb import chromadb
from chromadb import Settings from chromadb import Settings
from secrets import token_bytes
from base64 import b64encode from base64 import b64encode
from constants import ERROR_MESSAGES from bs4 import BeautifulSoup
from pathlib import Path from pathlib import Path
import json import json
import markdown import markdown
from bs4 import BeautifulSoup import requests
import shutil
from secrets import token_bytes
from constants import ERROR_MESSAGES
try: try:
@ -17,6 +21,8 @@ try:
except ImportError: except ImportError:
print("dotenv not installed, skipping...") print("dotenv not installed, skipping...")
WEBUI_NAME = "Open WebUI"
#################################### ####################################
# ENV (dev,test,prod) # ENV (dev,test,prod)
@ -24,7 +30,6 @@ except ImportError:
ENV = os.environ.get("ENV", "dev") ENV = os.environ.get("ENV", "dev")
try: try:
with open(f"../package.json", "r") as f: with open(f"../package.json", "r") as f:
PACKAGE_DATA = json.load(f) PACKAGE_DATA = json.load(f)
@ -94,6 +99,32 @@ for version in soup.find_all("h2"):
CHANGELOG = changelog_json CHANGELOG = changelog_json
####################################
# CUSTOM_NAME
####################################
CUSTOM_NAME = os.environ.get("CUSTOM_NAME", "")
if CUSTOM_NAME:
r = requests.get(f"https://api.openwebui.com/api/v1/custom/{CUSTOM_NAME}")
data = r.json()
if "logo" in data:
url = (
f"https://api.openwebui.com{data['logo']}"
if data["logo"][0] == "/"
else data["logo"]
)
r = requests.get(url, stream=True)
if r.status_code == 200:
with open("./static/favicon.png", "wb") as f:
r.raw.decode_content = True
shutil.copyfileobj(r.raw, f)
WEBUI_NAME = data["name"]
#################################### ####################################
# DATA/FRONTEND BUILD DIR # DATA/FRONTEND BUILD DIR
#################################### ####################################

View file

@ -20,7 +20,7 @@ from apps.rag.main import app as rag_app
from apps.web.main import app as webui_app from apps.web.main import app as webui_app
from config import ENV, VERSION, CHANGELOG, FRONTEND_BUILD_DIR from config import WEBUI_NAME, ENV, VERSION, CHANGELOG, FRONTEND_BUILD_DIR
class SPAStaticFiles(StaticFiles): class SPAStaticFiles(StaticFiles):
@ -72,6 +72,7 @@ async def get_app_config():
return { return {
"status": True, "status": True,
"name": WEBUI_NAME,
"version": VERSION, "version": VERSION,
"images": images_app.state.ENABLED, "images": images_app.state.ENABLED,
"default_models": webui_app.state.DEFAULT_MODELS, "default_models": webui_app.state.DEFAULT_MODELS,
@ -84,6 +85,9 @@ async def get_app_changelog():
return CHANGELOG return CHANGELOG
app.mount("/static", StaticFiles(directory="static"), name="static")
app.mount( app.mount(
"/", "/",
SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True), SPAStaticFiles(directory=FRONTEND_BUILD_DIR, html=True),

BIN
backend/static/favicon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6 KiB

View file

@ -2,9 +2,9 @@
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import { Confetti } from 'svelte-confetti'; import { Confetti } from 'svelte-confetti';
import { config } from '$lib/stores'; import { WEBUI_NAME, config } from '$lib/stores';
import { WEBUI_NAME, WEB_UI_VERSION } from '$lib/constants'; import { WEBUI_VERSION } from '$lib/constants';
import { getChangelog } from '$lib/apis'; import { getChangelog } from '$lib/apis';
import Modal from './common/Modal.svelte'; import Modal from './common/Modal.svelte';
@ -23,7 +23,7 @@
<div class="px-5 py-4 dark:text-gray-300"> <div class="px-5 py-4 dark:text-gray-300">
<div class="flex justify-between items-start"> <div class="flex justify-between items-start">
<div class="text-xl font-bold"> <div class="text-xl font-bold">
Whats New in {WEBUI_NAME} Whats New in {$WEBUI_NAME}
<Confetti x={[-1, -0.25]} y={[0, 0.5]} /> <Confetti x={[-1, -0.25]} y={[0, 0.5]} />
</div> </div>
<button <button
@ -48,7 +48,7 @@
<div class="text-sm dark:text-gray-200">Release Notes</div> <div class="text-sm dark:text-gray-200">Release Notes</div>
<div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" /> <div class="flex self-center w-[1px] h-6 mx-2.5 bg-gray-200 dark:bg-gray-700" />
<div class="text-sm dark:text-gray-200"> <div class="text-sm dark:text-gray-200">
v{WEB_UI_VERSION} v{WEBUI_VERSION}
</div> </div>
</div> </div>
</div> </div>

View file

@ -1,4 +1,5 @@
<script lang="ts"> <script lang="ts">
import { WEBUI_BASE_URL } from '$lib/constants';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
export let models = []; export let models = [];
@ -27,14 +28,16 @@
> >
{#if model in modelfiles} {#if model in modelfiles}
<img <img
src={modelfiles[model]?.imageUrl ?? './favicon.png'} src={modelfiles[model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`}
alt="modelfile" alt="modelfile"
class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none" class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none"
draggable="false" draggable="false"
/> />
{:else} {:else}
<img <img
src={models.length === 1 ? '/favicon.png' : '/favicon.png'} src={models.length === 1
? `${WEBUI_BASE_URL}/static/favicon.png`
: `${WEBUI_BASE_URL}/static/favicon.png`}
class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none" class=" w-14 rounded-full border-[1px] border-gray-200 dark:border-none"
alt="logo" alt="logo"
draggable="false" draggable="false"

View file

@ -298,7 +298,9 @@
{#key message.id} {#key message.id}
<div class=" flex w-full message-{message.id}"> <div class=" flex w-full message-{message.id}">
<ProfileImage src={modelfiles[message.model]?.imageUrl ?? '/favicon.png'} /> <ProfileImage
src={modelfiles[message.model]?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`}
/>
<div class="w-full overflow-hidden"> <div class="w-full overflow-hidden">
<Name> <Name>

View file

@ -1,7 +1,7 @@
<script lang="ts"> <script lang="ts">
import { getOllamaVersion } from '$lib/apis/ollama'; import { getOllamaVersion } from '$lib/apis/ollama';
import { WEBUI_NAME, WEB_UI_VERSION } from '$lib/constants'; import { WEBUI_VERSION } from '$lib/constants';
import { config, showChangelog } from '$lib/stores'; import { WEBUI_NAME, config, showChangelog } from '$lib/stores';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let ollamaVersion = ''; let ollamaVersion = '';
@ -17,13 +17,13 @@
<div> <div>
<div class=" mb-2.5 text-sm font-medium flex space-x-2 items-center"> <div class=" mb-2.5 text-sm font-medium flex space-x-2 items-center">
<div> <div>
{WEBUI_NAME} Version {$WEBUI_NAME} Version
</div> </div>
</div> </div>
<div class="flex w-full"> <div class="flex w-full">
<div class="flex-1 text-xs text-gray-700 dark:text-gray-200 flex space-x-1.5 items-center"> <div class="flex-1 text-xs text-gray-700 dark:text-gray-200 flex space-x-1.5 items-center">
<div> <div>
v{WEB_UI_VERSION} v{WEBUI_VERSION}
</div> </div>
<button <button

View file

@ -3,8 +3,8 @@
import toast from 'svelte-french-toast'; import toast from 'svelte-french-toast';
import { createModel, deleteModel, pullModel } from '$lib/apis/ollama'; import { createModel, deleteModel, pullModel } from '$lib/apis/ollama';
import { WEBUI_API_BASE_URL, WEBUI_NAME } from '$lib/constants'; import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { models, user } from '$lib/stores'; import { WEBUI_NAME, models, user } from '$lib/stores';
import { splitStream } from '$lib/utils'; import { splitStream } from '$lib/utils';
export let getModels: Function; export let getModels: Function;
@ -59,9 +59,9 @@
} else { } else {
toast.success(`Model '${modelName}' has been successfully downloaded.`); toast.success(`Model '${modelName}' has been successfully downloaded.`);
const notification = new Notification(WEBUI_NAME, { const notification = new Notification($WEBUI_NAME, {
body: `Model '${modelName}' has been successfully downloaded.`, body: `Model '${modelName}' has been successfully downloaded.`,
icon: '/favicon.png' icon: `${WEBUI_BASE_URL}/static/favicon.png`
}); });
models.set(await getModels()); models.set(await getModels());

View file

@ -4,14 +4,13 @@
const { saveAs } = fileSaver; const { saveAs } = fileSaver;
import { getChatById } from '$lib/apis/chats'; import { getChatById } from '$lib/apis/chats';
import { chatId, modelfiles, settings } from '$lib/stores'; import { WEBUI_NAME, chatId, modelfiles, settings } from '$lib/stores';
import ShareChatModal from '../chat/ShareChatModal.svelte'; import ShareChatModal from '../chat/ShareChatModal.svelte';
import TagInput from '../common/Tags/TagInput.svelte'; import TagInput from '../common/Tags/TagInput.svelte';
import Tags from '../common/Tags.svelte'; import Tags from '../common/Tags.svelte';
import { WEBUI_NAME } from '$lib/constants';
export let initNewChat: Function; export let initNewChat: Function;
export let title: string = WEBUI_NAME; export let title: string = $WEBUI_NAME;
export let shareEnabled: boolean = false; export let shareEnabled: boolean = false;
export let tags = []; export let tags = [];
@ -102,7 +101,7 @@
</div> </div>
<div class=" flex-1 self-center font-medium line-clamp-1"> <div class=" flex-1 self-center font-medium line-clamp-1">
<div> <div>
{title != '' ? title : WEBUI_NAME} {title != '' ? title : $WEBUI_NAME}
</div> </div>
</div> </div>

View file

@ -17,6 +17,7 @@
} from '$lib/apis/chats'; } from '$lib/apis/chats';
import toast from 'svelte-french-toast'; import toast from 'svelte-french-toast';
import { slide } from 'svelte/transition'; import { slide } from 'svelte/transition';
import { WEBUI_BASE_URL } from '$lib/constants';
let show = false; let show = false;
let navElement; let navElement;
@ -114,7 +115,11 @@
> >
<div class="flex self-center"> <div class="flex self-center">
<div class="self-center mr-1.5"> <div class="self-center mr-1.5">
<img src="/favicon.png" class=" w-7 -translate-x-1.5 rounded-full" alt="logo" /> <img
src="{WEBUI_BASE_URL}/static/favicon.png"
class=" w-7 -translate-x-1.5 rounded-full"
alt="logo"
/>
</div> </div>
<div class=" self-center font-medium text-sm">New Chat</div> <div class=" self-center font-medium text-sm">New Chat</div>

View file

@ -1,7 +1,7 @@
import { dev } from '$app/environment'; import { dev } from '$app/environment';
// import { version } from '../../package.json'; // import { version } from '../../package.json';
export const WEBUI_NAME = 'Open WebUI'; export const APP_NAME = 'Open WebUI';
export const WEBUI_BASE_URL = dev ? `http://${location.hostname}:8080` : ``; export const WEBUI_BASE_URL = dev ? `http://${location.hostname}:8080` : ``;
export const WEBUI_API_BASE_URL = `${WEBUI_BASE_URL}/api/v1`; export const WEBUI_API_BASE_URL = `${WEBUI_BASE_URL}/api/v1`;
@ -11,7 +11,7 @@ export const AUDIO_API_BASE_URL = `${WEBUI_BASE_URL}/audio/api/v1`;
export const IMAGES_API_BASE_URL = `${WEBUI_BASE_URL}/images/api/v1`; export const IMAGES_API_BASE_URL = `${WEBUI_BASE_URL}/images/api/v1`;
export const RAG_API_BASE_URL = `${WEBUI_BASE_URL}/rag/api/v1`; export const RAG_API_BASE_URL = `${WEBUI_BASE_URL}/rag/api/v1`;
export const WEB_UI_VERSION = APP_VERSION; export const WEBUI_VERSION = APP_VERSION;
export const REQUIRED_OLLAMA_VERSION = '0.1.16'; export const REQUIRED_OLLAMA_VERSION = '0.1.16';
export const SUPPORTED_FILE_TYPE = [ export const SUPPORTED_FILE_TYPE = [

View file

@ -1,6 +1,8 @@
import { APP_NAME } from '$lib/constants';
import { writable } from 'svelte/store'; import { writable } from 'svelte/store';
// Backend // Backend
export const WEBUI_NAME = writable(APP_NAME);
export const config = writable(undefined); export const config = writable(undefined);
export const user = writable(undefined); export const user = writable(undefined);

View file

@ -36,6 +36,7 @@
import ModelSelector from '$lib/components/chat/ModelSelector.svelte'; import ModelSelector from '$lib/components/chat/ModelSelector.svelte';
import Navbar from '$lib/components/layout/Navbar.svelte'; import Navbar from '$lib/components/layout/Navbar.svelte';
import { RAGTemplate } from '$lib/utils/rag'; import { RAGTemplate } from '$lib/utils/rag';
import { WEBUI_BASE_URL } from '$lib/constants';
let stopResponseFlag = false; let stopResponseFlag = false;
let autoScroll = true; let autoScroll = true;
@ -334,7 +335,7 @@
content: $settings.system content: $settings.system
} }
: undefined, : undefined,
...messages.filter(message => !message.deleted) ...messages.filter((message) => !message.deleted)
] ]
.filter((message) => message) .filter((message) => message)
.map((message, idx, arr) => ({ .map((message, idx, arr) => ({
@ -452,7 +453,7 @@
: `${model}`, : `${model}`,
{ {
body: responseMessage.content, body: responseMessage.content,
icon: selectedModelfile?.imageUrl ?? '/favicon.png' icon: selectedModelfile?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`
} }
); );
} }
@ -540,7 +541,7 @@
content: $settings.system content: $settings.system
} }
: undefined, : undefined,
...messages.filter(message => !message.deleted) ...messages.filter((message) => !message.deleted)
] ]
.filter((message) => message) .filter((message) => message)
.map((message, idx, arr) => ({ .map((message, idx, arr) => ({
@ -622,7 +623,7 @@
if ($settings.notificationEnabled && !document.hasFocus()) { if ($settings.notificationEnabled && !document.hasFocus()) {
const notification = new Notification(`OpenAI ${model}`, { const notification = new Notification(`OpenAI ${model}`, {
body: responseMessage.content, body: responseMessage.content,
icon: '/favicon.png' icon: `${WEBUI_BASE_URL}/static/favicon.png`
}); });
} }

View file

@ -37,6 +37,7 @@
import ModelSelector from '$lib/components/chat/ModelSelector.svelte'; import ModelSelector from '$lib/components/chat/ModelSelector.svelte';
import Navbar from '$lib/components/layout/Navbar.svelte'; import Navbar from '$lib/components/layout/Navbar.svelte';
import { RAGTemplate } from '$lib/utils/rag'; import { RAGTemplate } from '$lib/utils/rag';
import { WEBUI_BASE_URL } from '$lib/constants';
let loaded = false; let loaded = false;
@ -466,7 +467,7 @@
: `${model}`, : `${model}`,
{ {
body: responseMessage.content, body: responseMessage.content,
icon: selectedModelfile?.imageUrl ?? '/favicon.png' icon: selectedModelfile?.imageUrl ?? `${WEBUI_BASE_URL}/static/favicon.png`
} }
); );
} }
@ -637,7 +638,7 @@
if ($settings.notificationEnabled && !document.hasFocus()) { if ($settings.notificationEnabled && !document.hasFocus()) {
const notification = new Notification(`OpenAI ${model}`, { const notification = new Notification(`OpenAI ${model}`, {
body: responseMessage.content, body: responseMessage.content,
icon: '/favicon.png' icon: `${WEBUI_BASE_URL}/static/favicon.png`
}); });
} }

View file

@ -1,6 +1,6 @@
<script> <script>
import { onMount, tick } from 'svelte'; import { onMount, tick } from 'svelte';
import { config, user, theme } from '$lib/stores'; import { config, user, theme, WEBUI_NAME } from '$lib/stores';
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import toast, { Toaster } from 'svelte-french-toast'; import toast, { Toaster } from 'svelte-french-toast';
@ -10,7 +10,7 @@
import '../app.css'; import '../app.css';
import '../tailwind.css'; import '../tailwind.css';
import 'tippy.js/dist/tippy.css'; import 'tippy.js/dist/tippy.css';
import { WEBUI_NAME } from '$lib/constants'; import { WEBUI_BASE_URL } from '$lib/constants';
let loaded = false; let loaded = false;
@ -22,6 +22,8 @@
if (backendConfig) { if (backendConfig) {
// Save Backend Status to Store // Save Backend Status to Store
await config.set(backendConfig); await config.set(backendConfig);
await WEBUI_NAME.set(backendConfig.name);
console.log(backendConfig); console.log(backendConfig);
if ($config) { if ($config) {
@ -55,7 +57,8 @@
</script> </script>
<svelte:head> <svelte:head>
<title>{WEBUI_NAME}</title> <title>{$WEBUI_NAME}</title>
<link rel="icon" href="{WEBUI_BASE_URL}/static/favicon.png" />
<link rel="stylesheet" type="text/css" href="/themes/rosepine.css" /> <link rel="stylesheet" type="text/css" href="/themes/rosepine.css" />
<link rel="stylesheet" type="text/css" href="/themes/rosepine-dawn.css" /> <link rel="stylesheet" type="text/css" href="/themes/rosepine-dawn.css" />

View file

@ -1,8 +1,8 @@
<script> <script>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { userSignIn, userSignUp } from '$lib/apis/auths'; import { userSignIn, userSignUp } from '$lib/apis/auths';
import { WEBUI_API_BASE_URL, WEBUI_NAME } from '$lib/constants'; import { WEBUI_API_BASE_URL, WEBUI_BASE_URL } from '$lib/constants';
import { config, user } from '$lib/stores'; import { WEBUI_NAME, config, user } from '$lib/stores';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
import toast from 'svelte-french-toast'; import toast from 'svelte-french-toast';
@ -61,7 +61,7 @@
<div class="fixed m-10 z-50"> <div class="fixed m-10 z-50">
<div class="flex space-x-2"> <div class="flex space-x-2">
<div class=" self-center"> <div class=" self-center">
<img src="/favicon.png" class=" w-8 rounded-full" alt="logo" /> <img src="{WEBUI_BASE_URL}/static/favicon.png" class=" w-8 rounded-full" alt="logo" />
</div> </div>
</div> </div>
</div> </div>
@ -90,12 +90,12 @@
}} }}
> >
<div class=" text-xl md:text-2xl font-bold"> <div class=" text-xl md:text-2xl font-bold">
{mode === 'signin' ? 'Sign in' : 'Sign up'} to {WEBUI_NAME} {mode === 'signin' ? 'Sign in' : 'Sign up'} to {$WEBUI_NAME}
</div> </div>
{#if mode === 'signup'} {#if mode === 'signup'}
<div class=" mt-1 text-xs font-medium text-gray-500"> <div class=" mt-1 text-xs font-medium text-gray-500">
{WEBUI_NAME} does not make any external connections, and your data stays securely on {$WEBUI_NAME} does not make any external connections, and your data stays securely on
your locally hosted server. your locally hosted server.
</div> </div>
{/if} {/if}

View file

@ -1,7 +1,6 @@
<script> <script>
import { goto } from '$app/navigation'; import { goto } from '$app/navigation';
import { WEBUI_NAME } from '$lib/constants'; import { WEBUI_NAME, config } from '$lib/stores';
import { config } from '$lib/stores';
import { onMount } from 'svelte'; import { onMount } from 'svelte';
let loaded = false; let loaded = false;
@ -20,7 +19,7 @@
<div class="absolute rounded-xl w-full h-full backdrop-blur flex justify-center"> <div class="absolute rounded-xl w-full h-full backdrop-blur flex justify-center">
<div class="m-auto pb-44 flex flex-col justify-center"> <div class="m-auto pb-44 flex flex-col justify-center">
<div class="max-w-md"> <div class="max-w-md">
<div class="text-center text-2xl font-medium z-50">{WEBUI_NAME} Backend Required</div> <div class="text-center text-2xl font-medium z-50">{$WEBUI_NAME} Backend Required</div>
<div class=" mt-4 text-center text-sm w-full"> <div class=" mt-4 text-center text-sm w-full">
Oops! You're using an unsupported method (frontend only). Please serve the WebUI from Oops! You're using an unsupported method (frontend only). Please serve the WebUI from