Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
156 changes: 93 additions & 63 deletions backend/services/model_health_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@
return current_factory


async def _embedding_dimension_check(

Check failure on line 68 in backend/services/model_health_service.py

View check run for this annotation

SonarQubeCloud / SonarCloud Code Analysis

Refactor this function to reduce its Cognitive Complexity from 24 to the 15 allowed.

See more on https://sonarcloud.io/project/issues?id=ModelEngine-Group_nexent&issues=AZ_6dHtT_hnwuKv5tzVP&open=AZ_6dHtT_hnwuKv5tzVP&pullRequest=3655
model_name: str,
model_type: str,
model_base_url: str,
Expand All @@ -74,51 +74,67 @@
model_factory: Optional[str] = None,
timeout_seconds: Optional[float] = None,
):
# For embedding types, try the user-provided URL first; if that returns
# no valid dimension, fall back to the URL with /embeddings appended.
# Some providers serve embeddings at the bare base URL while others
# require the explicit /embeddings endpoint.
if model_type in EMBEDDING_TYPES:
model_base_url = _normalize_embedding_url(model_base_url)
original_url = model_base_url
normalized_url = _normalize_embedding_url(original_url)
urls_to_try = [original_url]
if normalized_url != original_url:
urls_to_try.append(normalized_url)
else:
urls_to_try = [model_base_url]

effective_timeout = timeout_seconds if timeout_seconds else 5.0

if model_type == "embedding":
# DashScope text embedding models use OpenAI-compatible endpoint, same as generic
embedding = await OpenAICompatibleEmbedding(
model_name=model_name,
base_url=model_base_url,
api_key=model_api_key,
embedding_dim=0,
ssl_verify=ssl_verify,
).dimension_check(timeout=effective_timeout)
if len(embedding) > 0:
return len(embedding[0])
logging.warning(
f"Embedding dimension check for {model_name} gets empty response")
return 0
elif model_type == "multi_embedding":
model_factory_lower = (model_factory or "").lower()
if model_factory_lower == "dashscope":
embedding_instance = DashScopeMultimodalEmbedding(
api_key=model_api_key,
base_url=model_base_url,
for url in urls_to_try:
if model_type == "embedding":
# DashScope text embedding models use OpenAI-compatible endpoint, same as generic
embedding = await OpenAICompatibleEmbedding(
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
else:
embedding_instance = SiliconflowMultimodalEmbedding(
base_url=url,
api_key=model_api_key,
base_url=model_base_url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
embedding = await embedding_instance.dimension_check(timeout=effective_timeout)
if isinstance(embedding, list) and len(embedding) > 0 and isinstance(embedding[0], list):
return len(embedding[0])
).dimension_check(timeout=effective_timeout)
if len(embedding) > 0:
return len(embedding[0])
elif model_type == "multi_embedding":
model_factory_lower = (model_factory or "").lower()
if model_factory_lower == "dashscope":
embedding_instance = DashScopeMultimodalEmbedding(
api_key=model_api_key,
base_url=url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
else:
embedding_instance = SiliconflowMultimodalEmbedding(
api_key=model_api_key,
base_url=url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
embedding = await embedding_instance.dimension_check(timeout=effective_timeout)
if isinstance(embedding, list) and len(embedding) > 0 and isinstance(embedding[0], list):
return len(embedding[0])
else:
raise ValueError(f"Unsupported model type: {model_type}")

# All URL variants failed
if model_type == "embedding":
logging.warning(
f"Embedding dimension check for {model_name} gets unexpected response: {type(embedding)}, value: {embedding}")
return 0
else:
raise ValueError(f"Unsupported model type: {model_type}")
f"Embedding dimension check for {model_name} gets empty response")
elif model_type == "multi_embedding":
logging.warning(
f"Embedding dimension check for {model_name} gets unexpected response")
return 0




async def _provider_catalog_connectivity_check(
Expand Down Expand Up @@ -175,42 +191,56 @@
model_base_url = model_base_url.replace(
LOCALHOST_NAME, DOCKER_INTERNAL_HOST).replace(LOCALHOST_IP, DOCKER_INTERNAL_HOST)

# Normalize embedding URLs by appending /embeddings if not present
# For embedding types, try the user-provided URL first; if that fails,
# fall back to the URL with /embeddings appended. Some providers serve
# embeddings at the bare base URL while others require the explicit endpoint.
if model_type in EMBEDDING_TYPES:
model_base_url = _normalize_embedding_url(model_base_url)
original_url = model_base_url
normalized_url = _normalize_embedding_url(model_base_url)
urls_to_try = [original_url]
if normalized_url != original_url:
urls_to_try.append(normalized_url)
else:
urls_to_try = [model_base_url]

effective_timeout = timeout_seconds if timeout_seconds else 5.0
connectivity: bool
connectivity: bool = False

if model_type == "embedding":
emb = await OpenAICompatibleEmbedding(
model_name=model_name,
base_url=model_base_url,
api_key=model_api_key,
embedding_dim=0,
ssl_verify=ssl_verify,
).dimension_check(timeout=effective_timeout)
connectivity = len(emb) > 0 and len(emb[0]) > 0
elif model_type == "multi_embedding":
model_factory_lower = (model_factory or "").lower()
if model_factory_lower == "dashscope":
embedding = DashScopeMultimodalEmbedding(
api_key=model_api_key,
base_url=model_base_url,
for url in urls_to_try:
emb = await OpenAICompatibleEmbedding(
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
else:
embedding = SiliconflowMultimodalEmbedding(
base_url=url,
api_key=model_api_key,
base_url=model_base_url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
emb = await embedding.dimension_check(timeout=effective_timeout)
connectivity = len(emb) > 0 and len(emb[0]) > 0
).dimension_check(timeout=effective_timeout)
if len(emb) > 0 and len(emb[0]) > 0:
connectivity = True
break
elif model_type == "multi_embedding":
model_factory_lower = (model_factory or "").lower()
for url in urls_to_try:
if model_factory_lower == "dashscope":
embedding = DashScopeMultimodalEmbedding(
api_key=model_api_key,
base_url=url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
else:
embedding = SiliconflowMultimodalEmbedding(
api_key=model_api_key,
base_url=url,
model_name=model_name,
embedding_dim=0,
ssl_verify=ssl_verify,
)
emb = await embedding.dimension_check(timeout=effective_timeout)
if len(emb) > 0 and len(emb[0]) > 0:
connectivity = True
break
elif model_type == "llm":
observer = MessageObserver()
set_monitoring_operation("connectivity_check",
Expand Down
16 changes: 12 additions & 4 deletions backend/services/model_management_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,17 +324,25 @@ async def create_model_for_tenant(user_id: str, tenant_id: str, model_data: Dict
raise ValueError(
f"Name {model_data['display_name']} is already in use, please choose another display name")

# If embedding or multi_embedding, ensure base_url ends with /embeddings
# If embedding or multi_embedding, verify connectivity and get dimension.
# Try the user-provided URL first; if that fails, fall back to
# appending /embeddings (some providers serve embeddings at the
# bare base URL while others require the explicit endpoint).
if model_data.get("model_type") in ("embedding", "multi_embedding"):
base_url = model_data.get("base_url", "")
if base_url and "/embeddings" not in base_url:
model_data["base_url"] = f"{base_url.rstrip('/')}/embeddings"
# Infer model_factory from base_url if not set
model_data["model_factory"] = _infer_model_factory(
model_data["model_type"], model_data["base_url"], model_data.get("model_factory")
)
# Get embedding dimension
# Try original URL first
dimension = await embedding_dimension_check(model_data)
# If failed and URL doesn't already contain /embeddings, retry with it appended
if dimension is None and base_url and "/embeddings" not in base_url:
model_data["base_url"] = f"{base_url.rstrip('/')}/embeddings"
model_data["model_factory"] = _infer_model_factory(
model_data["model_type"], model_data["base_url"], model_data.get("model_factory")
)
dimension = await embedding_dimension_check(model_data)
if dimension is None:
raise ValueError(
f"Failed to get embedding dimension for model '{model_data.get('display_name', model_data.get('model_name'))}'. "
Expand Down
Loading
Loading