NOTICE
Open WebUI Community is currently undergoing a major revamp to improve user experience and performance. Expected completion by year-end! ✨

Function
filter
v0.1.7
Dynamic Vision Router
Routes incoming chat requests to a specified vision model if the user's message contains images.
Function ID
dynamic_vision_router
Creator
@hub
Downloads
1.7K+

Function Content
python
"""
title: Dynamic Vision Router
author: open-webui, atgehrhardt,
    credits to @iamg30 for v0.1.5-v0.1.7 updates
author_url: https://github.com/open-webui
funding_url: https://github.com/open-webui
version: 0.1.7
required_open_webui_version: 0.3.8
"""

from pydantic import BaseModel, Field
from typing import Callable, Awaitable, Any, Optional, Literal
import json

from open_webui.utils.misc import get_last_user_message_item


class Filter:
    class Valves(BaseModel):
        priority: int = Field(
            default=0,
            description="Priority level for the filter operations.",
        )
        vision_model_id: str = Field(
            default="",
            description="The identifier of the vision model to be used for processing images. Note: Compatibility is provider-specific; ollama models can only route to ollama models, and OpenAI models to OpenAI models respectively.",
        )
        skip_reroute_models: list[str] = Field(
            default_factory=list,
            description="A list of model identifiers that should not be re-routed to the chosen vision model.",
        )
        enabled_for_admins: bool = Field(
            default=False,
            description="Whether dynamic vision routing is enabled for admin users.",
        )
        enabled_for_users: bool = Field(
            default=True,
            description="Whether dynamic vision routing is enabled for regular users.",
        )
        status: bool = Field(
            default=False,
            description="A flag to enable or disable the status indicator. Set to True to enable status updates.",
        )
        pass

    def __init__(self):
        self.valves = self.Valves()
        pass

    async def inlet(
        self,
        body: dict,
        __event_emitter__: Callable[[Any], Awaitable[None]],
        __model__: Optional[dict] = None,
        __user__: Optional[dict] = None,
    ) -> dict:
        if __model__["id"] in self.valves.skip_reroute_models:
            return body
        if __model__["id"] == self.valves.vision_model_id:
            return body
        if __user__ is not None:
            if __user__.get("role") == "admin" and not self.valves.enabled_for_admins:
                return body
            elif __user__.get("role") == "user" and not self.valves.enabled_for_users:
                return body

        messages = body.get("messages")
        if messages is None:
            # Handle the case where messages is None
            return body

        user_message = get_last_user_message_item(messages)
        if user_message is None:
            # Handle the case where user_message is None
            return body

        has_images = user_message.get("images") is not None
        if not has_images:
            user_message_content = user_message.get("content")
            if user_message_content is not None and isinstance(
                user_message_content, list
            ):
                has_images = any(
                    item.get("type") == "image_url" for item in user_message_content
                )

        if has_images:
            if self.valves.vision_model_id:
                body["model"] = self.valves.vision_model_id
                if self.valves.status:
                    await __event_emitter__(
                        {
                            "type": "status",
                            "data": {
                                "description": f"Request routed to {self.valves.vision_model_id}",
                                "done": True,
                            },
                        }
                    )
            else:
                if self.valves.status:
                    await __event_emitter__(
                        {
                            "type": "status",
                            "data": {
                                "description": "No vision model ID provided, routing could not be completed.",
                                "done": True,
                            },
                        }
                    )
        return body