perf: stop scanning every skill on each listing and chat turn (#28798)

Listing skills ran one database query per skill in the instance. A non-admin opening the list on a workspace with 500 skills issued over 500 queries, the paginated list re-resolved the caller's group membership once per row, and every chat message carrying a skill loaded every skill the user can read, full body and owner included, to use the two or three it actually referenced.

Skills now arrive already filtered: the owner-or-grant check runs in the query as an EXISTS subquery, the same way prompts and the search endpoints already do it, the per-item write flag uses the existing batch grant lookup, and the chat path asks only for the skill ids the request names.

Measured with 500 skills of which 3 are visible to the caller: 504 queries and ~300 ms before, 4 queries and ~2.6 ms after. The resulting set is unchanged for owner, public, direct-user, group and multi-grant entries, for both read and write.
This commit is contained in:
Classic298
2026-08-19 11:07:33 -07:00
committed by GitHub
parent 9bdb072690
commit dbf715cb63
3 changed files with 40 additions and 58 deletions
+1 -3
View File
@@ -2643,9 +2643,7 @@ async def process_chat_payload(request, form_data, user, metadata, model):
if skill_ids:
from open_webui.models.skills import Skills as SkillsModel
# Reuse the rows from the access query instead of re-fetching each
# skill by id.
accessible_skills = {s.id: s for s in await SkillsModel.get_skills_by_user_id(user.id, 'read')}
accessible_skills = {s.id: s for s in await SkillsModel.get_skills(user_id=user.id, ids=skill_ids)}
for sid in skill_ids:
s = accessible_skills.get(sid)
if s and s.is_active: