refac
This commit is contained in:
@@ -839,7 +839,7 @@ async def get_models(request: Request, refresh: bool = False, user=Depends(get_v
|
||||
|
||||
models.append(model)
|
||||
|
||||
model_order_list = await Config.get('models.order_list')
|
||||
model_order_list = await Config.get('ui.model_order_list')
|
||||
if model_order_list:
|
||||
model_order_dict = {model_id: i for i, model_id in enumerate(model_order_list)}
|
||||
# Sort models by order list priority, with fallback for those not in the list
|
||||
|
||||
@@ -22,6 +22,7 @@ from open_webui.models.functions import (
|
||||
)
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.plugin import (
|
||||
get_functions_cache,
|
||||
get_function_module_from_cache,
|
||||
load_function_module_by_id,
|
||||
replace_imports,
|
||||
@@ -205,7 +206,7 @@ async def create_new_function(
|
||||
)
|
||||
form_data.meta.manifest = frontmatter
|
||||
|
||||
FUNCTIONS = request.app.state.FUNCTIONS
|
||||
FUNCTIONS = get_functions_cache(request)
|
||||
FUNCTIONS[form_data.id] = function_module
|
||||
|
||||
function = await Functions.insert_new_function(user.id, function_type, form_data, db=db)
|
||||
@@ -322,7 +323,7 @@ async def update_function_by_id(
|
||||
function_module, function_type, frontmatter = await load_function_module_by_id(id, content=form_data.content)
|
||||
form_data.meta.manifest = frontmatter
|
||||
|
||||
FUNCTIONS = request.app.state.FUNCTIONS
|
||||
FUNCTIONS = get_functions_cache(request)
|
||||
FUNCTIONS[id] = function_module
|
||||
|
||||
updated = {**form_data.model_dump(exclude={'id'}), 'type': function_type}
|
||||
@@ -363,9 +364,8 @@ async def delete_function_by_id(
|
||||
result = await Functions.delete_function_by_id(id, db=db)
|
||||
|
||||
if result:
|
||||
FUNCTIONS = request.app.state.FUNCTIONS
|
||||
if id in FUNCTIONS:
|
||||
del FUNCTIONS[id]
|
||||
FUNCTIONS = get_functions_cache(request)
|
||||
FUNCTIONS.pop(id, None)
|
||||
|
||||
return result
|
||||
|
||||
|
||||
@@ -773,14 +773,15 @@ async def edit_images(request: Request, form_data: EditImageForm, user=Depends(g
|
||||
# global image-edit switch and the per-user image-generation permission. The internal
|
||||
# callers (edit_image tool, chat middleware) gate themselves and call image_edits()
|
||||
# directly, so they are unaffected by this wrapper.
|
||||
if not request.app.state.config.ENABLE_IMAGE_EDIT:
|
||||
image_config = await get_image_config()
|
||||
if not image_config.ENABLE_IMAGE_EDIT:
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||
)
|
||||
|
||||
if user.role != 'admin' and not await has_permission(
|
||||
user.id, 'features.image_generation', request.app.state.config.USER_PERMISSIONS
|
||||
user.id, 'features.image_generation', image_config.USER_PERMISSIONS
|
||||
):
|
||||
raise HTTPException(
|
||||
status_code=403,
|
||||
|
||||
@@ -532,11 +532,7 @@ async def get_model_profile_image(
|
||||
|
||||
# Fallback: check arena models stored in config (not in the DB)
|
||||
if not profile_image_url:
|
||||
arena_models = getattr(
|
||||
getattr(request.app.state, 'config', None),
|
||||
'EVALUATION_ARENA_MODELS',
|
||||
[],
|
||||
)
|
||||
arena_models = await Config.get('evaluation.arena.models', []) or []
|
||||
for arena_model in arena_models:
|
||||
if arena_model.get('id') == id:
|
||||
profile_image_url = arena_model.get('meta', {}).get('profile_image_url')
|
||||
|
||||
@@ -31,6 +31,7 @@ from open_webui.utils.access_control import (
|
||||
)
|
||||
from open_webui.utils.auth import get_admin_user, get_verified_user
|
||||
from open_webui.utils.plugin import (
|
||||
get_tools_cache,
|
||||
get_tool_module_from_cache,
|
||||
load_tool_module_by_id,
|
||||
replace_imports,
|
||||
@@ -70,8 +71,9 @@ async def get_tools(
|
||||
tools = []
|
||||
|
||||
# Local Tools
|
||||
tools_cache = get_tools_cache(request)
|
||||
for tool in await Tools.get_tools(defer_content=True, db=db):
|
||||
tool_module = request.app.state.TOOLS.get(tool.id) if hasattr(request.app.state, 'TOOLS') else None
|
||||
tool_module = tools_cache.get(tool.id)
|
||||
tools.append(
|
||||
ToolUserResponse(
|
||||
**{
|
||||
@@ -368,7 +370,7 @@ async def create_new_tools(
|
||||
tool_module, frontmatter = await load_tool_module_by_id(form_data.id, content=form_data.content)
|
||||
form_data.meta.manifest = frontmatter
|
||||
|
||||
TOOLS = request.app.state.TOOLS
|
||||
TOOLS = get_tools_cache(request)
|
||||
TOOLS[form_data.id] = tool_module
|
||||
|
||||
specs = get_tool_specs(TOOLS[form_data.id])
|
||||
@@ -498,7 +500,7 @@ async def update_tools_by_id(
|
||||
tool_module, frontmatter = await load_tool_module_by_id(id, content=form_data.content)
|
||||
form_data.meta.manifest = frontmatter
|
||||
|
||||
TOOLS = request.app.state.TOOLS
|
||||
TOOLS = get_tools_cache(request)
|
||||
TOOLS[id] = tool_module
|
||||
|
||||
specs = get_tool_specs(TOOLS[id])
|
||||
@@ -624,9 +626,8 @@ async def delete_tools_by_id(
|
||||
|
||||
result = await Tools.delete_tool_by_id(id, db=db)
|
||||
if result:
|
||||
TOOLS = request.app.state.TOOLS
|
||||
if id in TOOLS:
|
||||
del TOOLS[id]
|
||||
TOOLS = get_tools_cache(request)
|
||||
TOOLS.pop(id, None)
|
||||
|
||||
return result
|
||||
|
||||
@@ -708,11 +709,7 @@ async def get_tools_valves_spec_by_id(
|
||||
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||
)
|
||||
|
||||
if id in request.app.state.TOOLS:
|
||||
tools_module = request.app.state.TOOLS[id]
|
||||
else:
|
||||
tools_module, _ = await load_tool_module_by_id(id)
|
||||
request.app.state.TOOLS[id] = tools_module
|
||||
tools_module, _ = await get_tool_module_from_cache(request, id)
|
||||
|
||||
if hasattr(tools_module, 'Valves'):
|
||||
Valves = tools_module.Valves
|
||||
@@ -759,11 +756,7 @@ async def update_tools_valves_by_id(
|
||||
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||
)
|
||||
|
||||
if id in request.app.state.TOOLS:
|
||||
tools_module = request.app.state.TOOLS[id]
|
||||
else:
|
||||
tools_module, _ = await load_tool_module_by_id(id)
|
||||
request.app.state.TOOLS[id] = tools_module
|
||||
tools_module, _ = await get_tool_module_from_cache(request, id)
|
||||
|
||||
if not hasattr(tools_module, 'Valves'):
|
||||
raise HTTPException(
|
||||
@@ -858,11 +851,7 @@ async def get_tools_user_valves_spec_by_id(
|
||||
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||
)
|
||||
|
||||
if id in request.app.state.TOOLS:
|
||||
tools_module = request.app.state.TOOLS[id]
|
||||
else:
|
||||
tools_module, _ = await load_tool_module_by_id(id)
|
||||
request.app.state.TOOLS[id] = tools_module
|
||||
tools_module, _ = await get_tool_module_from_cache(request, id)
|
||||
|
||||
if hasattr(tools_module, 'UserValves'):
|
||||
UserValves = tools_module.UserValves
|
||||
@@ -904,11 +893,7 @@ async def update_tools_user_valves_by_id(
|
||||
detail=ERROR_MESSAGES.ACCESS_PROHIBITED,
|
||||
)
|
||||
|
||||
if id in request.app.state.TOOLS:
|
||||
tools_module = request.app.state.TOOLS[id]
|
||||
else:
|
||||
tools_module, _ = await load_tool_module_by_id(id)
|
||||
request.app.state.TOOLS[id] = tools_module
|
||||
tools_module, _ = await get_tool_module_from_cache(request, id)
|
||||
|
||||
if hasattr(tools_module, 'UserValves'):
|
||||
UserValves = tools_module.UserValves
|
||||
|
||||
@@ -21,8 +21,8 @@ from open_webui.routers import ollama, openai
|
||||
from open_webui.socket.utils import RedisDict
|
||||
from open_webui.utils.access_control import has_access, has_base_model_access
|
||||
from open_webui.utils.plugin import (
|
||||
get_functions_cache,
|
||||
get_function_module_from_cache,
|
||||
load_function_module_by_id,
|
||||
)
|
||||
|
||||
logging.basicConfig(stream=sys.stdout, level=GLOBAL_LOG_LEVEL)
|
||||
@@ -322,10 +322,11 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None)
|
||||
# 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 = await Functions.get_function_valves_by_ids(list(all_function_ids))
|
||||
functions_cache = get_functions_cache(request)
|
||||
|
||||
def get_action_priority(action_id):
|
||||
try:
|
||||
function_module = request.app.state.FUNCTIONS.get(action_id)
|
||||
function_module = functions_cache.get(action_id)
|
||||
if function_module and hasattr(function_module, 'Valves'):
|
||||
valves_db = all_function_valves.get(action_id)
|
||||
valves = function_module.Valves(**(valves_db if valves_db else {}))
|
||||
@@ -355,7 +356,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None)
|
||||
log.info(f'Action not found: {action_id}')
|
||||
continue
|
||||
|
||||
function_module = request.app.state.FUNCTIONS.get(action_id)
|
||||
function_module = functions_cache.get(action_id)
|
||||
if function_module is None:
|
||||
log.info(f'Failed to load action module: {action_id}')
|
||||
continue
|
||||
@@ -368,7 +369,7 @@ async def get_all_models(request, refresh: bool = False, user: UserModel = None)
|
||||
log.info(f'Filter not found: {filter_id}')
|
||||
continue
|
||||
|
||||
function_module = request.app.state.FUNCTIONS.get(filter_id)
|
||||
function_module = functions_cache.get(filter_id)
|
||||
if function_module is None:
|
||||
log.info(f'Failed to load filter module: {filter_id}')
|
||||
continue
|
||||
|
||||
@@ -298,7 +298,33 @@ async def load_function_module_by_id(function_id: str, content: str | None = Non
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
|
||||
def _state_cache(request, name: str) -> dict:
|
||||
if not hasattr(request.app.state, name):
|
||||
setattr(request.app.state, name, {})
|
||||
return getattr(request.app.state, name)
|
||||
|
||||
|
||||
def get_tools_cache(request) -> dict:
|
||||
return _state_cache(request, 'TOOLS')
|
||||
|
||||
|
||||
def get_tool_contents_cache(request) -> dict:
|
||||
return _state_cache(request, 'TOOL_CONTENTS')
|
||||
|
||||
|
||||
def get_functions_cache(request) -> dict:
|
||||
return _state_cache(request, 'FUNCTIONS')
|
||||
|
||||
|
||||
def get_function_contents_cache(request) -> dict:
|
||||
return _state_cache(request, 'FUNCTION_CONTENTS')
|
||||
|
||||
|
||||
async def get_tool_module_from_cache(request, tool_id, load_from_db=True):
|
||||
tools_cache = get_tools_cache(request)
|
||||
tool_contents_cache = get_tool_contents_cache(request)
|
||||
content = None
|
||||
|
||||
if load_from_db:
|
||||
# Always load from the database by default
|
||||
tool = await Tools.get_tool_by_id(tool_id)
|
||||
@@ -312,27 +338,19 @@ async def get_tool_module_from_cache(request, tool_id, load_from_db=True):
|
||||
# Update the tool content in the database
|
||||
await Tools.update_tool_by_id(tool_id, {'content': content})
|
||||
|
||||
if (hasattr(request.app.state, 'TOOL_CONTENTS') and tool_id in request.app.state.TOOL_CONTENTS) and (
|
||||
hasattr(request.app.state, 'TOOLS') and tool_id in request.app.state.TOOLS
|
||||
):
|
||||
if request.app.state.TOOL_CONTENTS[tool_id] == content:
|
||||
return request.app.state.TOOLS[tool_id], None
|
||||
if tool_id in tool_contents_cache and tool_id in tools_cache:
|
||||
if tool_contents_cache[tool_id] == content:
|
||||
return tools_cache[tool_id], None
|
||||
|
||||
tool_module, frontmatter = await load_tool_module_by_id(tool_id, content)
|
||||
else:
|
||||
if hasattr(request.app.state, 'TOOLS') and tool_id in request.app.state.TOOLS:
|
||||
return request.app.state.TOOLS[tool_id], None
|
||||
if tool_id in tools_cache:
|
||||
return tools_cache[tool_id], None
|
||||
|
||||
tool_module, frontmatter = await load_tool_module_by_id(tool_id)
|
||||
|
||||
if not hasattr(request.app.state, 'TOOLS'):
|
||||
request.app.state.TOOLS = {}
|
||||
|
||||
if not hasattr(request.app.state, 'TOOL_CONTENTS'):
|
||||
request.app.state.TOOL_CONTENTS = {}
|
||||
|
||||
request.app.state.TOOLS[tool_id] = tool_module
|
||||
request.app.state.TOOL_CONTENTS[tool_id] = content
|
||||
tools_cache[tool_id] = tool_module
|
||||
tool_contents_cache[tool_id] = content
|
||||
|
||||
return tool_module, frontmatter
|
||||
|
||||
@@ -340,6 +358,10 @@ async def get_tool_module_from_cache(request, tool_id, load_from_db=True):
|
||||
async def get_function_module_from_cache(
|
||||
request, function_id, function: FunctionModel | None = None, load_from_db=True
|
||||
):
|
||||
functions_cache = get_functions_cache(request)
|
||||
function_contents_cache = get_function_contents_cache(request)
|
||||
content = None
|
||||
|
||||
if load_from_db:
|
||||
# Always load from the database by default
|
||||
# This is useful for hooks like "inlet" or "outlet" where the content might change
|
||||
@@ -357,30 +379,22 @@ async def get_function_module_from_cache(
|
||||
# Update the function content in the database
|
||||
await Functions.update_function_by_id(function_id, {'content': content})
|
||||
|
||||
if (
|
||||
hasattr(request.app.state, 'FUNCTION_CONTENTS') and function_id in request.app.state.FUNCTION_CONTENTS
|
||||
) and (hasattr(request.app.state, 'FUNCTIONS') and function_id in request.app.state.FUNCTIONS):
|
||||
if request.app.state.FUNCTION_CONTENTS[function_id] == content:
|
||||
return request.app.state.FUNCTIONS[function_id], None, None
|
||||
if function_id in function_contents_cache and function_id in functions_cache:
|
||||
if function_contents_cache[function_id] == content:
|
||||
return functions_cache[function_id], None, None
|
||||
|
||||
function_module, function_type, frontmatter = await load_function_module_by_id(function_id, content)
|
||||
else:
|
||||
# Load from cache (e.g. "stream" hook)
|
||||
# This is useful for performance reasons
|
||||
|
||||
if hasattr(request.app.state, 'FUNCTIONS') and function_id in request.app.state.FUNCTIONS:
|
||||
return request.app.state.FUNCTIONS[function_id], None, None
|
||||
if function_id in functions_cache:
|
||||
return functions_cache[function_id], None, None
|
||||
|
||||
function_module, function_type, frontmatter = await load_function_module_by_id(function_id)
|
||||
|
||||
if not hasattr(request.app.state, 'FUNCTIONS'):
|
||||
request.app.state.FUNCTIONS = {}
|
||||
|
||||
if not hasattr(request.app.state, 'FUNCTION_CONTENTS'):
|
||||
request.app.state.FUNCTION_CONTENTS = {}
|
||||
|
||||
request.app.state.FUNCTIONS[function_id] = function_module
|
||||
request.app.state.FUNCTION_CONTENTS[function_id] = content
|
||||
functions_cache[function_id] = function_module
|
||||
function_contents_cache[function_id] = content
|
||||
|
||||
return function_module, function_type, frontmatter
|
||||
|
||||
|
||||
@@ -95,7 +95,7 @@ from open_webui.tools.builtin import (
|
||||
from open_webui.utils.access_control import has_access, has_connection_access, has_permission
|
||||
from open_webui.utils.headers import get_custom_headers, include_user_info_headers
|
||||
from open_webui.utils.misc import is_string_allowed
|
||||
from open_webui.utils.plugin import load_tool_module_by_id
|
||||
from open_webui.utils.plugin import get_tool_contents_cache, get_tools_cache, load_tool_module_by_id
|
||||
from pydantic import BaseModel, Field, create_model
|
||||
from pydantic.fields import FieldInfo
|
||||
|
||||
@@ -250,11 +250,13 @@ async def get_tools(request: Request, tool_ids: list[str], user: UserModel, extr
|
||||
log.warning(f'Access denied to tool {tool_id} for user {user.id}')
|
||||
continue
|
||||
|
||||
module = request.app.state.TOOLS.get(tool_id)
|
||||
if module is None or request.app.state.TOOL_CONTENTS.get(tool_id) != tool.content:
|
||||
tools_cache = get_tools_cache(request)
|
||||
tool_contents_cache = get_tool_contents_cache(request)
|
||||
module = tools_cache.get(tool_id)
|
||||
if module is None or tool_contents_cache.get(tool_id) != tool.content:
|
||||
module, _ = await load_tool_module_by_id(tool_id, content=tool.content)
|
||||
request.app.state.TOOLS[tool_id] = module
|
||||
request.app.state.TOOL_CONTENTS[tool_id] = tool.content
|
||||
tools_cache[tool_id] = module
|
||||
tool_contents_cache[tool_id] = tool.content
|
||||
|
||||
__user__ = {
|
||||
**extra_params['__user__'],
|
||||
|
||||
Reference in New Issue
Block a user