forked from open-webui/open-webui
Merge branch 'dev' into fix/data-dir-handling
This commit is contained in:
commit
2f23325c90
22 changed files with 1571 additions and 1555 deletions
32
.github/workflows/format-backend.yaml
vendored
32
.github/workflows/format-backend.yaml
vendored
|
@ -1,29 +1,39 @@
|
||||||
name: Python CI
|
name: Python CI
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ['main']
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: 'Format Backend'
|
name: 'Format Backend'
|
||||||
env:
|
|
||||||
PUBLIC_API_BASE_URL: ''
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
strategy:
|
strategy:
|
||||||
matrix:
|
matrix:
|
||||||
node-version:
|
python-version: [3.11]
|
||||||
- latest
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
- name: Use Python
|
|
||||||
uses: actions/setup-python@v4
|
- name: Set up Python
|
||||||
- name: Use Bun
|
uses: actions/setup-python@v2
|
||||||
uses: oven-sh/setup-bun@v1
|
with:
|
||||||
|
python-version: ${{ matrix.python-version }}
|
||||||
|
|
||||||
- name: Install dependencies
|
- name: Install dependencies
|
||||||
run: |
|
run: |
|
||||||
python -m pip install --upgrade pip
|
python -m pip install --upgrade pip
|
||||||
pip install yapf
|
pip install black
|
||||||
|
|
||||||
- name: Format backend
|
- name: Format backend
|
||||||
run: bun run format:backend
|
run: black . --exclude "/venv/"
|
||||||
|
|
||||||
- name: Check for changes after format
|
- name: Check for changes after format
|
||||||
run: git diff --exit-code
|
run: git diff --exit-code
|
||||||
|
|
43
.github/workflows/format-build-frontend.yaml
vendored
43
.github/workflows/format-build-frontend.yaml
vendored
|
@ -1,25 +1,36 @@
|
||||||
name: Bun CI
|
name: Frontend Build
|
||||||
|
|
||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches: ['main']
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
pull_request:
|
pull_request:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
- dev
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build:
|
build:
|
||||||
name: 'Format & Build Frontend'
|
name: 'Format & Build Frontend'
|
||||||
env:
|
|
||||||
PUBLIC_API_BASE_URL: ''
|
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- name: Checkout Repository
|
||||||
- name: Use Bun
|
uses: actions/checkout@v4
|
||||||
uses: oven-sh/setup-bun@v1
|
|
||||||
- run: bun --version
|
- name: Setup Node.js
|
||||||
- name: Install frontend dependencies
|
uses: actions/setup-node@v3
|
||||||
run: bun install
|
with:
|
||||||
- name: Format frontend
|
node-version: '20' # Or specify any other version you want to use
|
||||||
run: bun run format
|
|
||||||
- name: Check for changes after format
|
- name: Install Dependencies
|
||||||
|
run: npm install
|
||||||
|
|
||||||
|
- name: Format Frontend
|
||||||
|
run: npm run format
|
||||||
|
|
||||||
|
- name: Check for Changes After Format
|
||||||
run: git diff --exit-code
|
run: git diff --exit-code
|
||||||
- name: Build frontend
|
|
||||||
if: always()
|
- name: Build Frontend
|
||||||
run: bun run build
|
run: npm run build
|
||||||
|
|
|
@ -325,7 +325,7 @@ def save_url_image(url):
|
||||||
|
|
||||||
return image_id
|
return image_id
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error saving image: {e}")
|
log.exception(f"Error saving image: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
@ -397,7 +397,7 @@ def generate_image(
|
||||||
user.id,
|
user.id,
|
||||||
app.state.COMFYUI_BASE_URL,
|
app.state.COMFYUI_BASE_URL,
|
||||||
)
|
)
|
||||||
print(res)
|
log.debug(f"res: {res}")
|
||||||
|
|
||||||
images = []
|
images = []
|
||||||
|
|
||||||
|
@ -409,7 +409,7 @@ def generate_image(
|
||||||
with open(file_body_path, "w") as f:
|
with open(file_body_path, "w") as f:
|
||||||
json.dump(data.model_dump(exclude_none=True), f)
|
json.dump(data.model_dump(exclude_none=True), f)
|
||||||
|
|
||||||
print(images)
|
log.debug(f"images: {images}")
|
||||||
return images
|
return images
|
||||||
else:
|
else:
|
||||||
if form_data.model:
|
if form_data.model:
|
||||||
|
|
|
@ -4,6 +4,12 @@ import json
|
||||||
import urllib.request
|
import urllib.request
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import random
|
import random
|
||||||
|
import logging
|
||||||
|
|
||||||
|
from config import SRC_LOG_LEVELS
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
log.setLevel(SRC_LOG_LEVELS["COMFYUI"])
|
||||||
|
|
||||||
from pydantic import BaseModel
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
@ -121,7 +127,7 @@ COMFYUI_DEFAULT_PROMPT = """
|
||||||
|
|
||||||
|
|
||||||
def queue_prompt(prompt, client_id, base_url):
|
def queue_prompt(prompt, client_id, base_url):
|
||||||
print("queue_prompt")
|
log.info("queue_prompt")
|
||||||
p = {"prompt": prompt, "client_id": client_id}
|
p = {"prompt": prompt, "client_id": client_id}
|
||||||
data = json.dumps(p).encode("utf-8")
|
data = json.dumps(p).encode("utf-8")
|
||||||
req = urllib.request.Request(f"{base_url}/prompt", data=data)
|
req = urllib.request.Request(f"{base_url}/prompt", data=data)
|
||||||
|
@ -129,7 +135,7 @@ def queue_prompt(prompt, client_id, base_url):
|
||||||
|
|
||||||
|
|
||||||
def get_image(filename, subfolder, folder_type, base_url):
|
def get_image(filename, subfolder, folder_type, base_url):
|
||||||
print("get_image")
|
log.info("get_image")
|
||||||
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
||||||
url_values = urllib.parse.urlencode(data)
|
url_values = urllib.parse.urlencode(data)
|
||||||
with urllib.request.urlopen(f"{base_url}/view?{url_values}") as response:
|
with urllib.request.urlopen(f"{base_url}/view?{url_values}") as response:
|
||||||
|
@ -137,14 +143,14 @@ def get_image(filename, subfolder, folder_type, base_url):
|
||||||
|
|
||||||
|
|
||||||
def get_image_url(filename, subfolder, folder_type, base_url):
|
def get_image_url(filename, subfolder, folder_type, base_url):
|
||||||
print("get_image")
|
log.info("get_image")
|
||||||
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
data = {"filename": filename, "subfolder": subfolder, "type": folder_type}
|
||||||
url_values = urllib.parse.urlencode(data)
|
url_values = urllib.parse.urlencode(data)
|
||||||
return f"{base_url}/view?{url_values}"
|
return f"{base_url}/view?{url_values}"
|
||||||
|
|
||||||
|
|
||||||
def get_history(prompt_id, base_url):
|
def get_history(prompt_id, base_url):
|
||||||
print("get_history")
|
log.info("get_history")
|
||||||
with urllib.request.urlopen(f"{base_url}/history/{prompt_id}") as response:
|
with urllib.request.urlopen(f"{base_url}/history/{prompt_id}") as response:
|
||||||
return json.loads(response.read())
|
return json.loads(response.read())
|
||||||
|
|
||||||
|
@ -212,15 +218,15 @@ def comfyui_generate_image(
|
||||||
try:
|
try:
|
||||||
ws = websocket.WebSocket()
|
ws = websocket.WebSocket()
|
||||||
ws.connect(f"ws://{host}/ws?clientId={client_id}")
|
ws.connect(f"ws://{host}/ws?clientId={client_id}")
|
||||||
print("WebSocket connection established.")
|
log.info("WebSocket connection established.")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Failed to connect to WebSocket server: {e}")
|
log.exception(f"Failed to connect to WebSocket server: {e}")
|
||||||
return None
|
return None
|
||||||
|
|
||||||
try:
|
try:
|
||||||
images = get_images(ws, comfyui_prompt, client_id, base_url)
|
images = get_images(ws, comfyui_prompt, client_id, base_url)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Error while receiving images: {e}")
|
log.exception(f"Error while receiving images: {e}")
|
||||||
images = None
|
images = None
|
||||||
|
|
||||||
ws.close()
|
ws.close()
|
||||||
|
|
|
@ -272,7 +272,7 @@ async def pull_model(
|
||||||
if request_id in REQUEST_POOL:
|
if request_id in REQUEST_POOL:
|
||||||
yield chunk
|
yield chunk
|
||||||
else:
|
else:
|
||||||
print("User: canceled request")
|
log.warning("User: canceled request")
|
||||||
break
|
break
|
||||||
finally:
|
finally:
|
||||||
if hasattr(r, "close"):
|
if hasattr(r, "close"):
|
||||||
|
@ -670,7 +670,7 @@ async def generate_completion(
|
||||||
else:
|
else:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
status_code=400,
|
status_code=400,
|
||||||
detail="error_detail",
|
detail=ERROR_MESSAGES.MODEL_NOT_FOUND(form_data.model),
|
||||||
)
|
)
|
||||||
|
|
||||||
url = app.state.OLLAMA_BASE_URLS[url_idx]
|
url = app.state.OLLAMA_BASE_URLS[url_idx]
|
||||||
|
|
|
@ -333,7 +333,7 @@ def store_docs_in_vector_db(docs, collection_name, overwrite: bool = False) -> b
|
||||||
if overwrite:
|
if overwrite:
|
||||||
for collection in CHROMA_CLIENT.list_collections():
|
for collection in CHROMA_CLIENT.list_collections():
|
||||||
if collection_name == collection.name:
|
if collection_name == collection.name:
|
||||||
print(f"deleting existing collection {collection_name}")
|
log.info(f"deleting existing collection {collection_name}")
|
||||||
CHROMA_CLIENT.delete_collection(name=collection_name)
|
CHROMA_CLIENT.delete_collection(name=collection_name)
|
||||||
|
|
||||||
collection = CHROMA_CLIENT.create_collection(
|
collection = CHROMA_CLIENT.create_collection(
|
||||||
|
@ -346,7 +346,7 @@ def store_docs_in_vector_db(docs, collection_name, overwrite: bool = False) -> b
|
||||||
)
|
)
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
log.exception(e)
|
||||||
if e.__class__.__name__ == "UniqueConstraintError":
|
if e.__class__.__name__ == "UniqueConstraintError":
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
@ -575,7 +575,7 @@ def scan_docs_dir(user=Depends(get_admin_user)):
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
log.exception(e)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
|
|
@ -119,6 +119,7 @@ log.info(f"GLOBAL_LOG_LEVEL: {GLOBAL_LOG_LEVEL}")
|
||||||
|
|
||||||
log_sources = [
|
log_sources = [
|
||||||
"AUDIO",
|
"AUDIO",
|
||||||
|
"COMFYUI",
|
||||||
"CONFIG",
|
"CONFIG",
|
||||||
"DB",
|
"DB",
|
||||||
"IMAGES",
|
"IMAGES",
|
||||||
|
@ -128,6 +129,7 @@ log_sources = [
|
||||||
"OLLAMA",
|
"OLLAMA",
|
||||||
"OPENAI",
|
"OPENAI",
|
||||||
"RAG",
|
"RAG",
|
||||||
|
"WEBHOOK",
|
||||||
]
|
]
|
||||||
|
|
||||||
SRC_LOG_LEVELS = {}
|
SRC_LOG_LEVELS = {}
|
||||||
|
|
|
@ -4,31 +4,19 @@
|
||||||
"default_locale": "en-US",
|
"default_locale": "en-US",
|
||||||
"prompt_suggestions": [
|
"prompt_suggestions": [
|
||||||
{
|
{
|
||||||
"title": [
|
"title": ["Help me study", "vocabulary for a college entrance exam"],
|
||||||
"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."
|
"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": [
|
"title": ["Give me ideas", "for what to do with my kids' art"],
|
||||||
"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."
|
"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": [
|
"title": ["Tell me a fun fact", "about the Roman Empire"],
|
||||||
"Tell me a fun fact",
|
|
||||||
"about the Roman Empire"
|
|
||||||
],
|
|
||||||
"content": "Tell me a random fun fact about the Roman Empire"
|
"content": "Tell me a random fun fact about the Roman Empire"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"title": [
|
"title": ["Show me a code snippet", "of a website's sticky header"],
|
||||||
"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."
|
"content": "Show me a code snippet of a website's sticky header in CSS and JavaScript."
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,6 +1,11 @@
|
||||||
import json
|
import json
|
||||||
import requests
|
import requests
|
||||||
from config import VERSION, WEBUI_FAVICON_URL, WEBUI_NAME
|
import logging
|
||||||
|
|
||||||
|
from config import SRC_LOG_LEVELS, VERSION, WEBUI_FAVICON_URL, WEBUI_NAME
|
||||||
|
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
log.setLevel(SRC_LOG_LEVELS["WEBHOOK"])
|
||||||
|
|
||||||
|
|
||||||
def post_webhook(url: str, message: str, event_data: dict) -> bool:
|
def post_webhook(url: str, message: str, event_data: dict) -> bool:
|
||||||
|
@ -39,9 +44,11 @@ def post_webhook(url: str, message: str, event_data: dict) -> bool:
|
||||||
else:
|
else:
|
||||||
payload = {**event_data}
|
payload = {**event_data}
|
||||||
|
|
||||||
|
log.debug(f"payload: {payload}")
|
||||||
r = requests.post(url, json=payload)
|
r = requests.post(url, json=payload)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
log.debug(f"r.text: {r.text}")
|
||||||
return True
|
return True
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(e)
|
log.exception(e)
|
||||||
return False
|
return False
|
||||||
|
|
4
package-lock.json
generated
4
package-lock.json
generated
|
@ -1,12 +1,12 @@
|
||||||
{
|
{
|
||||||
"name": "open-webui",
|
"name": "open-webui",
|
||||||
"version": "0.1.114",
|
"version": "0.1.116",
|
||||||
"lockfileVersion": 3,
|
"lockfileVersion": 3,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "open-webui",
|
"name": "open-webui",
|
||||||
"version": "0.1.114",
|
"version": "0.1.116",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sveltejs/adapter-node": "^1.3.1",
|
"@sveltejs/adapter-node": "^1.3.1",
|
||||||
"async": "^3.2.5",
|
"async": "^3.2.5",
|
||||||
|
|
|
@ -13,7 +13,6 @@
|
||||||
"lint:types": "npm run check",
|
"lint:types": "npm run check",
|
||||||
"lint:backend": "pylint backend/",
|
"lint:backend": "pylint backend/",
|
||||||
"format": "prettier --plugin-search-dir --write '**/*.{js,ts,svelte,css,md,html,json}'",
|
"format": "prettier --plugin-search-dir --write '**/*.{js,ts,svelte,css,md,html,json}'",
|
||||||
"format:backend": "yapf --recursive backend -p -i",
|
|
||||||
"i18n:parse": "i18next --config i18next-parser.config.ts && prettier --write 'src/lib/i18n/**/*.{js,json}'"
|
"i18n:parse": "i18next --config i18next-parser.config.ts && prettier --write 'src/lib/i18n/**/*.{js,json}'"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
|
|
@ -360,4 +360,4 @@
|
||||||
"You": "Tu",
|
"You": "Tu",
|
||||||
"You're a helpful assistant.": "Sei un assistente utile.",
|
"You're a helpful assistant.": "Sei un assistente utile.",
|
||||||
"You're now logged in.": "Ora hai effettuato l'accesso."
|
"You're now logged in.": "Ora hai effettuato l'accesso."
|
||||||
}
|
}
|
||||||
|
|
|
@ -360,4 +360,4 @@
|
||||||
"You": "あなた",
|
"You": "あなた",
|
||||||
"You're a helpful assistant.": "あなたは役に立つアシスタントです。",
|
"You're a helpful assistant.": "あなたは役に立つアシスタントです。",
|
||||||
"You're now logged in.": "ログインしました。"
|
"You're now logged in.": "ログインしました。"
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
|
|
||||||
@layer base {
|
@layer base {
|
||||||
html, pre {
|
html,
|
||||||
|
pre {
|
||||||
font-family: -apple-system, 'Arimo', ui-sans-serif, system-ui, 'Segoe UI', Roboto, Ubuntu,
|
font-family: -apple-system, 'Arimo', ui-sans-serif, system-ui, 'Segoe UI', Roboto, Ubuntu,
|
||||||
Cantarell, 'Noto Sans', sans-serif, 'Helvetica Neue', Arial, 'Apple Color Emoji',
|
Cantarell, 'Noto Sans', sans-serif, 'Helvetica Neue', Arial, 'Apple Color Emoji',
|
||||||
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
'Segoe UI Emoji', 'Segoe UI Symbol', 'Noto Color Emoji';
|
||||||
|
|
|
@ -19,12 +19,10 @@ const config = {
|
||||||
},
|
},
|
||||||
onwarn: (warning, handler) => {
|
onwarn: (warning, handler) => {
|
||||||
const { code, _ } = warning;
|
const { code, _ } = warning;
|
||||||
if (code === "css-unused-selector")
|
if (code === 'css-unused-selector') return;
|
||||||
return;
|
|
||||||
|
|
||||||
handler(warning);
|
handler(warning);
|
||||||
},
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
export default config;
|
export default config;
|
||||||
|
|
|
@ -1,6 +0,0 @@
|
||||||
{
|
|
||||||
"model_name": "string",
|
|
||||||
"litellm_params": {
|
|
||||||
"model": "ollama/mistral"
|
|
||||||
}
|
|
||||||
}
|
|
Loading…
Reference in a new issue