SpringAI4.0

目录

一、项目

[1.0 简介](#1.0 简介)

(1)项目介绍

[2.0 项目搭建](#2.0 项目搭建)

[(1) 项目初始化](#(1) 项目初始化)

(2)构建RAG知识库

(3)多线程处理文档

(4)切换向量数据库

(5)重排序

(6)MCP

(7)敏感词处理

(8)聊天记忆持久化

[3.0 成果展示](#3.0 成果展示)

(1)界面展示

(2)会话内容记忆

(3)会话列表记忆

(4)接入的mcp

(5)后台


综合案例

一、项目

1.0 简介

(1)项目介绍

构建一套面向"嘟嘟就业课"课程咨询场景的智能聊天系统

支持 对话记忆、RAG 知识库问答、敏感词安全引导、⼯具调⽤ (MCP ⼯单系统) , 并提供简单易⽤的 Web 聊天界⾯

组成:`chat-bot-service`:对外 Web 服务 (端⼝默认 8081) , 提供聊天流式接⼝、会话管理、RAG 检索、敏感词引导、MCP 客⼾端调⽤. `ticket-service`:MCP Server (⽆ Web, STDIO 启动) , 暴露"创建⼯单/查询⼯单"的⼯具能⼒, 持久化在 MySQL.

2.0 项目搭建

(1) 项目初始化

在一期案例的基础上 进行改动 创建项目:bit-chat-bot 和 模块chat - bot - service

(2)代码整理

升级SpringAI版本 切换框架为SpringAI Alibaba

java 复制代码
<properties>
    <spring-ai.version>1.0.1</spring-ai.version>
</properties>

<!-- 父工程依赖 -->
<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.5.3</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>

<!-- 依赖版本管理 -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-bom</artifactId>
            <version>${spring-ai.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

chat-bot-service项目pom.xml修改如下

java 复制代码
<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>

    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>

    <!-- spring ai alibaba -->
    <dependency>
        <groupId>com.alibaba.cloud.ai</groupId>
        <artifactId>spring-ai-alibaba-starter-dashscope</artifactId>
    </dependency>

    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-webflux</artifactId>
    </dependency>
</dependencies>

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.alibaba.cloud.ai</groupId>
            <artifactId>spring-ai-alibaba-bom</artifactId>
            <version>1.0.0.2</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

修改配置文件:

java 复制代码
server:
  port: 8081

spring:
  application:
    name: spring-chat-bot
  ai:
    dashscope:
      api-key: ${DASHSCOPE_API_KEY}

logging:
  level:
    org.springframework.ai.chat.client.advisor: debug
  pattern:
    console: "%d{HH:mm:ss.SSS} %5p ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n%wEx"

修改代码:

由于切换了SpringAI版本以及更改了LLM的配置,所以导致先前出现的代码出现一些问题,需要进行修改

修改CommonConfiguration.java

java 复制代码
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.MessageChatMemoryAdvisor;
import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor;
import org.springframework.ai.chat.memory.ChatMemory;
import org.springframework.ai.chat.memory.MessageWindowChatMemory;
import org.springframework.ai.dashscope.DashScopeChatModel;

@Configuration
public class CommonConfiguration {

    @Bean
    public ChatMemory chatMemory() {
        MessageWindowChatMemory memory = MessageWindowChatMemory.builder()
                .maxMessages(10)
                .build();
        return memory;
    }

    @Bean
    public ChatClient dashscopeChatClient(DashScopeChatModel chatModel, ChatMemory chatMemory) {
        return ChatClient.builder(chatModel)
                .defaultSystem("你叫小特,是比特教育研发的一款智能AI助手,擅长Java和C++,主要工作是解决学生在学习过程中遇到的一些问题")
                .defaultAdvisors(
                        new SimpleLoggerAdvisor(),
                        MessageChatMemoryAdvisor.builder(chatMemory).build()
                )
                .build();
    }
}

修改ChatController

修改之后进行测试:

启动服务 测试http://127.0.0.1:8081/index.html

(2)构建RAG知识库

1 文件加载

由于就业课的网络公开资源较为有限,为提升就业课智能咨询系统的回答质量,解决其网络资源不足的问题,我们需要引入知识库作为大语言模型的上下文

添加文件:把提供的文件放在resource/bit目录下,为知识库的搭建做准备

resource的file下面

有了相关文档,首先加载上述提供的文件,转换为Document,方便后续处理

添加相关依赖:

java 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-markdown-document-reader</artifactId>
</dependency>

创建rag包下DocumentLoader

把这些mardown文件变成resource 接下来使用markdown reader把resource变成document List

//简单来说就是 把本地的Markdown文件,通过Spring的Resource加载机制和Spring AI的Markdown读取器,转成程序可以处理的文档对象列表,为构建知识库做准备

写代码的时候ctrl加左键 看构造方法参数 这些都是编译器提前提供好了的

java 复制代码
@Slf4j
@Component
public class DocumentLoader {
    @Autowired
    private ResourceLoader resourceLoader;

    public Resource[] getResources(String location) throws IOException {
        ResourcePatternResolver resolver = new PathMatchingResourcePatternResolver(resourceLoader);
        return resolver.getResources(location);
    }

    public List<Document> loadMarkdowns() {
        List<Document> allDocuments = new ArrayList<>();
        try {
            Resource[] resources = getResources("classpath:bit/*.md");
            for (Resource resource : resources) {
                String fileName = resource.getFilename();
                log.info("load file:"+ fileName);
                MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
                        .withHorizontalRuleCreateDocument(true)
                        .withIncludeCodeBlock(false)
                        .withIncludeBlockquote(false)
                        .withAdditionalMetadata("filename", fileName)
                        .build();
                MarkdownDocumentReader reader = new MarkdownDocumentReader(resource, config);
                allDocuments.addAll(reader.get());
            }
        }catch (IOException e){
            log.error("加载文件失败", e);
        }
        log.info("文档加载完成");
        return allDocuments;
    }
}

2 文本分割

文档加载后,为适应模型的上下文窗口限制,需要对原始文档进行切分

也就是将冗长文档拆解为符合令牌数量限制的语义片段,这是确保后续向量化处理与精准检索能够顺利进行的先决条件

//模仿TokenTextSplitter 对源文档按中文标点符号进行切分 因为源码默认是英文的 不方便

我们拿来修改一下

最主要的部分是:

java 复制代码
// Find the last period or punctuation mark in the chunk
int lastPunctuation = Math.max(chunkText.lastIndexOf('.'),
        Math.max(chunkText.lastIndexOf('?'),
        Math.max(chunkText.lastIndexOf('!'),
        Math.max(chunkText.lastIndexOf('。'),
        Math.max(chunkText.lastIndexOf('?'),
        Math.max(chunkText.lastIndexOf('!'),
                chunkText.lastIndexOf('\n'))))));

在文本里面找到一个最合适的断句点,避免把一句话切的稀碎,它在最后一个可以干净利落断句的标点符合位置,让切割更符合语言习惯

3 补充关键词元信息

为了实现更精准的智能检索,完成文本分割后,系统将对分割后的文本块进行"元信息增强"处理,为每个文本块提取并附加关键词元信息,当进行语义检索时,这些关键词与文本块的嵌入向量系统工作,提升问答系统的响应质量与用户体验。

java 复制代码
@Component
public class KeywordEnricher {

    @Autowired
    private DashScopeChatModel chatModel;

    /**
     * 补充关键词元信息
     * @param documents
     * @return
     */
    public List<Document> enrich(List<Document> documents) {
        // 关键词提取
        KeywordMetadataEnricher enricher = KeywordMetadataEnricher.builder(chatModel)
                .keywordCount(5)
                .build();
        return enricher.apply(documents);
    }
}

4 定义向量数据库

完成这些预处理后 关键的一步就是把这些文本框存入向量数据库

完成知识库构建的最后一步 此后 系统便可根据用户问题,实时从库中召回最相关的知识片段

java 复制代码
@Configuration
public class VectorConfig {
    @Bean
    public VectorStore vectorStore(EmbeddingModel embeddingModel){
        return SimpleVectorStore.builder(embeddingModel).build();
    }
}

5 流程串联

通过这个DataInit方法把整个流程串联起来

代码不进行展示了 比较多 需要解决一下bug,可能会有乱码的问题

解决方式是在配置文件里面加入

java 复制代码
    charset:
      console: UTF-8
      file: UTF-8

6 应用RAG知识库问答

知识库构建完成后,即可基于向量库实施检索了

修改提示词:

在之前的CommonConfiguration里面把提示词修改一下

你是⼀名专业的企业培训课程咨询 助⼿, 代表【就业课】为客⼾提供课程咨询服务. 你的职责是准确、礼貌、⾼效地解答客⼾关于⽐特就业课培训课程的各类问题

定义QuestionAnswerAdvisor,绑定到ChatClient:

添加依赖

java 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>

加入代码:

java 复制代码
QuestionAnswerAdvisor questionAnswerAdvisor = QuestionAnswerAdvisor.builder(vectorStore).build();
-----------------
.defaultAdvisors(questionAnswerAdvisor)

提示词也修改一下 //这部分需要修改很多的bug

封装一个 Advisor类

7 测试:

启动项目 观察日志 知识库是否搭建完成

(3)多线程处理文档

问题:启动服务的时候 关键词提取耗时非常长(6--10min)

优化:使用多线程处理文档

CountDownLatch

同时等待N个任务执行结束:同时出发,都结束,才是结束

• 构造 CountDownLatch 实例, 初始化 10 表⽰有 10 个任务需要完成.

• 每个任务执⾏完毕, 都调⽤ latch.countDown() . 在 CountDownLatch 内部的计数器同时⾃减

• 主线程中使⽤ latch.await(); 阻塞等待所有任务执⾏完毕. 相当于计数器为 0 了.

看看代码吧:

java 复制代码
public class Demo {
    public static void main(String[] args) throws Exception {
        CountDownLatch latch = new CountDownLatch(10);
        Runnable r = new Runnable() {
            @Override
            public void run() {
                try {
                    Thread.sleep((int) (Math.random() * 10000));
                    latch.countDown();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        };

        for (int i = 0; i < 10; i++) {
            new Thread(r).start();
        }

        // 必须等到 10 人全部回来
        latch.await();
        System.out.println("比赛结束");
    }
}

latch.countDown 就像是在一个计数器门上按下减一 ,就是个倒计数信号,每完成一个任务减一下,减到0就放行等待的人。

使用CountDownLatch和线程池进行批量处理

测试:服务重启后,通过启动日志,可以观察到本次优化的效果:关键流程的耗时从原来的6--10 大幅降至2分钟以内

java 复制代码
 private final ExecutorService executorService = Executors.newFixedThreadPool(8);

代码讲解:简单来说就是把document分批次搬进向量数据库 线程池里面的现成同时搬

batchSize是分批 每批几个 enricher.enrich是贴标签,比如给文档补充一些关键词之类的元信息 vectorStore.add是把处理好的文档写入向量数据库,后面检索用 countDownLatch.await(10, TimeUnit.MINUTES); 就是主线程等所有人干完

(4)切换向量数据库

基于测试,,我们发现当前设计存在的两个问题:

数据易失性:向量数据存储在内存,服务重启后会造成数据丢失

初始化效率:因为数据丢失,所以每次重启都需要重新写入全量向量,效率低下

为了解决上述问题,进行以下两点优化:

数据持久化:将向量存储从内存迁移至Redis向量数据库,确保数据持久可用

流程可配置优化:引入用户配置项,允许按需控制是否执行向量初始化流程,避免无效开销

java 复制代码
data:
  is-load: true

使用配置:

java 复制代码
@Value("${data.is-load}")
private boolean isLoad;

@PostConstruct
public void initData(){
    if (!isLoad){
        log.info("知识库文档无需加载....");
        return;
    }
    //.... 执行文档加载流程
}

切换向量数据库:

添加redis相关依赖、添加Redis配置 、 删除SimpleVectorStore定义

java 复制代码
<!-- 接入Redis -->
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
-----------------------------------------------------------------
spring:
  ai:
    vectorstore:
      redis:
        initialize-schema: true # 是否自动创建索引结构
        index-name: bit-chat-bot # 向量索引名称
        prefix: "rag:" # Redis Key 前缀
  data:
    redis:
      url: redis://XX.XX.XX.XX:XX

//添加依赖 配置之后,注入VectroStore会自动切换为RedisVectorStore 删除之前定义的SimpleVecctorStore 注释掉就可以

重新测试

(5)重排序

在初步检索之后,我们可以引入一个更擅长判断相关性的精排模型,对候选文档进行重新打分

从而更精准的筛选出最匹配的内容,再交大模型生成回答,这一流程能够有效提升最终答案的准确度

定义重排序Advisor

利用SpringAI提供的 RestrievalRerankAdvisor 我们在初步检索的基础上进行精细相关性排序,显著提升检索精度

也可以对重排序模型进行配置

(6)MCP

1 添加MCP应用

尽管接入了向量数据库和知识库后,大模型的回答能力有了明显的提升,但在实际使用中,还是会遇到一些超出它处理范围的用户请求

比如,当用户明确说 转人工客服 找专属顾问咨询 或是提到涉及敏感操作、复杂流程等需求时,仅靠预训练模型和静态的知识库往往难以应对

为了提升系统的灵活性和服务能力,我们计划引入外部工具调用机制(MCP),让模型在遇到特定场景时,能够触发外部服务或流程进行衔接

开发工单MCP服务

就是把工单系统做成一个标准插头,让AI助手能直接插上,自动帮你查任务 派任务 改状态

用这个来模拟人工客服

我们这个mcp服务要实现的功能是什么:

• 接收需求:使⽤"创建⼯单"⼯具, 将⽤⼾请求转化为待处理⼯单.

• 跟进进度:使⽤"查询⼯单"⼯具, 通过ID随时查看最新状态.

例如:我要退款 当我收到这个请求的时候 系统可以直接创建一个工单 这样后台的客服人员就可以看着这个工单列表来联系用户了

java 复制代码
-- 创建数据库
DROP DATABASE IF EXISTS bit_chat_bot;
CREATE DATABASE IF NOT EXISTS bit_chat_bot DEFAULT CHARACTER SET utf8mb4;

-- 使用数据库
USE bit_chat_bot;

-- 创建表
DROP TABLE IF EXISTS `ticket_info`;
CREATE TABLE `ticket_info` (
  `id` int NOT NULL AUTO_INCREMENT,
  `ticket_id` varchar(128) NOT NULL COMMENT '工单ID',
  `title` varchar(128) NOT NULL COMMENT '工单标题',
  `description` varchar(255) NOT NULL COMMENT '工单详细描述',
  `related_chat_id` varchar(128) DEFAULT NULL COMMENT '关联会话ID',
  `status` tinyint DEFAULT '1' COMMENT '工单状态 1-新建 2-处理中 3-已解决 4-已关闭',
  `creator` varchar(128) DEFAULT 'system' COMMENT '创建人',
  `assignee` varchar(128) DEFAULT NULL COMMENT '分配给',
  `created_time` datetime DEFAULT CURRENT_TIMESTAMP,
  `updated_time` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  `closed_time` datetime DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='工单信息表';

接下来进行mcp服务开发:

创建模块ticket-service//方便管理

完善pom文件

java 复制代码
 <dependencies>
        <dependency>
            <groupId>org.springframework.ai</groupId>
            <artifactId>spring-ai-starter-mcp-server</artifactId>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
        </dependency>
        <dependency>
            <groupId>com.mysql</groupId>
            <artifactId>mysql-connector-j</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
                <version>3.5.3</version>
            </plugin>
        </plugins>
    </build>

添加配置文件 : 别忘记数据库相关的信息

java 复制代码
spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/bit_chat_bot?characterEncoding=utf8&useSSL=false&allowPublicKeyRetrieval=true
    username: root
    password: root
    driver-class-name: com.mysql.cj.jdbc.Driver
  ai:
    mcp:
      server:
        name: ticket-service
        version: 0.0.1
  main:
    web-application-type: none
    banner-mode: off
mybatis:
  configuration:
    map-underscore-to-camel-case: true #配置驼峰自动转换
logging:
  pattern:
    console: "%d{HH:mm:ss.SSS} %5p ${PID:- } --- [%15.15t] %-40.40logger{39} : %m%n%wEx"

添加启动类

3 定义工具和暴漏工具

java 复制代码
@Configuration
public class TicketTool {
    @Bean
    public ToolCallbackProvider toolCallbackProvider(TicketService ticketService){
        return MethodToolCallbackProvider.builder()
                .toolObjects(ticketService)
                .build();
    }
}

maven里面进行打包 //中文路径可能会有乱码的情况

更改路径:

接入MCP

添加依赖

java 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-mcp-client</artifactId>
</dependency>

添加mcp配置 并创建mcp-servers-config.json文件

java 复制代码
spring:
  ai:
    mcp:
      client:
        request-timeout: 60000
        stdio:
          servers-configuration: classpath:/mcp/mcp-servers-config.json

文件内容为:

java 复制代码
{
  "mcpServers": {
    "ticket-service": {
      "command": "java",
      "args": [
        "-Dspring.ai.mcp.server.stdio=true",
        "-Dlogging.pattern.console=",
        "-Dfile.encoding=UTF-8",
        "-jar",
        "D:/Git/spring-ai-2/spring-chat-bot2/ticket-service/target/ticket-service-1.0-SNAPSHOT.jar"
      ]
    }
  }
}

添加工具

将会话ID传递给MCP

java 复制代码
.defaultToolCallbacks(toolCallbackProvider)

修改QuestionAnswerAdvisor模板提示词

java 复制代码
1.若上下文信息中包含与用户问题直接相关的内容,即使表述方式略有不同,也应通过语义理解判断其相关性,并据此进行回复。
2.如果答案不在上下文中,请帮忙创建工单,并让用户等待专业课程顾问回答。
3.如果用户要求 "人工客服"," 人工顾问 ' 来回答,请帮忙创建工单,并让用户等待专业课程顾问回答。
4.回复时直接给出答案或解决方案,避免使用 "根据您提供的信息"、"根据上下文" 等冗余表达。
确保系统具备基本的语义匹配能力,不能仅依赖字面完全匹配来判断信息相关性

测试MCP

(7)敏感词处理

我们可以基于用户的输入内容进行智能判断与分类处理

例如:当检测到脏话或违规内容时,系统将不予响应

Spring AI 提供的 SafeGuardAdvisor 组件可⽤于对⽤⼾输⼊内容进⾏安全检测与过滤, ⽀持敏感信息识别、不当⾔论拦截, 从⽽保障对话系统的安全性与合规性

java 复制代码
 .defaultAdvisors(new SafeGuardAdvisor(List.of("正副")))

自定义处理

SafeGuardAdvisor 的内置敏感词过滤是比较"死板"的,如果你觉得它不够用,可以自己动手写一个更聪明的 Advisor 来代替它。

自定义Advisor:CustomSafeGuardAdvisor

修改对应的返回模板

java 复制代码
private static final String DEFAULT_FAILURE_RESPONSE = "这个问题我暂时解答不了, 我们聊点别的吧";
(8)聊天记忆持久化

存在问题:服务重启后所有历史会话和上下文全部丢失 无法支持生产环境长期运行需求

当前系统的会话管理由两部分组成:

会话记忆 会话列表 //都是在内存中实现的 不持久

目标:将上述两个模块的数据存储方式改为持久化存储,提升系统可用性与数据可靠性

SpringAI提供了多种内置的聊天记忆存储实现,包括:

• InMemoryChatMemoryRepository (默认)

• JdbcChatMemoryRepository (关系型数据库)

• CassandraChatMemoryRepository

• Neo4jChatMemoryRepository

我们选择JDBC方案,适配现有MySQL环境,实现轻量级持久化

引入依赖:

java 复制代码
<dependency>
    <groupId>org.springframework.ai</groupId>
    <artifactId>spring-ai-starter-model-chat-memory-repository-jdbc</artifactId>
</dependency>

<!-- MySQL驱动 -->
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <scope>runtime</scope>
</dependency>

添加配置:

java 复制代码
spring:
  ai:
    chat:
      memory:
        repository:
          jdbc:
            initialize-schema: always
            schema: classpath:/sql/schema-mysql.sql
  datasource:
    username: root
    password: root
    url: jdbc:mysql://localhost:3306/bit_chat_bot?characterEncoding=utf8&useSSL=false&serverTimezone=UTC
    driver-class-name: com.mysql.cj.jdbc.Driver

在resources/sql/schema-mysql.sql文件中定义表结构

java 复制代码
CREATE TABLE chat_sessions (
    id INT NOT NULL AUTO_INCREMENT,
    chat_id VARCHAR(36) NOT NULL,
    title VARCHAR(127) NOT NULL DEFAULT '新会话',
    created_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP,
    updated_time DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
    PRIMARY KEY (`id`)
);

配置JdbcChatMemoryRepository 通过注入JdbcChatMemoryRepository 构建持久化的MessageWindowChatMemory

java 复制代码
@Bean
ChatMemory chatMemory(JdbcChatMemoryRepository chatMemoryRepository) {
    return MessageWindowChatMemory
            .builder()
            .maxMessages(10) // 控制每个会话最多保留10条消息
            .chatMemoryRepository(chatMemoryRepository)
            .build();
}

扩展:实现会话列表的持久化

⽬前"会话列表"是通过内存Map存储( MemoryChatHistoryRepository )的, 可以将其改造为"数

据库持久化版本".

参考步骤: 设计数据库表结构 编写实体类ChatSession 实现JdbcChatHistroyRepository类

替换原内存实现为数据库实现 测试:重启服务后确认数据不丢失

//这部分代码可以用AI实现

3.0 成果展示

(1)界面展示
(2)会话内容记忆
(3)会话列表记忆
(4)接入的mcp
(5)后台
相关推荐
vivo互联网技术9 小时前
VAPD AgentKit:可组合 Agent 前端通用库实践
前端·ai·架构·agent
@蔓蔓喜欢你10 小时前
Node.js 流处理:高效处理大数据的艺术
人工智能·ai
唐璜Taro10 小时前
AI Agent 智能体:从入门到实战的学习路线
学习·ai
@蔓蔓喜欢你10 小时前
CSS 变量:样式开发的新维度
人工智能·ai
创世宇图11 小时前
【AI入门知识点】Agent 是什么?为什么说它是 AI 的下一阶段?
ai·agent
Jurio.12 小时前
AI Daily Paper Reader(ADPR):零服务器搭建个人/团队通用大模型API驱动的论文阅读与推荐平台
论文阅读·人工智能·ai
searchforAI12 小时前
我用这款本土NotebookLM平替重构了知识库
人工智能·笔记·gpt·ai·音视频·知识图谱
不懂的浪漫12 小时前
01|从 Spring Boot 项目理解 RAG:ingest、query、rerank、trace 到 eval
java·人工智能·spring boot·后端·ai·rag
TheRouter12 小时前
AI Agent 的Prompt Injection 防御实战:从EchoLeak 零点击外泄到6层防护栈(含可运行代码与对比表)
人工智能·ai·prompt