Commit graph

94 commits

Author SHA1 Message Date
Timothy Jaeryang Baek
6d0295588e refac: modernize type annotations (PEP 604 / PEP 585) 2026-05-12 17:10:15 +09:00
Timothy Jaeryang Baek
c951b4f262 chore: format 2026-05-11 02:29:13 +09:00
Timothy Jaeryang Baek
1388f4568b refac 2026-05-11 01:46:33 +09:00
Timothy Jaeryang Baek
485d689cfd refac 2026-05-09 07:52:15 +09:00
Timothy Jaeryang Baek
4d766a3edf refac 2026-05-09 03:19:48 +09:00
Constantine
3560d2f630
perf(chats): drop redundant db.refresh after commit in update_chat_by_id (#24024)
The chat table has no computed columns (no DEFAULT, SERIAL/IDENTITY,
or TRIGGER that populate server-side values on UPDATE), and every
column modified by update_chat_by_id is set explicitly from Python
values earlier in the function. db.refresh therefore issues a SELECT
that replaces those just-written Python values with the round-tripped
database representation of the same values, which is a no-op for
functional purposes but pulls the entire chat.chat JSON blob back over
the network and through the driver's JSON decoder.

On large, active chats where chat.chat can reach tens of megabytes,
skipping the refresh measurably reduces latency and eliminates one
~JSON-sized transient allocation per write.
2026-04-24 18:34:57 +09:00
Timothy Jaeryang Baek
4113b15a60 chore: format 2026-04-17 14:28:18 +09:00
Classic298
32cfb5788a
perf(chats): select only meta column in get_chat_tags_by_id_and_user_id (#23798)
Avoid loading the full Chat row (including the potentially large `chat`
JSON column) just to read tag IDs from `meta.tags`. Issue a narrow
SELECT on `Chat.meta` instead, which is much cheaper for chats with
large message histories.

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-17 12:35:58 +09:00
Classic298
2dca850cee
perf: use set for O(1) lookup in insert_chat_files dedupe (#23800)
Convert chat_message_file_ids from list to set so the membership test
in the comprehension is O(1) instead of O(m), turning the dedupe from
O(n*m) into O(n+m). Also replace the redundant set([...]) with a set
comprehension.

https://claude.ai/code/session_01Le3NnqNhcgaJvFrDZGqmwe

Co-authored-by: Claude <noreply@anthropic.com>
2026-04-17 12:28:34 +09:00
Timothy Jaeryang Baek
2e52ad8ff2 refac: shared chat 2026-04-17 10:16:32 +09:00
Timothy Jaeryang Baek
cf4218e688 refac 2026-04-13 21:29:03 -05:00
Timothy Jaeryang Baek
25898116ea chore: format 2026-04-12 18:12:59 -05:00
Timothy Jaeryang Baek
27169124f2 refac: async db 2026-04-12 14:22:11 -05:00
Timothy Jaeryang Baek
a71d927a0c chore: format 2026-04-02 08:11:06 -05:00
Timothy Jaeryang Baek
640dbb6a28 refac 2026-04-02 08:09:57 -05:00
Algorithm5838
a28ea36657
perf: inline update_chat_title_by_id into single DB context (#23214) 2026-04-01 07:06:16 -05:00
Timothy Jaeryang Baek
0e5696de74 refac 2026-04-01 05:55:48 -05:00
Timothy Jaeryang Baek
c8ef5a4f38 chore: format 2026-04-01 04:36:02 -05:00
Timothy Jaeryang Baek
0638b9f56c refac 2026-04-01 04:00:18 -05:00
Algorithm5838
1c5e84ddf2
perf: project only Chat.id in delete_shared_chats_by_user_id (#23216) 2026-03-30 05:15:12 -05:00
Timothy Jaeryang Baek
bcb71bb520 feat: tasks 2026-03-29 18:01:04 -05:00
Timothy Jaeryang Baek
ade617efa8 refac 2026-03-24 04:49:48 -05:00
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