From 7ced6ed7953531648ce3409bbd23564db13f2f60 Mon Sep 17 00:00:00 2001 From: turboderp <11859846+turboderp@users.noreply.github.com> Date: Wed, 15 Jul 2026 01:15:01 +0200 Subject: [PATCH] Fix circular import in vision.py --- backends/exllamav3/vision.py | 12 +++++++---- common/multimodal.py | 30 ++++++++------------------ endpoints/OAI/utils/chat_completion.py | 2 +- 3 files changed, 18 insertions(+), 26 deletions(-) diff --git a/backends/exllamav3/vision.py b/backends/exllamav3/vision.py index fb3eaa6..aa6df57 100644 --- a/backends/exllamav3/vision.py +++ b/backends/exllamav3/vision.py @@ -1,6 +1,7 @@ """Vision utilities for ExLlamaV3.""" -from common import model +from typing import TYPE_CHECKING + from common.optional_dependencies import dependencies from common.image_util import get_image from common.logger import xlogger @@ -10,6 +11,9 @@ from common.logger import xlogger if dependencies.exllamav3: from exllamav3.tokenizer import MMEmbedding +if TYPE_CHECKING: + from backends.exllamav3.model import ExllamaV3Container + from collections import OrderedDict from hashlib import blake2b from typing import OrderedDict as OrderedDictType @@ -22,7 +26,7 @@ def _image_key_128(s: str) -> bytes: return blake2b(s.encode("utf-8"), digest_size=16).digest() -async def get_image_embedding_exl3(url: str) -> "MMEmbedding": +async def get_image_embedding_exl3(container: "ExllamaV3Container", url: str) -> "MMEmbedding": key = _image_key_128(url) cached = _embedding_cache.get(key) @@ -33,8 +37,8 @@ async def get_image_embedding_exl3(url: str) -> "MMEmbedding": return embedding image = await get_image(url) - embedding = model.container.vision_model.get_image_embeddings( - tokenizer=model.container.tokenizer, + embedding = container.vision_model.get_image_embeddings( + tokenizer=container.tokenizer, image=image, text_alias=None, ) diff --git a/common/multimodal.py b/common/multimodal.py index f222cc9..8b950c6 100644 --- a/common/multimodal.py +++ b/common/multimodal.py @@ -1,32 +1,20 @@ -from backends.exllamav3.vision import get_image_embedding_exl3 -from common import model -from common.logger import xlogger +from typing import List, TYPE_CHECKING + from pydantic import BaseModel, Field -from typing import List -from common.optional_dependencies import dependencies +from backends.exllamav3.vision import get_image_embedding_exl3 -if dependencies.exllamav3: - from exllamav3 import Model +if TYPE_CHECKING: + from backends.exllamav3.model import ExllamaV3Container class MultimodalEmbeddingWrapper(BaseModel): """Common multimodal embedding wrapper""" - type: str = None content: list = Field(default_factory=list) text_alias: List[str] = Field(default_factory=list) - async def add(self, url: str): - # Determine the type of vision embedding to use - if not self.type: - if dependencies.exllamav3 and isinstance(model.container.vision_model, Model): - self.type = "MMEmbedding" - - # Create the embedding - if self.type == "MMEmbedding": - embedding = await get_image_embedding_exl3(url) - self.content.append(embedding) - self.text_alias.append(embedding.text_alias) - else: - xlogger.error("No valid vision model to create embedding") + async def add(self, container: "ExllamaV3Container", url: str): + embedding = await get_image_embedding_exl3(container, url) + self.content.append(embedding) + self.text_alias.append(embedding.text_alias) diff --git a/endpoints/OAI/utils/chat_completion.py b/endpoints/OAI/utils/chat_completion.py index 4ff2bf0..65afdf1 100644 --- a/endpoints/OAI/utils/chat_completion.py +++ b/endpoints/OAI/utils/chat_completion.py @@ -214,7 +214,7 @@ async def format_messages_with_template( if content.type == "text": concatenated_content += content.text elif content.type == "image_url" and mm_embeddings: - await mm_embeddings.add(content.image_url.url) + await mm_embeddings.add(model.container, content.image_url.url) concatenated_content += mm_embeddings.text_alias[-1] # Convert the message content into a concatenated string