diff --git a/astrbot/core/config/default.py b/astrbot/core/config/default.py index c03027f3b2..4930bc9caa 100644 --- a/astrbot/core/config/default.py +++ b/astrbot/core/config/default.py @@ -1463,6 +1463,7 @@ class ChatProviderTemplate(TypedDict): "type": "openai_embedding", "provider": "openai", "provider_type": "embedding", + "hint": "provider_group.provider.openai_embedding.hint", "enable": True, "embedding_api_key": "", "embedding_api_base": "", @@ -1476,6 +1477,7 @@ class ChatProviderTemplate(TypedDict): "type": "gemini_embedding", "provider": "google", "provider_type": "embedding", + "hint": "provider_group.provider.gemini_embedding.hint", "enable": True, "embedding_api_key": "", "embedding_api_base": "", @@ -2192,9 +2194,9 @@ class ChatProviderTemplate(TypedDict): "type": "string", }, "proxy": { - "description": "代理地址", + "description": "provider_group.provider.proxy.description", "type": "string", - "hint": "HTTP/HTTPS 代理地址,格式如 http://127.0.0.1:7890。仅对该提供商的 API 请求生效,不影响 Docker 内网通信。", + "hint": "provider_group.provider.proxy.hint", }, "model": { "description": "模型 ID", diff --git a/astrbot/core/provider/sources/openai_embedding_source.py b/astrbot/core/provider/sources/openai_embedding_source.py index b686a6ee6b..8bf92ef4d5 100644 --- a/astrbot/core/provider/sources/openai_embedding_source.py +++ b/astrbot/core/provider/sources/openai_embedding_source.py @@ -23,12 +23,16 @@ def __init__(self, provider_config: dict, provider_settings: dict) -> None: if proxy: logger.info(f"[OpenAI Embedding] 使用代理: {proxy}") http_client = httpx.AsyncClient(proxy=proxy) + api_base = provider_config.get("embedding_api_base", "").strip() + if not api_base: + api_base = "https://api.openai.com/v1" + else: + api_base = api_base.removesuffix("/") + if not api_base.endswith("/v1"): + api_base = f"{api_base}/v1" self.client = AsyncOpenAI( api_key=provider_config.get("embedding_api_key"), - base_url=provider_config.get( - "embedding_api_base", - "https://api.openai.com/v1", - ), + base_url=api_base, timeout=int(provider_config.get("timeout", 20)), http_client=http_client, ) diff --git a/astrbot/dashboard/routes/config.py b/astrbot/dashboard/routes/config.py index 6d60fb6de0..08b8c12b83 100644 --- a/astrbot/dashboard/routes/config.py +++ b/astrbot/dashboard/routes/config.py @@ -754,6 +754,22 @@ async def get_embedding_dim(self): if not provider_type: return Response().error("provider_config 缺少 type 字段").__dict__ + # 首次添加某类提供商时,provider_cls_map 可能尚未注册该适配器 + if provider_type not in provider_cls_map: + try: + self.core_lifecycle.provider_manager.dynamic_import_provider( + provider_type, + ) + except ImportError: + logger.error(traceback.format_exc()) + return ( + Response() + .error( + "提供商适配器加载失败,请检查提供商类型配置或查看服务端日志" + ) + .__dict__ + ) + # 获取对应的 provider 类 if provider_type not in provider_cls_map: return ( @@ -779,7 +795,7 @@ async def get_embedding_dim(self): if inspect.iscoroutinefunction(init_fn): await init_fn() - # 获取嵌入向量维度 + # 通过实际请求验证当前 embedding_dimensions 是否可用 vec = await inst.get_embedding("echo") dim = len(vec) diff --git a/dashboard/src/components/shared/AstrBotConfig.vue b/dashboard/src/components/shared/AstrBotConfig.vue index 12cb0bee1c..bc1c86bdfc 100644 --- a/dashboard/src/components/shared/AstrBotConfig.vue +++ b/dashboard/src/components/shared/AstrBotConfig.vue @@ -48,6 +48,40 @@ const filteredIterable = computed(() => { return rest }) +const providerHint = computed(() => { + const hint = props.iterable?.hint + if (typeof hint !== 'string' || !hint) return '' + + if ( + hint === 'provider_group.provider.openai_embedding.hint' + || hint === 'provider_group.provider.gemini_embedding.hint' + ) { + return '' + } + + return hint +}) + +const getItemHint = (itemKey, itemMeta) => { + if (itemMeta?.hint) return itemMeta.hint + + if (itemKey !== 'embedding_api_base') return '' + + const providerType = props.iterable?.type + if (providerType === 'openai_embedding') { + return getRaw('provider_group.provider.openai_embedding.hint') + ? 'provider_group.provider.openai_embedding.hint' + : '' + } + if (providerType === 'gemini_embedding') { + return getRaw('provider_group.provider.gemini_embedding.hint') + ? 'provider_group.provider.gemini_embedding.hint' + : '' + } + + return '' +} + const dialog = ref(false) const currentEditingKey = ref('') const currentEditingLanguage = ref('json') @@ -153,14 +187,14 @@ function hasVisibleItemsAfter(items, currentIndex) {