Commit Graph

72 Commits

Author SHA1 Message Date
Timothy Jaeryang Baek de3317e26b refac 2026-03-17 17:58:01 -05:00
Timothy Jaeryang Baek b1048fc9bc refac 2026-03-07 20:22:01 -06:00
Classic298 223c14f48b fix: add deterministic tiebreaker to all paginated chat queries (#22387)
Add Chat.id as a secondary sort key to all paginated chat queries
that use offset/limit pagination. When multiple chats share the same
updated_at timestamp, the database does not guarantee a stable order
across page boundaries, causing chats to appear on multiple pages.

This produces duplicate keys in the Svelte sidebar each-block
(each_key_duplicate error). Adding Chat.id as a tiebreaker ensures
fully deterministic ordering.

Extends the fix from #22383 (which addressed get_chat_ids_by_model_id)
to all remaining paginated chat queries.
2026-03-07 20:16:50 -06:00
Timothy Jaeryang Baek 9044abf3bb chore: format 2026-02-23 01:40:53 -06:00
Timothy Jaeryang Baek 0185f3340d refac 2026-02-22 17:28:01 -06:00
Timothy Jaeryang Baek 631e30e22d refac 2026-02-21 15:35:34 -06:00
Classic298 45e23c3ad0 perf: eliminate 2 redundant full chat deserialization on every message send (#21596)
* perf: eliminate 2 redundant full chat deserialization on every message send (#162)

Problem:
Every message send triggered get_chat_by_id_and_user_id which loads the
entire Chat row — including the potentially massive JSON blob containing
the full conversation history — even when the caller only needed a
simple yes/no ownership check or a single column value.

Two call sites in the message-send hot path were doing this:

1. main.py ownership verification: loaded the entire chat object including
   all message history JSON, then checked `if chat is None`. The JSON blob
   was immediately discarded — only the existence of the row mattered.

2. middleware.py folder check: loaded the entire chat object including all
   message history JSON, then read only `chat.folder_id` — a plain column
   on the chat table that requires zero JSON parsing.

Fix:
- Added `chat_exists_by_id_and_user_id()`: uses SQL EXISTS subquery which
  returns a boolean without loading any row data. The database can satisfy
  this from the primary key index alone.

- Added `get_chat_folder_id()`: queries only the `folder_id` column via
  `db.query(Chat.folder_id)`, which tells SQLAlchemy to SELECT only that
  single column instead of the entire row.

Both new methods preserve the same error handling semantics (return
False/None on exception) and user_id filtering (ownership check) as
the original get_chat_by_id_and_user_id.

Impact:
- Best case (typical): eliminates deserializing 2 full chat JSON blobs per
  message send. For long conversations (hundreds of messages with tool
  calls, images, file attachments), this blob can be multiple megabytes.
- Worst case: no regression — the new queries are strictly cheaper than
  the old ones (less data transferred, less Python object construction,
  no Pydantic model_validate overhead).
- The 3 remaining full chat loads in process_chat_payload (load_messages_from_db,
  add_file_context, chat_image_generation_handler) are left untouched as
  they genuinely need the full history and require separate analysis.

* Address maintainer feedback: rename method and inline call (#166)

- Rename chat_exists_by_id_and_user_id -> is_chat_owner
- Remove intermediate chat_owned variable; call is_chat_owner directly in if condition
2026-02-21 14:53:31 -06:00
Classic298 d664922feb Avoid loading full chat JSON blob for pinned/archived/shared list endpoints (#21591)
Co-authored-by: Tim Baek <tim@openwebui.com>
2026-02-19 16:48:23 -06:00
Classic298 3db6d49e57 Query title column directly in get_chat_title_by_id instead of loading full chat (#157) (#21590)
Previously loaded the entire ChatModel (including the full conversation JSON
blob) just to extract the title string. Now queries only the Chat.title
column directly, which is already a top-level DB column.
2026-02-19 16:41:46 -06:00
Timothy Jaeryang Baek 139f02a9d9 refac 2026-02-19 16:04:41 -06:00
Classic298 35763a352c Optimize shared chats list to use column projection (#163) (#21614)
The GET /chats/shared endpoint was loading full Chat rows including
the entire conversation history JSON blob, only to discard it and
return SharedChatResponse (id, title, share_id, timestamps). Now
uses with_entities() to select only the 5 needed columns, avoiding
deserialization of potentially large chat JSON for every shared chat.
2026-02-19 15:50:03 -06:00
Timothy Jaeryang Baek 09dc28df1e chore: format 2026-02-16 00:43:32 -06:00
Timothy Jaeryang Baek c748c3ede7 refac 2026-02-16 00:41:36 -06:00
Timothy Jaeryang Baek 626d236d13 chore: format 2026-02-13 15:00:39 -06:00
Timothy Jaeryang Baek a9b8677cc0 refac 2026-02-13 14:59:05 -06:00
Classic298 0f3f68b0c4 enh (#21362) 2026-02-13 14:56:53 -06:00
Timothy Jaeryang Baek f376d4f378 chore: format 2026-02-11 16:24:11 -06:00
Tim Baek 599cd2eeeb feat: analytics backend API with chat_message table
- Add chat_message table for message-level analytics with usage JSON field
- Add migration to backfill from existing chats
- Add /analytics endpoints: summary, models, users, daily
- Support hourly/daily granularity for time-series data
- Fill missing days/hours in date range
2026-02-01 07:04:13 +04:00
Timothy Jaeryang Baek a10ac774ab enh: manage shared chats 2026-01-29 18:51:02 +04:00
Timothy Jaeryang Baek 5921a19519 refac 2026-01-06 02:19:57 +04:00
Timothy Jaeryang Baek 71ca25c8ac refac 2025-12-31 20:23:32 +04:00
Classic298 048692c068 fix: prevent insert_shared_chat_by_chat_id crash when chat is None (#20273)
Add null check after db.get(Chat, chat_id) before accessing chat.share_id. Returns None instead of crashing with AttributeError when chat doesn't exist.
2025-12-31 17:38:57 +04:00
Timothy Jaeryang Baek 2041ab483e refac/enh: db session sharing 2025-12-28 22:00:44 +04:00
Timothy Jaeryang Baek 39a2b9789c refac 2025-12-26 16:16:10 +04:00
Tim Baek df106099a1 refac 2025-12-25 18:32:13 -05:00
Tim Baek 4be99174be refac 2025-12-25 18:11:17 -05:00
Timothy Jaeryang Baek 45e3237756 fix/refac: shared chat files behaviour 2025-12-21 23:29:54 +04:00
Timothy Jaeryang Baek f1bf4f20c5 feat: chat_file table 2025-12-21 23:17:53 +04:00
Classic298 48ccb1e170 fix: consolidate psql cleanup logic and fix web add with cleanup (#20072)
* sequential

* consolidate logic and fix for web add

* Update WebSearch.svelte

* Update retrieval.py

* Update retrieval.py

* Update WebSearch.svelte
2025-12-21 07:14:29 -05:00
Classic298 823b9a6dd9 chore/perf: Remove old SRC level log env vars with no impact (#20045)
* Update openai.py

* Update env.py

* Merge pull request open-webui#19030 from open-webui/dev (#119)

Co-authored-by: Tim Baek <tim@openwebui.com>
Co-authored-by: Claude <noreply@anthropic.com>

---------

Co-authored-by: Tim Baek <tim@openwebui.com>
Co-authored-by: Claude <noreply@anthropic.com>
2025-12-20 08:16:14 -05:00
Timothy Jaeryang Baek a7993f6f4e refac 2025-12-10 12:22:40 -05:00
Timothy Jaeryang Baek 5148970ef5 refac 2025-11-23 19:47:21 -05:00
Timothy Jaeryang Baek 7cf07b7e97 refac: rm folder id on chat archive 2025-11-23 00:05:27 -05:00
Timothy Jaeryang Baek e6951e804a feat/enh: move chats in folder on delete
Co-Authored-By: expruc <25387342+expruc@users.noreply.github.com>
2025-11-23 00:01:49 -05:00
Timothy Jaeryang Baek bb3e222e09 refac: clean null bytes on load 2025-11-22 20:50:27 -05:00
Timothy Jaeryang Baek 4af7cc818e refac/fix: chat search null byte filter 2025-11-22 20:34:49 -05:00
Timothy Jaeryang Baek b32f7815b8 refac: search chat postgres 2025-11-21 18:31:03 -05:00
Timothy Jaeryang Baek a51579a84b refac/pref: chat import optimization
Co-Authored-By: G30 <50341825+silentoplayz@users.noreply.github.com>
2025-11-21 03:49:49 -05:00
Timothy Jaeryang Baek 90f76d24ec refac 2025-11-19 02:16:09 -05:00
Davixk 8da4e5bb19 fix(chats): fix chat search crash (#18576)
* fix(chats): handle null bytes in PostgreSQL search

Removes null bytes from message content before performing
case-insensitive search in PostgreSQL, preventing conversion
errors and ensuring reliable query results.

* fix(chats): prevent null byte errors in PostgreSQL queries

Ensures chat content and titles containing null bytes are excluded from PostgreSQL text queries to avoid conversion errors.

Improves reliability of search and filtering by handling problematic characters in JSON fields.
2025-11-06 12:41:21 -05:00
kaiwdev 2b0b87c0f9 fix: handle invalid order_by attribute in Chat 2025-10-20 14:19:02 +09:00
Timothy Jaeryang Baek 3e003a5f17 refac 2025-10-20 00:48:01 -04:00
Timothy Jaeryang Baek 5fe56a862b fix: pinned chats in ref chat 2025-10-14 18:06:29 -05:00
silentoplayz a572cf4842 feat: add backend handling for unarchiving all chats
The previous implementation for unarchiving all chats in `ArchivedChatsModal.svelte` was inefficient, as it sent a separate request for each chat, which could potentially overload the server.

This commit introduces a new backend endpoint, `/chats/unarchive/all`, to handle the bulk unarchiving of all chats for a user with a single API call.

The frontend has been updated to use this new endpoint, resolving the performance issue by minimizing the number of requests to the server.
2025-09-28 13:25:34 -04:00
Timothy Jaeryang Baek c80bb31968 refac/enh: folder optimization 2025-09-26 20:48:17 -05:00
Timothy Jaeryang Baek 0dee15ba97 refac/enh: include foldered chats in ref chat input menu 2025-09-24 11:27:19 -05:00
Timothy Jaeryang Baek b8086c5edf refac: folder delete logic 2025-09-24 09:04:54 -05:00
Timothy Jaeryang Baek aa8ab349ed feat: ref chat 2025-09-14 10:26:46 +02:00
Timothy Jaeryang Baek b3a95f40fc refac/enh: add performance indexes
Co-Authored-By: decent-engineer-decent-datascientist <77806775+decent-engineer-decent-datascientist@users.noreply.github.com>
2025-08-19 03:24:10 +04:00
Timothy Jaeryang Baek 3f7d3def02 enh: folder filter 2025-08-10 02:10:18 +04:00