Commit graph

1580 commits

Author SHA1 Message Date
Timothy Jaeryang Baek
53ccd718a5 refac 2026-07-14 00:24:20 -04:00
Timothy Jaeryang Baek
7088d245bb refac 2026-07-14 00:10:28 -04:00
Timothy Jaeryang Baek
3005b7bc71 refac 2026-07-13 23:31:14 -04:00
Timothy Jaeryang Baek
23062e9fca refac 2026-07-13 23:31:01 -04:00
Timothy Jaeryang Baek
9a772f42c8 refac 2026-07-10 16:41:35 -05:00
Timothy Jaeryang Baek
f5b196c060 refac 2026-07-09 17:59:17 -05:00
Timothy Jaeryang Baek
c89b6c50bc refac 2026-07-09 17:37:17 -05:00
Timothy Jaeryang Baek
5c389ad93f refac 2026-07-09 17:33:30 -05:00
Timothy Jaeryang Baek
8e46450acd refac 2026-07-09 17:28:34 -05:00
Timothy Jaeryang Baek
90eca2ac25 refac 2026-07-01 03:37:35 -05:00
Timothy Jaeryang Baek
54f31c630a refac 2026-07-01 03:32:12 -05:00
Timothy Jaeryang Baek
4351c78b1e refac 2026-07-01 03:22:13 -05:00
Timothy Jaeryang Baek
989c6c13f5 refac 2026-07-01 02:26:47 -05:00
Timothy Jaeryang Baek
9866a02863 refac 2026-07-01 02:08:34 -05:00
Timothy Jaeryang Baek
4067e357b2 refac
Some checks are pending
Python CI / Ruff Format (3.11) (push) Waiting to run
Python CI / Ruff Format (3.12) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/amd64 runner:ubuntu-latest], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args: free_disk:false name:main suffix:]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true USE_CUDA_VER=cu126 free_disk:true name:cuda126 suffix:-cuda126]) (push) Waiting to run
Create and publish Docker images with specific build args / notify-helm-charts (push) Blocked by required conditions
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_CUDA=true free_disk:true name:cuda suffix:-cuda]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_OLLAMA=true free_disk:false name:ollama suffix:-ollama]) (push) Waiting to run
Create and publish Docker images with specific build args / build (map[arch:linux/arm64 runner:ubuntu-24.04-arm], map[build_args:USE_SLIM=true free_disk:false name:slim suffix:-slim]) (push) Waiting to run
Create and publish Docker images with specific build args / merge (map[name:cuda suffix:-cuda]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:cuda126 suffix:-cuda126]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:main suffix:]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:ollama suffix:-ollama]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / merge (map[name:slim suffix:-slim]) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (, main) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda, cuda) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-cuda126, cuda126) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-ollama, ollama) (push) Blocked by required conditions
Create and publish Docker images with specific build args / copy-to-dockerhub (-slim, slim) (push) Blocked by required conditions
Frontend Build / Format & Build (push) Waiting to run
Frontend Build / Unit Tests (push) Waiting to run
2026-06-29 21:31:49 -05:00
Timothy Jaeryang Baek
5134e5ecfc refac 2026-06-29 14:03:11 -05:00
Timothy Jaeryang Baek
89709f5f80 refac 2026-06-29 13:39:08 -05:00
Timothy Jaeryang Baek
0443ab3a61 refac 2026-06-29 13:30:28 -05:00
Timothy Jaeryang Baek
22a44e67a8 refac 2026-06-29 13:15:29 -05:00
Timothy Jaeryang Baek
517cd8d102 refac 2026-06-29 13:03:14 -05:00
Timothy Jaeryang Baek
7ea7680f56 refac 2026-06-29 12:59:05 -05:00
G30
c584a4270c
perf(ui): non-blocking model and tool server loading for unreachable connections (#26289)
- Move setModels() and setToolServers() out of the loaded gate in
  +layout.svelte so the page renders immediately instead of blocking
  behind slow/unreachable connection timeouts
- Track failed Ollama backend URLs from /api/tags and skip them in the
  subsequent /api/ps fan-out, eliminating a redundant second timeout
- Silence the autocomplete toast that fires during the transient empty
  model state
2026-06-29 12:34:00 -05:00
Timothy Jaeryang Baek
bb6b2db88b refac 2026-06-29 12:26:23 -05:00
Timothy Jaeryang Baek
248315de14 refac 2026-06-29 12:25:29 -05:00
Timothy Jaeryang Baek
fe3300bd65 refac 2026-06-29 12:10:39 -05:00
Timothy Jaeryang Baek
b696c5deff refac 2026-06-29 11:38:59 -05:00
Timothy Jaeryang Baek
2c4e1fce8f refac 2026-06-29 11:13:36 -05:00
Timothy Jaeryang Baek
2d3035a112 refac 2026-06-29 10:54:53 -05:00
Timothy Jaeryang Baek
39837e0a3a refac 2026-06-29 10:51:52 -05:00
G30
8c7428122b
fix(rag): allow special tokens in document text during chunk measurement (#26210)
Documents (especially AI/LLM documentation) legitimately contain special token strings like <|endoftext|> as literal text. The tiktoken encoder raises a ValueError when encountering these during chunk size measurement in merge_docs_to_target_size(), preventing the entire file from being indexed. Pass disallowed_special=() to encoding.encode() to treat all text as normal content.
2026-06-29 10:43:24 -05:00
Juan Calderon-Perez
51246bcb31
perf(backend): offload blocking calls in async paths to threads (#26381)
Audit of asyncio.sleep vs time.sleep and event-loop-blocking calls:

- utils/plugin.py: run pip `install_frontmatter_requirements`
  (subprocess.check_call) via asyncio.to_thread in load_tool_module_by_id,
  load_function_module_by_id, and install_tool_and_function_dependencies.
- retrieval/utils.py: move the synchronous SSRF-guarded requests probe and
  loader.load() in get_content_from_url into a sync helper run via
  asyncio.to_thread.
- routers/audio.py: write uploaded audio to disk off the event loop in
  transcription().
- routers/pipelines.py: write uploaded pipeline file off the event loop in
  upload_pipeline().

The existing time.sleep call sites are all in genuinely synchronous
functions (sync requests/DB drivers/daemon threads) with async
counterparts that already use asyncio.sleep, so no time.sleep -> asyncio.sleep
changes were needed.


Claude-Session: https://claude.ai/code/session_01LXR5bYfsfSS42RGHQZu2Ta

Co-authored-by: Claude <noreply@anthropic.com>
2026-06-29 10:42:26 -05:00
Classic298
75df948f34
feat: forward client User-Agent to model backends via {{USER_AGENT}} placeholder (#26333)
Adds a {{USER_AGENT}} custom-header placeholder that relays the inbound
client's User-Agent to upstream model backends, so providers see the real
client instead of Open WebUI's internal aiohttp UA. This makes upstream
usage/cost attribution and backend telemetry possible, and is opt-in
per-connection (no global flag): admins add {{USER_AGENT}} to a connection's
custom headers in Admin > Settings > Connections.

The placeholder is sourced from the live inbound request (with a metadata
fallback for detached RAG/tool calls), so it resolves on every prompt-sending
path, not just chat completions:

- OpenAI completions, Responses API, and proxy — all route through
  get_headers_and_cookies, which now passes the request into get_custom_headers.
- Anthropic Messages API (/api/v1/messages) — already covered, it delegates
  to the chat completion handler.
- Ollama (/api/chat, /v1/completions, /v1/chat/completions, /v1/messages,
  /v1/responses) — previously had no custom-header support at all; send_request
  now applies per-connection custom headers (with templating) for every
  Ollama prompt endpoint.

Custom headers are applied after the built-in user-info headers so explicit
admin-configured headers take precedence. The other existing placeholders
({{CHAT_ID}}, {{USER_ID}}, ...) now also work on the newly covered paths.

Frontend: the connection editor's Headers field is now shown for Ollama
connections too (previously gated to non-Ollama), so the placeholder can be
configured there.

Ref: open-webui/open-webui#26159
2026-06-29 05:58:19 -05:00
Timothy Jaeryang Baek
260f3c3a22 refac 2026-06-29 05:56:08 -05:00
Timothy Jaeryang Baek
0883638027 refac 2026-06-29 05:47:21 -05:00
Timothy Jaeryang Baek
396d9ac181 refac 2026-06-29 05:27:51 -05:00
Timothy Jaeryang Baek
0eba3df119 refac 2026-06-29 05:21:49 -05:00
Timothy Jaeryang Baek
fa76764c3b refac 2026-06-29 05:16:57 -05:00
Timothy Jaeryang Baek
cdd7b88bec refac 2026-06-29 05:14:57 -05:00
Timothy Jaeryang Baek
e5b5e5917b refac 2026-06-29 04:43:08 -05:00
Timothy Jaeryang Baek
a3b487422d refac 2026-06-29 04:42:02 -05:00
Timothy Jaeryang Baek
f8ec63203c refac 2026-06-29 04:31:43 -05:00
Timothy Jaeryang Baek
fd7a59d37a refac 2026-06-29 04:27:48 -05:00
Timothy Jaeryang Baek
d3676b4f71 refac 2026-06-29 04:11:46 -05:00
Timothy Jaeryang Baek
33b91bd8ae refac 2026-06-29 03:58:00 -05:00
Classic298
0fc630b34b
fix: per-user model cache used static key= (cross-user model exposure) (#25783)
routers/openai.py and routers/ollama.py decorated get_all_models with
`@cached(key=lambda _, user: ...)`. In aiocache 0.12, `key=` is a STATIC
cache key: get_cache_key returns `self.key` verbatim (the lambda object)
without calling it, so every caller collides to ONE shared entry within
the TTL. The intended per-user namespacing never happened — one user's
permission-filtered model list could be served to another user (or an
anonymous caller) during the cache window.

The per-call hook is `key_builder=` (called as key_builder(func, *args,
**kwargs)). Switch both sites to key_builder with a (func, request,
user=None) signature so the key is built per call. user=None mirrors
ollama's optional-user signature and stays correct whether user is passed
positionally, as a kwarg, or omitted.

Verified offline: old form returns the same key object for distinct users
(collision); new form yields distinct openai_all_models_<id> /
ollama_all_models_<id> keys, and the unauthenticated base key when no user.
These two were the only @cached(key=lambda ...) sites in the backend.
2026-06-29 03:51:02 -05:00
G30
ee11069ef2
perf(ollama): offload multi-GB model file I/O with asyncio.to_thread (#25829)
The Ollama model upload and download handlers perform three stages
of sync file I/O on multi-GB model files inside async handlers:

1. Persist upload — file.file.read() + write() in a loop
2. SHA-256 hash — calculate_sha256() reads the file sequentially
3. Read for blob push — open().read() loads entire model into memory

All three stages block the event loop for the duration of the I/O.
For a 4GB model, each stage freezes the event loop for 10+ seconds
while every other user's request stalls.

Wrap each blocking stage in asyncio.to_thread() in both handlers:

- upload_model(): persist upload, calculate_sha256, blob read
- download_file_stream(): calculate_sha256, blob read

Benchmark (full pipeline: write + SHA-256 + read back, 3 trials):
- 200MB: max jitter 145ms → 1ms (145x improvement)
- 500MB: max jitter 1,026ms → 1ms (1,026x improvement)

File I/O is pure I/O — no GIL contention. asyncio.to_thread()
completely eliminates event loop blocking.
2026-06-29 03:48:48 -05:00
Classic298
a66477b710
fix: bind channel thread parent/reply to the URL channel (#25766)
GET /api/v1/channels/{id}/messages/{message_id}/thread authorized only the URL channel, but get_messages_by_parent_id() appended the thread parent (loaded by id) without checking it belonged to that channel, so a caller could read a message from a channel they cannot access by passing its id as the thread root. Require the parent to be in the requested channel before returning it, and reject a posted parent_id/reply_to_id that does not belong to the channel.

Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 03:46:50 -05:00
G30
7b1aa749eb
perf(retrieval): make URL fetch and file hash non-blocking with asyncio.to_thread (#25822)
- Wrap get_content_from_url() in asyncio.to_thread() inside
  get_sources_from_items() to prevent sync requests.get() from blocking
  the event loop when users attach URL sources to chat messages.
  The same function was already properly wrapped at retrieval.py:1839.

- Wrap hashlib.sha256(contents).hexdigest() in asyncio.to_thread()
  inside upload_file_handler() to prevent CPU-bound hashing from
  blocking the event loop during file uploads (44ms/100MB, scales
  linearly with file size).
2026-06-29 03:46:24 -05:00
Timothy Jaeryang Baek
a70a6589af refac 2026-06-29 03:42:36 -05:00
Timothy Jaeryang Baek
3fd0384ffc refac 2026-06-29 03:21:41 -05:00