diff --git a/backend/open_webui/models/functions.py b/backend/open_webui/models/functions.py index fdbfac5e7..bca1223b7 100644 --- a/backend/open_webui/models/functions.py +++ b/backend/open_webui/models/functions.py @@ -308,6 +308,31 @@ class FunctionsTable: log.exception(f"Error getting function valves by id {id}: {e}") return None + def get_function_valves_by_ids( + self, ids: list[str], db: Optional[Session] = None + ) -> dict[str, dict]: + """ + Batch fetch valves for multiple functions in a single query. + Returns a dict mapping function_id -> valves dict. + Functions without valves are mapped to {}. + """ + if not ids: + return {} + try: + with get_db_context(db) as db: + functions = ( + db.query(Function.id, Function.valves) + .filter(Function.id.in_(ids)) + .all() + ) + return { + f.id: (f.valves if f.valves else {}) for f in functions + } + except Exception as e: + log.exception(f"Error batch-fetching function valves: {e}") + return {} + + def update_function_valves_by_id( self, id: str, valves: dict, db: Optional[Session] = None ) -> Optional[FunctionValves]: diff --git a/backend/open_webui/utils/models.py b/backend/open_webui/utils/models.py index 6c82b4aa9..ebf855d2c 100644 --- a/backend/open_webui/utils/models.py +++ b/backend/open_webui/utils/models.py @@ -331,11 +331,17 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None) elif meta.get(key) is None: meta[key] = copy.deepcopy(value) + # Batch-fetch all function valves in one query to avoid N+1 DB hits + # inside get_action_priority (previously called per action × per model). + all_function_valves = Functions.get_function_valves_by_ids( + list(all_function_ids) + ) + def get_action_priority(action_id): try: function_module = request.app.state.FUNCTIONS.get(action_id) if function_module and hasattr(function_module, "Valves"): - valves_db = Functions.get_function_valves_by_id(action_id) + valves_db = all_function_valves.get(action_id) valves = function_module.Valves(**(valves_db if valves_db else {})) return getattr(valves, "priority", 0) except Exception: