【AI 工程化第八篇】Spring AI 多模型路由实战:DeepSeek、通义、Kimi、OpenAI 如何统一接入和自动切换

【AI 工程化第八篇】Spring AI 多模型路由实战:DeepSeek、通义、Kimi、OpenAI 如何统一接入和自动切换

系列定位:

第一篇:Agent 服务骨架。

第二篇:RAG 知识库。

第三篇:MCP / Tool Calling。

第四篇:线上可观测。

第五篇:生产治理。

第六篇:多租户知识库与数据安全。

第七篇:RAG 评测闭环。

第八篇:多模型统一接入、动态路由、自动降级和成本控制。

技术栈:Java 17 · Spring Boot 4.1.x / 3.5.x · Spring AI 2.0.x · PostgreSQL · Redis · Resilience4j

适用场景:企业 AI 网关、多模型平台、智能客服、RAG 问答、Agent 编排、多租户 SaaS

阅读前置:建议看过第五篇"生产治理"和第七篇"RAG 评测"


为什么企业 AI 应用不能只接一个模型

很多团队第一版 AI 应用会这样写:

yaml 复制代码
spring:
  ai:
    openai:
      api-key: ${OPENAI_API_KEY}
      chat:
        options:
          model: gpt-4.1-mini

这没问题,能快速跑通。

但上线后很快会遇到这些问题:

text 复制代码
主模型限流了,业务接口全挂
客服高频问答用贵模型,成本太高
复杂工单用便宜模型,答案质量不稳定
国内外模型延迟差异大
某个模型工具调用能力强,另一个模型结构化输出更稳
不同租户买的套餐不同,应该路由到不同模型

所以生产级 AI 应用一定要有"模型路由层"。

它要解决的是:

text 复制代码
同一套业务代码,如何统一接 DeepSeek、通义、Kimi、OpenAI?
不同场景如何自动选择模型?
主模型失败后如何降级?
如何按租户、成本、延迟、质量做路由?
如何记录每次路由原因,方便排查和计费?

一、先看最终效果

业务代码只关心"我要一次聊天调用":

java 复制代码
ChatResponse response = modelGateway.chat(ModelGatewayRequest.builder()
        .tenantId("tenant_a")
        .userId("10001")
        .scene("customer-service")
        .riskLevel("LOW")
        .message("超过7天还能退货吗?")
        .build());

真正调用哪个模型,由路由层决定:

json 复制代码
{
  "selectedProvider": "deepseek",
  "selectedModel": "deepseek-chat",
  "routeReason": "低风险客服问答,优先使用性价比模型",
  "fallback": false,
  "promptTokens": 1280,
  "completionTokens": 210,
  "costMillis": 1830
}

如果主模型失败,路由层自动降级:

json 复制代码
{
  "selectedProvider": "openai",
  "selectedModel": "gpt-4.1-mini",
  "routeReason": "deepseek 连续失败触发熔断,切换 fallback 模型",
  "fallback": true
}

业务层不需要知道背后细节。

这就是模型网关的价值。


二、多模型路由的核心原则

不要把"选模型"写死在 Controller 或 Service 里。

应该抽象成一个独立的模型治理层:

text 复制代码
业务场景 -> 路由策略 -> 模型提供商 -> ChatModel -> ChatClient -> 观测审计

路由决策至少考虑 6 个维度:

维度 示例
场景 客服、RAG、代码生成、工单总结、工具调用
风险 低风险咨询、高风险金融/合同/退款
租户套餐 免费版、专业版、企业版
成本预算 今日 Token 是否超额
实时状态 模型是否熔断、是否限流
能力差异 工具调用、长上下文、结构化输出、多模态

推荐第一版规则:

text 复制代码
低风险高频:便宜模型
高风险决策:强模型
结构化输出:稳定模型
工具调用:工具能力强的模型
主模型失败:fallback 模型
预算不足:降级模型

三、整体架构设计

3.1 功能模块图

text 复制代码
┌────────────────────────────────────────────────────────────────────┐
│                         业务应用层                                  │
│    RAG 问答 · 智能客服 · 工单总结 · Agent 工具调用 · 代码助手          │
└─────────────────────────────┬──────────────────────────────────────┘
                              │
┌─────────────────────────────▼──────────────────────────────────────┐
│                         Model Gateway                               │
│                                                                    │
│  ModelRouter                                                       │
│    - 按场景 / 风险 / 租户 / 预算选择模型                              │
│                                                                    │
│  ProviderRegistry                                                  │
│    - OpenAI                                                        │
│    - DeepSeek                                                      │
│    - Tongyi                                                        │
│    - Kimi                                                          │
│                                                                    │
│  Resilience Layer                                                  │
│    - Timeout                                                       │
│    - Retry                                                         │
│    - CircuitBreaker                                                │
│    - Fallback                                                      │
│                                                                    │
│  Observability                                                     │
│    - Token                                                         │
│    - Latency                                                       │
│    - Error Rate                                                    │
│    - Route Reason                                                  │
└─────────────┬──────────────┬──────────────┬───────────────────────┘
              │              │              │
┌─────────────▼────┐ ┌───────▼───────┐ ┌────▼────────┐
│ OpenAI Compatible │ │ DeepSeek API   │ │ Tongyi API  │ ...
│ ChatModel         │ │ ChatModel      │ │ ChatModel   │
└──────────────────┘ └───────────────┘ └─────────────┘

3.2 路由时序图

text 复制代码
业务服务          ModelGateway       ModelRouter       ProviderClient       LLM Provider
  │                  │                  │                   │                 │
  │ chat(request) ──▶│                  │                   │                 │
  │                  │ 预估 Token        │                   │                 │
  │                  │ 检查租户预算       │                   │                 │
  │                  │─────────────────▶│                   │                 │
  │                  │◀─────────────────│ route result       │                 │
  │                  │──────────────────────────────────────▶│                 │
  │                  │                  │                   │ call model ─────▶│
  │                  │                  │                   │◀────────────────│
  │                  │ 记录路由日志       │                   │                 │
  │                  │ 记录 Token/耗时    │                   │                 │
  │◀─────────────────│                  │                   │                 │

四、核心表结构

4.1 模型提供商表

sql 复制代码
CREATE TABLE t_ai_model_provider (
    id              BIGSERIAL PRIMARY KEY,
    provider_code   VARCHAR(64)  NOT NULL UNIQUE,
    provider_name   VARCHAR(128) NOT NULL,
    api_base_url    VARCHAR(255) NOT NULL,
    api_key_ref     VARCHAR(128) NOT NULL,
    protocol_type   VARCHAR(32)  NOT NULL DEFAULT 'OPENAI_COMPATIBLE',
    enabled         BOOLEAN      NOT NULL DEFAULT TRUE,
    priority        INT          NOT NULL DEFAULT 100,
    create_time     TIMESTAMP    NOT NULL DEFAULT now(),
    update_time     TIMESTAMP    NOT NULL DEFAULT now()
);

4.2 模型能力表

sql 复制代码
CREATE TABLE t_ai_model_catalog (
    id                    BIGSERIAL PRIMARY KEY,
    provider_code          VARCHAR(64) NOT NULL,
    model_code             VARCHAR(128) NOT NULL,
    model_name             VARCHAR(128) NOT NULL,
    context_window         INT,
    support_tool_calling   BOOLEAN     DEFAULT FALSE,
    support_json_output    BOOLEAN     DEFAULT FALSE,
    support_vision         BOOLEAN     DEFAULT FALSE,
    input_price_per_1k     NUMERIC(12, 6),
    output_price_per_1k    NUMERIC(12, 6),
    avg_latency_ms         BIGINT,
    enabled                BOOLEAN     DEFAULT TRUE,
    create_time            TIMESTAMP   DEFAULT now(),
    update_time            TIMESTAMP   DEFAULT now(),
    UNIQUE(provider_code, model_code)
);

4.3 路由规则表

sql 复制代码
CREATE TABLE t_ai_model_route_rule (
    id              BIGSERIAL PRIMARY KEY,
    route_key       VARCHAR(64)  NOT NULL UNIQUE,
    scene           VARCHAR(64)  NOT NULL,
    tenant_plan     VARCHAR(64)  NOT NULL DEFAULT 'DEFAULT',
    risk_level      VARCHAR(32)  NOT NULL DEFAULT 'LOW',
    primary_provider VARCHAR(64) NOT NULL,
    primary_model   VARCHAR(128) NOT NULL,
    fallback_provider VARCHAR(64),
    fallback_model  VARCHAR(128),
    cheap_provider  VARCHAR(64),
    cheap_model     VARCHAR(128),
    gray_percent    INT         NOT NULL DEFAULT 0,
    enabled         BOOLEAN     NOT NULL DEFAULT TRUE,
    create_time     TIMESTAMP   DEFAULT now(),
    update_time     TIMESTAMP   DEFAULT now()
);

4.4 路由审计表

sql 复制代码
CREATE TABLE t_ai_model_route_log (
    id              BIGSERIAL PRIMARY KEY,
    trace_id        VARCHAR(64)  NOT NULL,
    tenant_id       VARCHAR(64)  NOT NULL,
    user_id         VARCHAR(64),
    scene           VARCHAR(64)  NOT NULL,
    selected_provider VARCHAR(64) NOT NULL,
    selected_model  VARCHAR(128) NOT NULL,
    route_reason    VARCHAR(500),
    fallback        BOOLEAN      DEFAULT FALSE,
    prompt_tokens   INT          DEFAULT 0,
    completion_tokens INT        DEFAULT 0,
    success         BOOLEAN      DEFAULT TRUE,
    error_msg       VARCHAR(500),
    cost_millis     BIGINT       DEFAULT 0,
    create_time     TIMESTAMP    DEFAULT now()
);

CREATE INDEX idx_model_route_trace ON t_ai_model_route_log(trace_id);
CREATE INDEX idx_model_route_scene_time ON t_ai_model_route_log(scene, create_time DESC);

五、配置多个模型提供商

Spring AI 的 OpenAI Chat Model 支持配置 base-url、api-key、model 等参数。很多厂商提供 OpenAI 兼容协议时,都可以用这套方式统一接入。

注意:不同厂商的 base-url、模型名、鉴权方式会变,请以厂商官方文档为准。本文用环境变量占位,避免把密钥写进配置。

yaml 复制代码
ai:
  providers:
    openai:
      base-url: ${OPENAI_BASE_URL:https://api.openai.com}
      api-key: ${OPENAI_API_KEY}
      default-model: gpt-4.1-mini

    deepseek:
      base-url: ${DEEPSEEK_BASE_URL}
      api-key: ${DEEPSEEK_API_KEY}
      default-model: deepseek-chat

    tongyi:
      base-url: ${TONGYI_BASE_URL}
      api-key: ${TONGYI_API_KEY}
      default-model: qwen-plus

    kimi:
      base-url: ${KIMI_BASE_URL}
      api-key: ${KIMI_API_KEY}
      default-model: kimi-k2

业务代码不要直接读取这些配置。

统一通过 ModelProviderProperties 管理:

java 复制代码
import org.springframework.boot.context.properties.ConfigurationProperties;

import java.util.Map;

@ConfigurationProperties(prefix = "ai")
public record ModelProviderProperties(
        Map<String, ProviderConfig> providers
) {
    public record ProviderConfig(
            String baseUrl,
            String apiKey,
            String defaultModel
    ) {
    }
}

六、请求和路由对象

java 复制代码
import lombok.Builder;

@Builder
public record ModelGatewayRequest(
        String traceId,
        String tenantId,
        String userId,
        String scene,
        String riskLevel,
        String systemPrompt,
        String message,
        int estimatedPromptTokens,
        boolean requireToolCalling,
        boolean requireJsonOutput
) {
}

@Builder
public record ModelRouteResult(
        String providerCode,
        String modelCode,
        String reason,
        boolean fallback,
        boolean cheapMode
) {
}

public record ModelGatewayResponse(
        String content,
        String providerCode,
        String modelCode,
        String routeReason,
        boolean fallback,
        int promptTokens,
        int completionTokens,
        long costMillis
) {
}

七、ModelRouter:模型路由策略

java 复制代码
import org.springframework.stereotype.Service;

@Service
public class ModelRouter {

    private final TenantBudgetService tenantBudgetService;
    private final ModelHealthService modelHealthService;
    private final ModelRouteRuleRepository routeRuleRepository;

    public ModelRouter(TenantBudgetService tenantBudgetService,
                       ModelHealthService modelHealthService,
                       ModelRouteRuleRepository routeRuleRepository) {
        this.tenantBudgetService = tenantBudgetService;
        this.modelHealthService = modelHealthService;
        this.routeRuleRepository = routeRuleRepository;
    }

    /**
     * 路由顺序:
     * 1. 高风险场景优先强模型
     * 2. 工具调用 / JSON 输出选择能力匹配模型
     * 3. 租户预算不足时降级便宜模型
     * 4. 主模型熔断时切 fallback
     */
    public ModelRouteResult route(ModelGatewayRequest request) {
        ModelRouteRule rule = routeRuleRepository.findMatched(
                request.scene(),
                request.riskLevel(),
                request.tenantId()
        );

        if (!tenantBudgetService.hasEnoughBudget(request.tenantId(), request.estimatedPromptTokens())) {
            return ModelRouteResult.builder()
                    .providerCode(rule.cheapProvider())
                    .modelCode(rule.cheapModel())
                    .cheapMode(true)
                    .reason("租户预算不足,降级到低成本模型")
                    .build();
        }

        if (!modelHealthService.isHealthy(rule.primaryProvider(), rule.primaryModel())) {
            return ModelRouteResult.builder()
                    .providerCode(rule.fallbackProvider())
                    .modelCode(rule.fallbackModel())
                    .fallback(true)
                    .reason("主模型不可用或已熔断,切换 fallback 模型")
                    .build();
        }

        if ("HIGH".equalsIgnoreCase(request.riskLevel())) {
            return ModelRouteResult.builder()
                    .providerCode(rule.primaryProvider())
                    .modelCode(rule.primaryModel())
                    .reason("高风险场景使用主力模型")
                    .build();
        }

        if (request.requireToolCalling()) {
            ModelCapability capability = routeRuleRepository.findBestToolCallingModel(request.scene());
            return ModelRouteResult.builder()
                    .providerCode(capability.providerCode())
                    .modelCode(capability.modelCode())
                    .reason("当前请求需要工具调用,选择工具调用能力更稳定的模型")
                    .build();
        }

        return ModelRouteResult.builder()
                .providerCode(rule.cheapProvider())
                .modelCode(rule.cheapModel())
                .cheapMode(true)
                .reason("低风险高频场景使用性价比模型")
                .build();
    }
}

这个路由策略很朴素,但足够好用。

等你有了第七篇里的评测体系,就可以把路由从"规则驱动"升级成"数据驱动":

text 复制代码
不同模型在不同场景的 passRate
不同模型的平均成本
不同模型的 P95 延迟
不同模型的工具调用失败率

八、ProviderRegistry:统一创建 ChatClient

Spring AI 的 ChatClient 是对 ChatModel 的高级封装,支持同步和流式调用,也支持 system/user prompt、options、advisors、tools 等能力。

这里我们用 providerCode + modelCode 动态拿到对应客户端。

java 复制代码
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.model.ChatModel;
import org.springframework.ai.openai.OpenAiChatModel;
import org.springframework.ai.openai.api.OpenAiApi;
import org.springframework.stereotype.Component;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class ChatClientRegistry {

    private final ModelProviderProperties properties;
    private final Map<String, ChatClient> cache = new ConcurrentHashMap<>();

    public ChatClientRegistry(ModelProviderProperties properties) {
        this.properties = properties;
    }

    public ChatClient get(String providerCode) {
        return cache.computeIfAbsent(providerCode, this::createClient);
    }

    private ChatClient createClient(String providerCode) {
        ModelProviderProperties.ProviderConfig config = properties.providers().get(providerCode);
        if (config == null) {
            throw new BizException("模型提供商不存在:" + providerCode);
        }

        OpenAiApi openAiApi = OpenAiApi.builder()
                .baseUrl(config.baseUrl())
                .apiKey(config.apiKey())
                .build();

        ChatModel chatModel = OpenAiChatModel.builder()
                .openAiApi(openAiApi)
                .build();

        return ChatClient.builder(chatModel).build();
    }
}

如果你的项目不想运行时创建,也可以在配置类里显式注册多个 ChatClient Bean。

但当模型提供商很多、配置要热更新时,Registry 更灵活。


九、ModelGateway:统一调用入口

java 复制代码
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.metadata.Usage;
import org.springframework.ai.chat.model.ChatResponse;
import org.springframework.ai.openai.OpenAiChatOptions;
import org.springframework.stereotype.Service;

import java.time.Duration;
import java.time.Instant;

@Service
public class ModelGateway {

    private static final Logger log = LoggerFactory.getLogger(ModelGateway.class);

    private final ModelRouter modelRouter;
    private final ChatClientRegistry chatClientRegistry;
    private final ModelRouteAuditService auditService;
    private final TenantBudgetService tenantBudgetService;

    public ModelGateway(ModelRouter modelRouter,
                        ChatClientRegistry chatClientRegistry,
                        ModelRouteAuditService auditService,
                        TenantBudgetService tenantBudgetService) {
        this.modelRouter = modelRouter;
        this.chatClientRegistry = chatClientRegistry;
        this.auditService = auditService;
        this.tenantBudgetService = tenantBudgetService;
    }

    public ModelGatewayResponse chat(ModelGatewayRequest request) {
        Instant start = Instant.now();
        ModelRouteResult route = modelRouter.route(request);
        Usage usage = null;
        boolean success = false;
        String errorMsg = null;

        try {
            ChatClient chatClient = chatClientRegistry.get(route.providerCode());
            ChatResponse response = chatClient.prompt()
                    .system(request.systemPrompt())
                    .user(request.message())
                    .options(OpenAiChatOptions.builder()
                            .model(route.modelCode())
                            .temperature(0.2)
                            .maxTokens(1200)
                            .build())
                    .call()
                    .chatResponse();

            usage = response.getMetadata().getUsage();
            success = true;

            int totalTokens = usage == null ? 0 : usage.getTotalTokens();
            tenantBudgetService.consume(request.tenantId(), totalTokens);

            return new ModelGatewayResponse(
                    response.getResult().getOutput().getText(),
                    route.providerCode(),
                    route.modelCode(),
                    route.reason(),
                    route.fallback(),
                    usage == null ? 0 : usage.getPromptTokens(),
                    usage == null ? 0 : usage.getCompletionTokens(),
                    Duration.between(start, Instant.now()).toMillis()
            );
        } catch (Exception ex) {
            errorMsg = ex.getMessage();
            log.error("模型网关调用失败 traceId={}, provider={}, model={}",
                    request.traceId(), route.providerCode(), route.modelCode(), ex);
            throw new BizException("AI 模型调用失败,请稍后重试");
        } finally {
            auditService.save(ModelRouteAuditCommand.builder()
                    .traceId(request.traceId())
                    .tenantId(request.tenantId())
                    .userId(request.userId())
                    .scene(request.scene())
                    .providerCode(route.providerCode())
                    .modelCode(route.modelCode())
                    .routeReason(route.reason())
                    .fallback(route.fallback())
                    .promptTokens(usage == null ? 0 : usage.getPromptTokens())
                    .completionTokens(usage == null ? 0 : usage.getCompletionTokens())
                    .success(success)
                    .errorMsg(errorMsg)
                    .costMillis(Duration.between(start, Instant.now()).toMillis())
                    .build());
        }
    }
}

到这里,业务层已经不需要知道具体厂商。

text 复制代码
RAG 服务调用 ModelGateway
MCP Agent 调用 ModelGateway
客服助手调用 ModelGateway
评测 Runner 调用 ModelGateway

十、自动 fallback:不要只靠 catch

上面的代码失败后直接抛异常,真实生产还要做 fallback。

推荐流程:

text 复制代码
主模型失败
  -> 标记一次失败
  -> 如果是可重试错误,有限重试
  -> 如果仍失败,切 fallback 模型
  -> fallback 也失败,返回降级话术

示例:

java 复制代码
public ModelGatewayResponse chatWithFallback(ModelGatewayRequest request) {
    ModelRouteResult primary = modelRouter.route(request);
    try {
        return doChat(request, primary);
    } catch (Exception primaryEx) {
        modelHealthService.recordFailure(primary.providerCode(), primary.modelCode(), primaryEx);

        ModelRouteResult fallback = modelRouter.fallback(request, primary);
        try {
            return doChat(request, fallback);
        } catch (Exception fallbackEx) {
            modelHealthService.recordFailure(fallback.providerCode(), fallback.modelCode(), fallbackEx);
            return new ModelGatewayResponse(
                    "当前 AI 服务繁忙,请稍后再试。你也可以换一种问法,或联系人工客服。",
                    fallback.providerCode(),
                    fallback.modelCode(),
                    "主模型和备用模型均失败,返回固定降级话术",
                    true,
                    0,
                    0,
                    0
            );
        }
    }
}

不要无限 fallback。

否则会出现:

text 复制代码
主模型失败 -> 备用模型失败 -> 第三个模型失败 -> 第四个模型失败

用户等了很久,成本也烧了很多。

建议最多 1 次 fallback。


十一、前端如何透出模型信息

普通用户不需要看到模型细节。

但管理后台要能看到:

ts 复制代码
export interface ModelRouteInfo {
  providerCode: string
  modelCode: string
  routeReason: string
  fallback: boolean
  promptTokens: number
  completionTokens: number
  costMillis: number
}

后台排查时可以展示:

text 复制代码
模型:deepseek / deepseek-chat
路由原因:低风险客服问答,优先使用性价比模型
Fallback:否
Token:1490
耗时:1830ms

这样当用户反馈"今天回答变差了",你能快速判断是不是路由到了便宜模型。


十二、生产环境最容易踩的坑

12.1 所有场景都用一个模型

这是最贵也最不稳定的做法。

建议按场景拆:

text 复制代码
客服 FAQ:低成本模型
合同审阅:强模型
工具调用:Tool Calling 稳定模型
结构化抽取:JSON 输出稳定模型
摘要生成:低温度、低成本模型

12.2 fallback 模型能力不兼容

主模型支持工具调用,fallback 模型不支持。

结果:

text 复制代码
主模型失败后 fallback 成功了
但工具调用能力没了
Agent 行为变了

路由时必须检查能力:

text 复制代码
support_tool_calling
support_json_output
context_window

12.3 不记录路由原因

没有路由审计,就无法解释:

text 复制代码
为什么这个用户走了贵模型?
为什么这个租户被降级?
为什么今天错误率升高?

12.4 模型名写死在 Prompt 或业务代码里

模型名应该属于配置和路由层。

Prompt 里不要写:

text 复制代码
你正在使用 gpt-4.1-mini

否则切模型时会出现不一致。

12.5 只看成本,不看评测指标

降成本很容易:

text 复制代码
全部路由到便宜模型

但答案质量可能直接崩。

正确做法:

text 复制代码
成本下降
RAG Eval passRate 不下降
用户点踩率不升高
P95 延迟可接受

十三、总结

这篇文章把模型接入从"单模型配置"升级到了"多模型网关":

  1. 生产级 AI 应用不应该只依赖一个模型。
  2. 多模型路由要按场景、风险、租户、预算、能力和实时健康状态决策。
  3. 业务层只调用 ModelGateway,不直接依赖具体厂商。
  4. 路由原因、Token、耗时、成功失败必须落审计表。
  5. fallback 不能无限重试,最多 1 次备用模型更稳。
  6. 多模型路由必须结合第七篇的 RAG Eval,用数据证明质量没有下降。

下一篇我准备写:

Spring AI Prompt 模板与版本治理实战:System Prompt、Few-shot、变量注入、灰度发布和安全防注入

如果你想要完整工程骨架,可以在评论区留一句:

text 复制代码
多模型

我会继续把这个系列写完整。


可选标题

  1. Spring AI 多模型路由实战:DeepSeek、通义、Kimi、OpenAI 统一接入
  2. Java AI Agent 第八篇:从单模型调用升级到多模型网关
  3. 企业 AI 应用如何自动切模型:Spring AI 模型路由、降级和成本控制
  4. Spring Boot 多模型网关:让 RAG 和 Agent 自动选择最合适的大模型

推荐标签

Spring AI 多模型路由 AI Gateway DeepSeek 通义千问 Kimi OpenAI Java

参考资料

相关推荐
Sarvartha19 小时前
Lambda 表达式和函数式接口
java·开发语言
爱编程的小白L19 小时前
2027 计算机毕业设计选题汇总|深度学习专项(2027最新)
人工智能·深度学习·课程设计
计算机毕业设计杰瑞19 小时前
【计算机毕设精品】基于SpringBoot的一体化教务与学业质量管理系统的设计与实现,附源码_增删改查_java项目_可完美运行部署_网站项目
java·spring boot·课程设计
逸模19 小时前
BIM在连锁餐饮装修中的应用:不只是画三维图
大数据·数据库·人工智能·物联网·建模
Zooproxy全球IP代理19 小时前
住宅IP在AI行业中的技术应用:数据采集基础设施的工程实践
人工智能·网络协议·tcp/ip
Rocky Ding*19 小时前
MOSS-VL技术原理深度解析:让视觉流持续进入生成过程,实时 Agent 才有架构基础
论文阅读·人工智能·深度学习·机器学习·aigc·多模态·ai-native
一木 之林19 小时前
Dify学习笔记 01 · 平台入门与实战:部署、五类应用、RAG与MCP(第1-16集)
人工智能·笔记·学习·计算机视觉
茵Cindy19 小时前
AI+HR智能体架构如何落地?从入口到生态底座的工程实现
人工智能·架构·ai+hr