fix(deploy): drop DASHSCOPE_API_KEY requirement so Docker boots with no LLM key configured (#99)

This commit is contained in:
matevip 2026-05-11 20:33:44 +08:00
parent a1ca7ab534
commit 08fcab12d1
7 changed files with 38 additions and 10 deletions

View File

@ -77,7 +77,10 @@ services:
DB_NAME: ${DB_NAME:-mateclaw}
DB_USERNAME: ${DB_USERNAME:-mateclaw}
DB_PASSWORD: ${DB_PASSWORD:?DB_PASSWORD is required in .env}
DASHSCOPE_API_KEY: ${DASHSCOPE_API_KEY:-}
# LLM provider keys (DashScope / OpenAI / Anthropic / DeepSeek / Kimi / …) are
# NOT configured via env vars. After startup, add providers in the admin UI:
# Settings → Models → Add Provider
# Keys are stored in mate_model_provider and hot-reloaded.
SERPER_API_KEY: ${SERPER_API_KEY:-}
JWT_SECRET: ${JWT_SECRET:-}
MATECLAW_CORS_ALLOWED_ORIGINS: ${MATECLAW_CORS_ALLOWED_ORIGINS:-}

View File

@ -15,13 +15,19 @@ import org.springframework.scheduling.annotation.EnableScheduling;
* @author MateClaw Team
*/
@SpringBootApplication(exclude = {
// 禁用 Spring AI MCP Client 自动配置 McpClientManager 自行管理生命周期
// Disable Spring AI MCP Client auto-configuration (lifecycle owned by McpClientManager).
org.springframework.ai.mcp.client.common.autoconfigure.McpClientAutoConfiguration.class,
org.springframework.ai.mcp.client.common.autoconfigure.McpToolCallbackAutoConfiguration.class,
org.springframework.ai.mcp.client.common.autoconfigure.StdioTransportAutoConfiguration.class,
org.springframework.ai.mcp.client.common.autoconfigure.annotations.McpClientAnnotationScannerAutoConfiguration.class,
org.springframework.ai.mcp.client.httpclient.autoconfigure.SseHttpClientTransportAutoConfiguration.class,
org.springframework.ai.mcp.client.httpclient.autoconfigure.StreamableHttpHttpClientTransportAutoConfiguration.class,
// DashScopeAgent is the Bailian "Application Agent" (Bailian-hosted prompt+tool app),
// not the chat model. We don't use it model configuration is admin-UI driven and
// built by AgentDashScopeChatModelBuilder. Its auto-config strictly requires
// spring.ai.dashscope.api-key to be non-empty at startup, which makes the whole
// ApplicationContext fail when users deploy via Docker without setting the key.
com.alibaba.cloud.ai.autoconfigure.dashscope.DashScopeAgentAutoConfiguration.class,
})
@EnableScheduling
@MapperScan("vip.mate.**.repository")

View File

@ -172,7 +172,7 @@ public class AgentDashScopeChatModelBuilder implements ChatModelBuilder {
}
if (!modelProviderService.hasUsableApiKey(apiKey)) {
throw new MateClawException("err.agent.dashscope_key_missing",
"DashScope API Key 未配置,请在模型设置中填写 dashscope 的 API Key或设置 DASHSCOPE_API_KEY 环境变量");
"DashScope API Key 未配置,请在「设置 → 模型 → 添加供应商」中为 dashscope 填写 API Key");
}
builder.apiKey(apiKey.trim());

View File

@ -551,7 +551,16 @@ public class ModelProviderService {
return false;
}
String normalized = apiKey.trim();
// Reject masked display values (the UI sends "********" when the user
// didn't re-type the key) and known placeholder sentinels without this
// check, the chat / embedding fallback chain happily forwards the
// placeholder to the LLM endpoint, which then returns a 401 at request
// time. "configure-in-admin-ui" is the application.yml default that
// keeps DashScopeChatAutoConfiguration happy at startup when no env var
// is set; "your-*-api-key-here" are legacy sentinels from earlier
// .env.example / application.yml versions.
return !normalized.contains("*")
&& !"configure-in-admin-ui".equalsIgnoreCase(normalized)
&& !"your-dashscope-api-key-here".equalsIgnoreCase(normalized)
&& !"your-api-key-here".equalsIgnoreCase(normalized);
}

View File

@ -8,10 +8,11 @@ import vip.mate.llm.service.ModelProviderService;
* DashScope vision provider uses {@code qwen-vl-max} via the
* OpenAI-compatible endpoint at {@code /compatible-mode/v1/chat/completions}.
*
* <p>Default for the Chinese cloud rollout: API keys are typically
* available (DASHSCOPE_API_KEY is mandatory for the rest of the
* platform) and per-image cost is the lowest of the supported vendors,
* so this provider sits at the front of the auto-detect chain.
* <p>Sits at the front of the auto-detect chain when a DashScope provider row
* is configured in the admin UI: per-image cost is the lowest of the supported
* vendors, and DashScope is the most common first provider added on the
* Chinese cloud rollout. Falls back to the next provider in the chain when no
* DashScope API key is available.
*/
@Component
public class DashScopeVisionProvider extends OpenAiCompatibleVisionProvider {

View File

@ -67,10 +67,19 @@ spring:
enabled: ${H2_CONSOLE_ENABLED:false}
path: /h2-console
# Spring AI Alibaba (DashScope) - Spring AI Alibaba 1.1.x 配置路径
# Spring AI Alibaba (DashScope) — Spring AI Alibaba 1.1.x configuration path.
#
# The api-key here is only consumed by Spring AI Alibaba's auto-configured beans
# as a *fallback*. The real source of truth for every provider/key/model is the
# admin UI ("Settings → Models", persisted in mate_model_provider /
# mate_model_config); AgentDashScopeChatModelBuilder resolves the key per-request
# from the provider row first, only falling back to this property when the row
# is incomplete. The placeholder default keeps DashScopeChatAutoConfiguration
# happy at startup when no env var is set (Docker / fresh install) — leave it
# alone unless you know what you're doing.
ai:
dashscope:
api-key: ${DASHSCOPE_API_KEY:your-dashscope-api-key-here}
api-key: ${DASHSCOPE_API_KEY:configure-in-admin-ui}
chat:
options:
model: qwen-max

View File

@ -7,7 +7,7 @@
## 前置条件
1. 后端启动:`cd mateclaw-server && mvn spring-boot:run`(需设置 `DASHSCOPE_API_KEY`
1. 后端启动:`cd mateclaw-server && mvn spring-boot:run`(零环境变量,启动后到「设置 → 模型」加 LLM 供应商
2. 前端启动:`cd mateclaw-ui && pnpm dev`
3. 访问 http://localhost:5173登录