refac/enh: function valves validation

This commit is contained in:
Timothy Jaeryang Baek 2025-09-16 12:00:59 -05:00
parent fed5615c19
commit e66e0526ed
2 changed files with 70 additions and 45 deletions

View file

@ -19,6 +19,7 @@ from fastapi import (
from starlette.responses import Response, StreamingResponse from starlette.responses import Response, StreamingResponse
from open_webui.constants import ERROR_MESSAGES
from open_webui.socket.main import ( from open_webui.socket.main import (
get_event_call, get_event_call,
get_event_emitter, get_event_emitter,
@ -60,8 +61,18 @@ def get_function_module_by_id(request: Request, pipe_id: str):
function_module, _, _ = get_function_module_from_cache(request, pipe_id) function_module, _, _ = get_function_module_from_cache(request, pipe_id)
if hasattr(function_module, "valves") and hasattr(function_module, "Valves"): if hasattr(function_module, "valves") and hasattr(function_module, "Valves"):
Valves = function_module.Valves
valves = Functions.get_function_valves_by_id(pipe_id) valves = Functions.get_function_valves_by_id(pipe_id)
function_module.valves = function_module.Valves(**(valves if valves else {}))
if valves:
try:
function_module.valves = Valves(
**({k: v for k, v in valves if v is not None})
)
except Exception as e:
log.exception(f"Error loading valves for function {pipe_id}: {e}")
raise e
return function_module return function_module
@ -70,65 +81,69 @@ async def get_function_models(request):
pipe_models = [] pipe_models = []
for pipe in pipes: for pipe in pipes:
function_module = get_function_module_by_id(request, pipe.id) try:
function_module = get_function_module_by_id(request, pipe.id)
# Check if function is a manifold # Check if function is a manifold
if hasattr(function_module, "pipes"): if hasattr(function_module, "pipes"):
sub_pipes = []
# Handle pipes being a list, sync function, or async function
try:
if callable(function_module.pipes):
if asyncio.iscoroutinefunction(function_module.pipes):
sub_pipes = await function_module.pipes()
else:
sub_pipes = function_module.pipes()
else:
sub_pipes = function_module.pipes
except Exception as e:
log.exception(e)
sub_pipes = [] sub_pipes = []
log.debug( # Handle pipes being a list, sync function, or async function
f"get_function_models: function '{pipe.id}' is a manifold of {sub_pipes}" try:
) if callable(function_module.pipes):
if asyncio.iscoroutinefunction(function_module.pipes):
sub_pipes = await function_module.pipes()
else:
sub_pipes = function_module.pipes()
else:
sub_pipes = function_module.pipes
except Exception as e:
log.exception(e)
sub_pipes = []
for p in sub_pipes: log.debug(
sub_pipe_id = f'{pipe.id}.{p["id"]}' f"get_function_models: function '{pipe.id}' is a manifold of {sub_pipes}"
sub_pipe_name = p["name"] )
if hasattr(function_module, "name"): for p in sub_pipes:
sub_pipe_name = f"{function_module.name}{sub_pipe_name}" sub_pipe_id = f'{pipe.id}.{p["id"]}'
sub_pipe_name = p["name"]
pipe_flag = {"type": pipe.type} if hasattr(function_module, "name"):
sub_pipe_name = f"{function_module.name}{sub_pipe_name}"
pipe_flag = {"type": pipe.type}
pipe_models.append(
{
"id": sub_pipe_id,
"name": sub_pipe_name,
"object": "model",
"created": pipe.created_at,
"owned_by": "openai",
"pipe": pipe_flag,
}
)
else:
pipe_flag = {"type": "pipe"}
log.debug(
f"get_function_models: function '{pipe.id}' is a single pipe {{ 'id': {pipe.id}, 'name': {pipe.name} }}"
)
pipe_models.append( pipe_models.append(
{ {
"id": sub_pipe_id, "id": pipe.id,
"name": sub_pipe_name, "name": pipe.name,
"object": "model", "object": "model",
"created": pipe.created_at, "created": pipe.created_at,
"owned_by": "openai", "owned_by": "openai",
"pipe": pipe_flag, "pipe": pipe_flag,
} }
) )
else: except Exception as e:
pipe_flag = {"type": "pipe"} log.exception(e)
continue
log.debug(
f"get_function_models: function '{pipe.id}' is a single pipe {{ 'id': {pipe.id}, 'name': {pipe.name} }}"
)
pipe_models.append(
{
"id": pipe.id,
"name": pipe.name,
"object": "model",
"created": pipe.created_at,
"owned_by": "openai",
"pipe": pipe_flag,
}
)
return pipe_models return pipe_models

View file

@ -148,6 +148,16 @@ async def sync_functions(
content=function.content, content=function.content,
) )
if hasattr(function_module, "Valves") and function.valves:
Valves = function_module.Valves
try:
Valves(**{k: v for k, v in function.valves if v is not None})
except Exception as e:
log.exception(
f"Error validating valves for function {function.id}: {e}"
)
raise e
return Functions.sync_functions(user.id, form_data.functions) return Functions.sync_functions(user.id, form_data.functions)
except Exception as e: except Exception as e:
log.exception(f"Failed to load a function: {e}") log.exception(f"Failed to load a function: {e}")