Files
wehub-resource-sync e4dcfc49aa
Tests / Import Check (Python 3.13) (push) Has been cancelled
Tests / Import Check (Python 3.14) (push) Has been cancelled
Tests / Python Tests (Python 3.11) (push) Has been cancelled
Tests / Python Tests (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.14) (push) Has been cancelled
Tests / Test Summary (push) Has been cancelled
Tests / Lint and Format (push) Has been cancelled
Tests / Web Node Tests (push) Has been cancelled
Tests / Import Check (Python 3.11) (push) Has been cancelled
Tests / Import Check (Python 3.12) (push) Has been cancelled
Tests / Python Tests (Python 3.13) (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 13:00:43 +08:00

118 lines
4.1 KiB
Python

"""Embedding endpoint URL helpers.
Embedding adapters post to the configured URL exactly. These helpers keep the
user-visible Settings value aligned with provider-specific endpoint paths.
"""
from __future__ import annotations
from urllib.parse import urlparse
EMBEDDING_PROVIDER_ALIASES = {
"google": "gemini",
"huggingface": "custom",
"lm_studio": "vllm",
"llama_cpp": "vllm",
"openai_compatible": "custom",
}
EMBEDDING_PROVIDER_LABELS = {
"openai": "OpenAI",
"gemini": "Gemini",
"openrouter": "OpenRouter",
"jina": "Jina",
"vllm": "vLLM / LM Studio",
"siliconflow": "SiliconFlow",
"ollama": "Ollama",
"cohere": "Cohere",
}
EMBEDDING_PROVIDER_DEFAULT_ENDPOINTS = {
"openai": "https://api.openai.com/v1/embeddings",
"gemini": "https://generativelanguage.googleapis.com/v1beta/openai/embeddings",
"openrouter": "https://openrouter.ai/api/v1/embeddings",
"cohere": "https://api.cohere.com/v2/embed",
"jina": "https://api.jina.ai/v1/embeddings",
"ollama": "http://localhost:11434/api/embed",
"vllm": "http://localhost:8000/v1/embeddings",
"siliconflow": "https://api.siliconflow.cn/v1/embeddings",
"aliyun": (
"https://dashscope.aliyuncs.com/api/v1/services/embeddings/"
"multimodal-embedding/multimodal-embedding"
),
}
EMBEDDING_PROVIDERS_REQUIRING_EMBEDDINGS_PATH = {
"openai",
"gemini",
"openrouter",
"jina",
"vllm",
"siliconflow",
}
def canonical_embedding_provider_name(name: str | None) -> str:
value = str(name or "").strip().lower().replace("-", "_")
return EMBEDDING_PROVIDER_ALIASES.get(value, value)
def _same_origin_url(url: str, path: str) -> str:
parsed = urlparse(url if "://" in url else f"http://{url}")
if parsed.scheme and parsed.netloc:
return f"{parsed.scheme}://{parsed.netloc}{path}"
return url.rstrip("/") + path
def normalize_embedding_endpoint_for_display(provider: str | None, base_url: str | None) -> str:
"""Return the full endpoint URL that should be shown and saved in Settings."""
provider_name = canonical_embedding_provider_name(provider)
url = str(base_url or "").strip()
if not url:
return EMBEDDING_PROVIDER_DEFAULT_ENDPOINTS.get(provider_name, "")
trimmed = url.rstrip("/")
if provider_name in EMBEDDING_PROVIDERS_REQUIRING_EMBEDDINGS_PATH:
if trimmed.endswith("/embeddings"):
return trimmed
if trimmed.endswith("/v1"):
return f"{trimmed}/embeddings"
if provider_name == "ollama":
if trimmed.endswith("/api/embed"):
return trimmed
if trimmed.endswith("/api"):
return f"{trimmed}/embed"
parsed = urlparse(trimmed if "://" in trimmed else f"http://{trimmed}")
if parsed.scheme and parsed.netloc and parsed.path in {"", "/"}:
return _same_origin_url(trimmed, "/api/embed")
if provider_name == "cohere":
if trimmed.endswith("/embed"):
return trimmed
if trimmed.endswith("/v2"):
return f"{trimmed}/embed"
return url
def embedding_endpoint_validation_error(provider: str | None, base_url: str | None) -> str | None:
"""Validate that known providers use the exact endpoint path shown to users."""
provider_name = canonical_embedding_provider_name(provider)
url = str(base_url or "").strip()
if not url:
return "Embedding endpoint URL is empty."
parsed = urlparse(url if "://" in url else f"http://{url}")
path = parsed.path.rstrip("/")
label = EMBEDDING_PROVIDER_LABELS.get(provider_name, provider_name or "Embedding provider")
if provider_name in EMBEDDING_PROVIDERS_REQUIRING_EMBEDDINGS_PATH:
if not path.endswith("/embeddings"):
return f"{label} embedding endpoint must end with /embeddings."
elif provider_name == "ollama":
if path != "/api/embed":
return "Ollama embedding endpoint must be the full /api/embed URL."
elif provider_name == "cohere":
if not path.endswith("/embed"):
return "Cohere embedding endpoint must end with /embed."
return None