Skip to content
Open
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
14 changes: 14 additions & 0 deletions astrbot/core/config/default.py
Original file line number Diff line number Diff line change
Expand Up @@ -1825,6 +1825,20 @@
"timeout": 60,
"proxy": "",
},
"阿里云百炼 Embedding": {
"id": "dashscope_embedding",
"type": "dashscope_embedding",
"provider": "dashscope",
"provider_type": "embedding",
"hint": "provider_group.provider.dashscope_embedding.hint",
"enable": True,
"embedding_api_key": "",
"embedding_api_base": "https://dashscope.aliyuncs.com/compatible-mode/v1",
"embedding_model": "text-embedding-v4",
"embedding_dimensions": 1024,
"timeout": 20,
"proxy": "",
},
"vLLM Rerank": {
"id": "vllm_rerank",
"type": "vllm_rerank",
Expand Down
4 changes: 4 additions & 0 deletions astrbot/core/provider/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,10 @@ def dynamic_import_provider(self, type: str) -> None:
from .sources.ollama_embedding_source import (
OllamaEmbeddingProvider as OllamaEmbeddingProvider,
)
case "dashscope_embedding":
from .sources.dashscope_embedding_source import (
DashscopeEmbeddingProvider as DashscopeEmbeddingProvider,
)
case "vllm_rerank":
from .sources.vllm_rerank_source import (
VLLMRerankProvider as VLLMRerankProvider,
Expand Down
88 changes: 88 additions & 0 deletions astrbot/core/provider/sources/dashscope_embedding_source.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import httpx
from openai import AsyncOpenAI

from astrbot import logger

from ..entities import ProviderType
from ..provider import EmbeddingProvider
from ..register import register_provider_adapter


@register_provider_adapter(
"dashscope_embedding",
"DashScope text-embedding-v4 Embedding Provider",
provider_type=ProviderType.EMBEDDING,
)
class DashscopeEmbeddingProvider(EmbeddingProvider):
def __init__(self, provider_config: dict, provider_settings: dict) -> None:
super().__init__(provider_config, provider_settings)
proxy = provider_config.get("proxy", "")
provider_id = provider_config.get("id", "unknown_id")
http_client = None
if proxy:
logger.info(f"[DashScope Embedding] {provider_id} Using proxy: {proxy}")
http_client = httpx.AsyncClient(proxy=proxy)
api_base = (
provider_config.get(
"embedding_api_base",
"https://dashscope.aliyuncs.com/compatible-mode/v1",
)
.strip()
.removesuffix("/")
.removesuffix("/embeddings")
)
if api_base and not api_base.endswith("/v1") and not api_base.endswith("/v4"):
api_base = api_base + "/v1"
logger.info(f"[DashScope Embedding] {provider_id} Using API Base: {api_base}")
self.client = AsyncOpenAI(
api_key=provider_config.get("embedding_api_key"),
base_url=api_base,
timeout=int(provider_config.get("timeout", 20)),
http_client=http_client,
)
self.model = provider_config.get("embedding_model", "text-embedding-v4")

async def get_embedding(self, text: str) -> list[float]:
kwargs = self._embedding_kwargs()
embedding = await self.client.embeddings.create(
input=text,
model=self.model,
**kwargs,
)
if not embedding.data:
raise Exception("DashScope API returned no embedding data.")
return embedding.data[0].embedding

async def get_embeddings(self, text: list[str]) -> list[list[float]]:
kwargs = self._embedding_kwargs()
embeddings = await self.client.embeddings.create(
input=text,
model=self.model,
**kwargs,
)
return [item.embedding for item in embeddings.data]

def _embedding_kwargs(self) -> dict:
kwargs = {}
if "embedding_dimensions" in self.provider_config:
try:
kwargs["dimensions"] = int(self.provider_config["embedding_dimensions"])
except (ValueError, TypeError):
logger.warning(
f"embedding_dimensions in embedding configs is not a valid integer: '{self.provider_config['embedding_dimensions']}', ignored."
)
return kwargs

def get_dim(self) -> int:
if "embedding_dimensions" in self.provider_config:
try:
return int(self.provider_config["embedding_dimensions"])
except (ValueError, TypeError):
logger.warning(
f"embedding_dimensions in embedding configs is not a valid integer: '{self.provider_config['embedding_dimensions']}', ignored."
)
return 1024

async def terminate(self):
if self.client:
await self.client.close()
Original file line number Diff line number Diff line change
Expand Up @@ -1321,6 +1321,9 @@
"gemini_embedding": {
"hint": "Gemini Embedding does not require manually adding /v1beta."
},
"dashscope_embedding": {
"hint": "text-embedding-v4 supports multiple dimensions: 64, 128, 256, 512, 768, 1024 (default), 1536, 2048. API base defaults to DashScope compatible mode."
},
"volcengine_cluster": {
"description": "Volcengine cluster",
"hint": "For voice cloning models, choose volcano_icl or volcano_icl_concurr; default is volcano_tts."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1318,6 +1318,9 @@
"gemini_embedding": {
"hint": "Gemini Embedding не требует ручного добавления /v1beta."
},
"dashscope_embedding": {
"hint": "text-embedding-v4 поддерживает несколько размеров: 64, 128, 256, 512, 768, 1024 (по умолчанию), 1536, 2048. API base по умолчанию использует совместимый режим DashScope."
},
"volcengine_cluster": {
"description": "Кластер Volcengine",
"hint": "Для моделей клонирования голоса выберите volcano_icl или volcano_icl_concurr; по умолчанию volcano_tts."
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1323,6 +1323,9 @@
"gemini_embedding": {
"hint": "Gemini Embedding 无需手动添加 /v1beta。"
},
"dashscope_embedding": {
"hint": "text-embedding-v4 支持多种维度: 64、128、256、512、768、1024(默认)、1536、2048。API Base 默认使用 DashScope 兼容模式。"
},
"volcengine_cluster": {
"description": "火山引擎集群",
"hint": "若使用语音复刻大模型,可选volcano_icl或volcano_icl_concurr,默认使用volcano_tts"
Expand Down