Spring AI Alibaba实战:通义千问与Java的完美融合

Spring AI Alibaba实战:通义千问与Java的完美融合

前言

在国产大模型快速发展的今天,通义千问(Qwen)已经成为国内开发者首选的AI模型之一。它有着优秀的中文理解能力、合理的定价,以及与国内合规要求的天然契合。

本文基于我在实际项目中使用Spring AI Alibaba的经验,分享如何在Spring Boot中集成通义千问,以及踩过的那些坑。


一、为什么选择Spring AI Alibaba

1.1 与OpenAI方式的对比

对比项 OpenAI 通义千问(Spring AI Alibaba)
合规要求 数据出境限制 国内合规,数据不出境
中文理解 一般 优秀
API定价 较高 约1/3价格
网络要求 需要代理 国内直连
定制能力 有限 支持企业专属模型

1.2 Spring AI Alibaba的优势

ini 复制代码
Spring AI Alibaba = Spring生态 + 通义千问 + 国内基础设施

核心优势:

  1. 无缝集成:与Spring Boot自动配置完美融合
  2. 类型安全:相比Python,Java的编译期检查能避免很多运行时错误
  3. 企业级特性:支持连接池、熔断、监控等生产级特性
  4. Prompt模板:提供结构化的提示词管理

二、快速开始:10分钟接入通义千问

2.1 获取API密钥

  1. 访问阿里云百炼平台:dashscope.aliyun.com/
  2. 开通通义千问服务
  3. 获取API-KEY(格式:sk-xxxxxxxx

2.2 创建Spring Boot项目

使用Spring Initializr创建项目,选择:

  • Spring Boot 3.3+
  • Java 17+
  • 依赖:Spring Web, Lombok

2.3 添加依赖

xml 复制代码
<!-- pom.xml -->
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>3.3.0</version>
    </parent>
    
    <groupId>com.example</groupId>
    <artifactId>spring-ai-alibaba-demo</artifactId>
    <version>1.0.0</version>
    
    <properties>
        <java.version>17</java.version>
        <spring-ai-alibaba.version>1.0.0-M3</spring-ai-alibaba.version>
    </properties>
    
    <dependencies>
        <!-- Spring Web -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        
        <!-- Spring AI Alibaba -->
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-spring-boot-starter</artifactId>
            <version>${spring-ai-alibaba.version}</version>
        </dependency>
        
        <!-- Lombok -->
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <optional>true</optional>
        </dependency>
        
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>
    
    <repositories>
        <repository>
            <id>spring-milestones</id>
            <name>Spring Milestones</name>
            <url>https://repo.spring.io/milestone</url>
        </repository>
    </repositories>
</project>

2.4 配置application.yml

yaml 复制代码
# application.yml
server:
  port: 8080

spring:
  application:
    name: spring-ai-alibaba-demo
  
  ai:
    alibaba:
      # 从环境变量或配置中心获取,不要硬编码
      api-key: ${ALI_API_KEY:sk-your-key-here}
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      
      chat:
        options:
          # 可选模型:qwen-turbo(快)、qwen-plus(强)、qwen-max(最强)
          model: qwen-plus
          # 温度参数:0=确定性输出,1=创造性输出
          temperature: 0.7
          # 最大生成token数
          max-tokens: 2000
      
      embedding:
        options:
          # 嵌入模型
          model: text-embedding-v4

logging:
  level:
    com.alibaba.cloud.ai: DEBUG
    org.springframework.ai: DEBUG

三、基础功能:ChatClient实战

3.1 最简单的对话

java 复制代码
package com.example.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.stereotype.Service;

@Slf4j
@Service
@RequiredArgsConstructor
public class ChatService {
    
    private final ChatClient chatClient;
    
    /**
     * 构造函数注入ChatClient.Builder
     * Spring会自动配置ChatClient.Builder
     */
    public ChatService(ChatClient.Builder chatClientBuilder) {
        this.chatClient = chatClientBuilder.build();
        log.info("ChatService initialized with ChatClient");
    }
    
    /**
     * 基础对话
     */
    public String chat(String message) {
        log.info("Received message: {}", message);
        String response = chatClient.prompt()
                .user(message)
                .call()
                .content();
        log.info("AI response length: {}", response.length());
        return response;
    }
}

3.2 带系统提示的对话

java 复制代码
/**
 * 带系统提示的对话
 * 系统提示用于设定AI的角色和行为规范
 */
public String chatWithSystemPrompt(String message) {
    return chatClient.prompt()
            .system("你是一个专业的Java技术专家,擅长Spring Boot、微服务架构和性能优化。" +
                    "回答要简洁、准确,尽量给出代码示例。如果涉及代码,请使用Java语言。")
            .user(message)
            .call()
            .content();
}

3.3 流式输出

对于长文本回复,流式输出能显著改善用户体验:

java 复制代码
import reactor.core.publisher.Flux;

/**
 * 流式输出
 * 适用于长回复场景,用户可以实时看到生成过程
 */
public Flux<String> chatStream(String message) {
    return chatClient.prompt()
            .user(message)
            .stream()
            .content();
}

Controller层实现SSE(Server-Sent Events):

java 复制代码
package com.example.demo.controller;

import com.example.demo.service.ChatService;
import lombok.RequiredArgsConstructor;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.*;
import reactor.core.publisher.Flux;

@RestController
@RequestMapping("/api/chat")
@RequiredArgsConstructor
public class ChatController {
    
    private final ChatService chatService;
    
    /**
     * 普通对话接口
     * POST /api/chat
     */
    @PostMapping
    public String chat(@RequestBody ChatRequest request) {
        if (request.message() == null || request.message().isBlank()) {
            throw new IllegalArgumentException("消息内容不能为空");
        }
        return chatService.chat(request.message());
    }
    
    /**
     * 流式对话接口(SSE)
     * POST /api/chat/stream
     */
    @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatStream(@RequestBody ChatRequest request) {
        return chatService.chatStream(request.message());
    }
}

/**
 * 请求参数记录
 */
public record ChatRequest(String message) {}

四、进阶功能:结构化输出与Prompt模板

4.1 结构化输出

在很多场景下,我们需要AI返回结构化的数据(JSON、Java对象等)。

定义输出结构
java 复制代码
package com.example.demo.model;

/**
 * 代码审查结果
 */
public record CodeReviewResult(
        int score,                     // 代码质量评分(1-100)
        List<String> issues,           // 发现的问题
        List<String> suggestions,      // 改进建议
        String summary                 // 总体评价
) {}

/**
 * SQL优化建议
 */
public record SqlOptimizationResult(
        String originalSql,
        String optimizedSql,
        List<String> improvements,
        String explanation
) {}
实现结构化输出
java 复制代码
/**
 * 代码审查:返回结构化结果
 */
public CodeReviewResult reviewCode(String code) {
    String prompt = """
        请作为资深Java代码审查专家,对以下代码进行审查。
        
        代码内容:
        ```java
        %s
        ```
        
        请按JSON格式返回审查结果,包含以下字段:
        - score: 代码质量评分(1-100的整数)
        - issues: 发现的问题列表(字符串数组)
        - suggestions: 改进建议列表(字符串数组)
        - summary: 总体评价(字符串)
        
        返回格式必须是合法的JSON,不要包含其他内容。
        """.formatted(code);
    
    String jsonResponse = chatClient.prompt()
            .user(prompt)
            .call()
            .content();
    
    // 提取JSON(AI可能返回markdown代码块)
    String json = extractJsonFromResponse(jsonResponse);
    
    try {
        ObjectMapper mapper = new ObjectMapper();
        return mapper.readValue(json, CodeReviewResult.class);
    } catch (JsonProcessingException e) {
        log.error("Failed to parse JSON response: {}", jsonResponse, e);
        throw new RuntimeException("AI返回格式错误", e);
    }
}

/**
 * 从AI响应中提取JSON
 */
private String extractJsonFromResponse(String response) {
    // 去除markdown代码块标记
    response = response.trim();
    if (response.startsWith("```json")) {
        response = response.substring(7);
    }
    if (response.startsWith("```")) {
        response = response.substring(3);
    }
    if (response.endsWith("```")) {
        response = response.substring(0, response.length() - 3);
    }
    return response.trim();
}

4.2 Prompt模板

Spring AI提供了Prompt模板功能,可以管理复杂的提示词。

java 复制代码
import org.springframework.ai.chat.prompt.PromptTemplate;
import org.springframework.ai.chat.messages.Message;

/**
 * 使用Prompt模板
 */
public String chatWithTemplate(String topic, String audience, int length) {
    String template = """
        请写一篇关于{topic}的技术博客,要求:
        
        1. 面向{audience}
        2. 文章长度约{length}字
        3. 包含代码示例
        4. 语言简洁易懂
        5. 包含实际应用案例
        
        请直接开始写文章正文,不要有任何开场白。
        """;
    
    PromptTemplate promptTemplate = new PromptTemplate(template);
    Message message = promptTemplate.createMessage(Map.of(
            "topic", topic,
            "audience", audience,
            "length", String.valueOf(length)
    ));
    
    return chatClient.prompt()
            .messages(message)
            .call()
            .content();
}

五、RAG实战:让AI读懂你的业务文档

5.1 添加向量存储依赖

xml 复制代码
<!-- 使用Milvus作为向量数据库 -->
<dependency>
    <groupId>com.alibaba.cloud.ai</groupId>
    <artifactId>spring-ai-alibaba-vector-store-milvus</artifactId>
    <version>1.0.0-M3</version>
</dependency>

5.2 配置Milvus

yaml 复制代码
# application.yml(追加)
spring:
  ai:
    vectorstore:
      milvus:
        client:
          host: localhost
          port: 19530
          username: ""
          password: ""
        collection-name: company_docs
        embedding-dimension: 1536  # text-embedding-v4的输出维度

5.3 文档处理服务

java 复制代码
package com.example.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.Map;
import java.util.UUID;

@Slf4j
@Service
@RequiredArgsConstructor
public class DocumentIngestionService {
    
    private final VectorStore vectorStore;
    private final EmbeddingModel embeddingModel;
    
    /**
     * 将文本添加到知识库
     */
    public int addDocument(String content, String source) {
        Document doc = new Document(
                UUID.randomUUID().toString(),
                content,
                Map.of(
                        "source", source,
                        "timestamp", String.valueOf(System.currentTimeMillis())
                )
        );
        
        vectorStore.add(List.of(doc));
        log.info("Document added to knowledge base: {}", source);
        return 1;
    }
    
    /**
     * 批量添加文档
     */
    public int addDocuments(List<String> contents, String sourcePrefix) {
        List<Document> documents = new ArrayList<>();
        for (int i = 0; i < contents.size(); i++) {
            Document doc = new Document(
                    UUID.randomUUID().toString(),
                    contents.get(i),
                    Map.of(
                            "source", sourcePrefix + "_chunk_" + i,
                            "chunk_index", String.valueOf(i)
                    )
            );
            documents.add(doc);
        }
        
        vectorStore.add(documents);
        log.info("Added {} document chunks to knowledge base", documents.size());
        return documents.size();
    }
}

5.4 RAG问答服务

java 复制代码
package com.example.demo.service;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.ai.chat.messages.UserMessage;
import org.springframework.ai.chat.prompt.Prompt;
import org.springframework.stereotype.Service;

import java.util.List;
import java.util.stream.Collectors;

@Slf4j
@Service
@RequiredArgsConstructor
public class RagService {
    
    private final ChatClient chatClient;
    private final VectorStore vectorStore;
    
    /**
     * RAG问答
     * @param question 用户问题
     * @return AI回答
     */
    public String answerWithRag(String question) {
        // Step 1: 从向量库检索相关文档
        List<Document> relevantDocs = vectorStore.similaritySearch(
                org.springframework.ai.chat.client.SearchRequest.builder()
                        .query(question)
                        .topK(5)                 // 返回最相关的5个文档
                        .similarityThreshold(0.5) // 相似度阈值
                        .build()
        );
        
        if (relevantDocs.isEmpty()) {
            return "知识库中未找到相关信息。";
        }
        
        log.info("Retrieved {} relevant documents", relevantDocs.size());
        
        // Step 2: 构建上下文
        String context = relevantDocs.stream()
                .map(Document::getText)
                .collect(Collectors.joining("\n\n---\n\n"));
        
        // Step 3: 构建RAG Prompt
        String prompt = """
            你是一个专业的企业知识助手。请严格根据以下上下文信息回答问题。
            
            【重要规则】:
            1. 如果上下文中有答案,请基于上下文回答
            2. 如果上下文中没有相关信息,请明确告知用户
            3. 回答要准确、简洁、有条理
            4. 可以适当引用上下文中的内容
            
            上下文信息:
            %s
            
            用户问题:%s
            
            请基于上下文回答:
            """.formatted(context, question);
        
        // Step 4: 调用AI生成答案
        String answer = chatClient.prompt()
                .user(prompt)
                .call()
                .content();
        
        log.info("RAG answer generated, length: {}", answer.length());
        return answer;
    }
    
    /**
     * 流式RAG问答
     */
    public reactor.core.publisher.Flux<String> answerWithRagStream(String question) {
        List<Document> relevantDocs = vectorStore.similaritySearch(
                org.springframework.ai.chat.client.SearchRequest.builder()
                        .query(question)
                        .topK(5)
                        .build()
        );
        
        if (relevantDocs.isEmpty()) {
            return reactor.core.publisher.Flux.just("知识库中未找到相关信息。");
        }
        
        String context = relevantDocs.stream()
                .map(Document::getText)
                .collect(Collectors.joining("\n\n"));
        
        String prompt = "根据以下上下文回答问题:\n%s\n\n问题:%s".formatted(context, question);
        
        return chatClient.prompt()
                .user(prompt)
                .stream()
                .content();
    }
}

六、踩坑记录与解决方案

6.1 API调用超时

问题现象

csharp 复制代码
java.net.SocketTimeoutException: Read timed out

原因分析: 大模型生成时间较长,默认的10秒超时不够。

解决方案

java 复制代码
// 自定义超时配置
@Configuration
public class AiConfig {
    
    @Bean
    public ChatClient chatClient(ChatClient.Builder builder) {
        return builder
                .defaultClientRequest(request -> request
                        .timeout(java.time.Duration.ofSeconds(60))  // 延长到60秒
                )
                .build();
    }
}

6.2 中文乱码

问题现象: 返回的中文显示为乱码。

原因分析: HTTP响应编码未正确设置。

解决方案

yaml 复制代码
spring:
  ai:
    alibaba:
      base-url: https://dashscope.aliyuncs.com/compatible-mode/v1
      # 确保使用兼容模式URL,该URL默认支持UTF-8

6.3 Token超限

问题现象

vbnet 复制代码
RuntimeException: This model's maximum context length is 128000 tokens

解决方案

java 复制代码
/**
 * 智能截断,避免超出Token限制
 */
private String truncateByTokenEstimate(String text, int maxTokens) {
    // 粗略估算:中文1字≈1.5 token,英文1词≈1.3 token
    int estimatedTokens = estimateTokens(text);
    
    if (estimatedTokens <= maxTokens) {
        return text;
    }
    
    // 按字符比例截断
    int maxChars = (int) (maxTokens / 1.5);
    log.warn("Text truncated from {} to {} chars to fit token limit", 
             text.length(), maxChars);
    return text.substring(0, Math.min(maxChars, text.length()));
}

private int estimateTokens(String text) {
    long chineseCount = text.chars()
            .filter(c -> c >= 0x4E00 && c <= 0x9FFF)
            .count();
    long englishWords = text.split("\\s+").length;
    return (int) (chineseCount * 1.5 + englishWords * 1.3);
}

6.4 嵌入模型维度不匹配

问题现象

yaml 复制代码
IllegalArgumentException: Dimension mismatch: expected 1536, got 1024

原因分析: 不同嵌入模型的输出维度不同,需要与向量库配置一致。

解决方案

yaml 复制代码
spring:
  ai:
    alibaba:
      embedding:
        options:
          model: text-embedding-v4  # 输出维度1536
    
    vectorstore:
      milvus:
        embedding-dimension: 1536  # 与嵌入模型输出维度一致

6.5 流式输出被拦截器处理

问题现象: SSE流式输出被Spring的某些拦截器处理,导致格式错误。

解决方案

java 复制代码
@RestController
@RequestMapping("/api/chat")
public class ChatController {
    
    // 为流式接口禁用某些拦截器
    @PostMapping(value = "/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public Flux<String> chatStream(@RequestBody ChatRequest request) {
        return chatService.chatStream(request.message())
                .doOnNext(token -> log.debug("Streaming token: {}", token));
    }
}

七、生产级最佳实践

7.1 配置管理

java 复制代码
@Configuration
@ConfigurationProperties(prefix = "app.ai")
@Data
public class AiProperties {
    
    /**
     * 是否启用AI功能(用于灰度发布)
     */
    private boolean enabled = true;
    
    /**
     * 最大重试次数
     */
    private int maxRetries = 3;
    
    /**
     * 超时时间(秒)
     */
    private int timeoutSeconds = 60;
    
    /**
     * Token预算(每次请求最大token数)
     */
    private int maxTokensPerRequest = 2000;
}

7.2 错误处理与重试

java 复制代码
import org.springframework.retry.annotation.Retryable;
import org.springframework.retry.annotation.Backoff;

@Service
@Slf4j
public class RobustChatService {
    
    private final ChatClient chatClient;
    
    @Retryable(
            value = {Exception.class},
            maxAttempts = 3,
            backoff = @Backoff(delay = 1000, multiplier = 2)
    )
    public String chatWithRetry(String message) {
        try {
            return chatClient.prompt()
                    .user(message)
                    .call()
                    .content();
        } catch (Exception e) {
            log.error("AI调用失败,将重试", e);
            throw e;  // 触发重试
        }
    }
}

7.3 成本监控

java 复制代码
@Component
@Slf4j
public class TokenUsageMonitor {
    
    private final MeterRegistry meterRegistry;
    
    public TokenUsageMonitor(MeterRegistry meterRegistry) {
        this.meterRegistry = meterRegistry;
    }
    
    /**
     * 记录Token使用情况
     */
    public void recordUsage(int inputTokens, int outputTokens) {
        meterRegistry.counter("ai.token.usage.input").increment(inputTokens);
        meterRegistry.counter("ai.token.usage.output").increment(outputTokens);
        
        // 估算成本(通义千问qwen-plus价格:0.004元/千tokens)
        double costYuan = (inputTokens + outputTokens) * 0.004 / 1000;
        meterRegistry.counter("ai.cost.yuan").increment(costYuan);
        
        log.info("Token usage - Input: {}, Output: {}, Estimated cost: {} yuan", 
                 inputTokens, outputTokens, costYuan);
    }
    
    /**
     * 获取今日总成本
     */
    public double getTodaysCost() {
        // 实际实现需要对接监控系统
        return meterRegistry.counter("ai.cost.yuan").count();
    }
}

八、完整项目示例

8.1 项目结构

css 复制代码
spring-ai-alibaba-demo/
├── src/main/java/com/example/demo/
│   ├── DemoApplication.java
│   ├── config/
│   │   ├── AiConfig.java
│   │   └── SwaggerConfig.java
│   ├── controller/
│   │   ├── ChatController.java
│   │   └── RagController.java
│   ├── service/
│   │   ├── ChatService.java
│   │   ├── RagService.java
│   │   └── DocumentService.java
│   └── model/
│       ├── ChatRequest.java
│       └── CodeReviewResult.java
├── src/main/resources/
│   ├── application.yml
│   └── prompt-templates/
│       ├── code-review.st
│       └── sql-optimization.st
└── docker-compose.yml

8.2 Docker Compose配置

yaml 复制代码
version: '3.8'

services:
  milvus:
    image: milvusdb/milvus:v2.4.0
    container_name: milvus-standalone
    ports:
      - "19530:19530"
    environment:
      ETCD_ENDPOINTS: milvus-etcd:2379
      MINIO_ADDRESS: milvus-minio:9000
    volumes:
      - ./volumes/milvus:/var/lib/milvus
    restart: always
  
  app:
    build: .
    container_name: spring-ai-app
    ports:
      - "8080:8080"
    environment:
      - ALI_API_KEY=${ALI_API_KEY}
    depends_on:
      - milvus
    restart: always

8.3 启动类

java 复制代码
package com.example.demo;

import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@Slf4j
@SpringBootApplication
public class DemoApplication {
    
    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
        log.info("Spring AI Alibaba Demo started successfully!");
        log.info("API endpoint: http://localhost:8080/api/chat");
    }
}

九、性能测试与优化

9.1 性能基准测试

java 复制代码
@Test
void benchmarkChatPerformance() {
    int iterations = 100;
    long totalTime = 0;
    
    for (int i = 0; i < iterations; i++) {
        long start = System.currentTimeMillis();
        String response = chatService.chat("用一句话介绍Spring Boot");
        long end = System.currentTimeMillis();
        totalTime += (end - start);
    }
    
    double avgTime = totalTime / (double) iterations;
    log.info("Average response time: {} ms", avgTime);
    
    // 性能目标:平均响应时间 < 3秒
    assertTrue(avgTime < 3000);
}

9.2 优化建议

  1. 使用连接池
yaml 复制代码
spring:
  ai:
    alibaba:
      chat:
        options:
          # 启用请求合并
          stream: false
  1. 启用响应缓存
java 复制代码
@Cacheable(value = "ai-responses", key = "#message.hashCode()")
public String chatWithCache(String message) {
    return chatClient.prompt().user(message).call().content();
}
  1. 异步处理
java 复制代码
@Async
public CompletableFuture<String> chatAsync(String message) {
    return CompletableFuture.supplyAsync(() -> chatService.chat(message));
}

十、总结与资源

10.1 关键要点

  1. Spring AI Alibaba让Java开发者能够以Spring的方式使用通义千问
  2. ChatClient API简单易用,支持链式调用和流式输出
  3. RAG是生产环境最常用的模式,需要配合向量数据库
  4. 注意超时、Token限制、成本控制等生产级问题
  5. 通义千问的中文理解能力非常适合国内项目

10.2 适用场景

场景 推荐模型 理由
实时对话 qwen-turbo 速度快,成本低
复杂推理 qwen-plus 能力强,性价比高
代码生成 qwen-coder-plus 专门针对代码优化
向量嵌入 text-embedding-v4 中文优化,维度合理

10.3 参考资源


如果有帮助,欢迎点赞、收藏、关注! 如有问题,欢迎在评论区交流。

相关推荐
F_U_N_1 小时前
打工人实测:PandaWiki,把知识管理变简单
人工智能·开源
SCKJAI1 小时前
算力轻量化赋能巡检升级!视程空间AIR SC6N0-C NX平台,打造高阶智能巡检机器狗
人工智能
逻辑君1 小时前
认知神经科学研究报告【20260043】
人工智能·机器学习
同元软控1 小时前
从 Copilot 到 Agent:MWORKS AI 全线升级,开启科学计算与系统建模仿真的智能体时代
人工智能·copilot
码农小白AI1 小时前
漏电流报告审核为何进入“新速度时代”?IACheck用AI报告审核重构效率与精度
人工智能·重构
王_teacher1 小时前
RNN 反向传播数学推导(BPTT 时间反向传播)
人工智能·rnn·深度学习
wanhengidc1 小时前
算力服务器的应用场景
运维·服务器·人工智能·安全·web安全·智能手机
企微增长观察1 小时前
2026企业微信AI SCRM实测:微盛·企微管家全行业私域运营
大数据·人工智能·企业微信