langchain4j搭建失物招领系统(六)---实现失物查询功能-RAG使用

今天通过RAG来实现失物查询功能

一、RAG相关配置

1、定义向量数据库

java 复制代码
    // 配置向量数据库, 这里使用内存数据库
    @Bean
    public EmbeddingStore<TextSegment> embeddingStore() {
        return new InMemoryEmbeddingStore<>();
    }

2、定义向量模型

java 复制代码
    // 配置向量模型
    @Bean
    public EmbeddingModel embeddingModel() {
        return QwenEmbeddingModel.builder()
                .apiKey(System.getenv("ALI_AI_KEY"))
                .modelName("text-embedding-v3")
                .build();
    }

3、定义内容检索器

java 复制代码
    // 配置内容检索器
    @Bean
    public ContentRetriever contentRetriever(EmbeddingStore<TextSegment> embeddingStore, EmbeddingModel embeddingModel) {
        return EmbeddingStoreContentRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(2)
                .minScore(0.5)
                .build();
    }

二、向量数据初始化

1、初始化

要查询向量数据,需要先通过向量模型把数据先存入到向量数据库中,我这边先定义个接口初始化一下向量数据。

java 复制代码
    @GetMapping(value = "/embedding-index")
    public String embeddingIndex() {
        return aiChatService.embeddingIndex();
    }

初始化代码如下:

java 复制代码
    public String embeddingIndex() {
        String path = "./data/data.txt";
        try {
            // 将丢失物品数据写入文件
            FileUtil.writeString("", path, StandardCharsets.UTF_8);
            List<String> collect = StreamSupport.stream(lostPropertyRepository.findAll().spliterator(), false)
                    .map(JsonUtils::toJson)
                    .toList();
            FileUtil.appendLines(collect, path, StandardCharsets.UTF_8);
            log.info("write file success");
        } catch (Exception e) {
            log.error("write file error", e);
        }

        // 加载并解析文档内容
        DocumentParser documentParser = new TextDocumentParser();
        Document document = FileSystemDocumentLoader.loadDocument(FileUtil.getAbsolutePath(path), documentParser);

        // 按行分割文档为指定长度的文本片段
        DocumentSplitter splitter = new DocumentByLineSplitter(200, 100);
        List<TextSegment> documents = splitter.split(document);

        // 生成文本片段的嵌入向量并存储
        List<Embedding> embeddings = embeddingModel.embedAll(documents).content();
        embeddingStore.addAll(embeddings, documents);
        
        return "success";
    }

2、测试

查询测试:

java 复制代码
    @GetMapping(value = "/embedding-query")
    public List<String> embeddingQuery(String message) {
        return aiChatService.embeddingQuery(message);
    }
java 复制代码
    public List<String> embeddingQuery(String message) {
        EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest.builder()
                .queryEmbedding(embeddingModel.embed(message).content())
                .minScore(0.5)
                .maxResults(2)
                .build();
        EmbeddingSearchResult<TextSegment> search = embeddingStore.search(embeddingSearchRequest);
        return search.matches().stream().map(x -> x.embedded().text()).collect(Collectors.toList());
    }

我这边先通过DeepSeek帮我生成了一些失物数据,如下:

启动服务后,先初始化一下向量数据:

然后测试一下:

三、向量数据查询

1、增加失物查询工具

java 复制代码
    @Tool("根据物品及物品特征查询物品登记信息")
    public List<String> queryLostProperty(@P(value = "物品名称和特征") String lostProperty) {
        log.info("根据物品及物品特征查询物品登记信息,物品名称和特征: {}", lostProperty);
        List<String> list = contentRetriever.retrieve(new Query(lostProperty))
                .stream()
                .map(x -> x.textSegment().text())
                .toList();
        log.info("根据物品及物品特征查询物品登记信息,查询结果: {}", list);
        return list;
    }

2、定义AiServices

java 复制代码
    /**
     * 查询失物信息
     */
    @SystemMessage(fromResource = "/message/system/queryLostProperty.txt")
    @UserMessage("当前sessionId:{{sessionId}};用户当前消息:{{message}}")
    Flux<String> queryLostProperty(@V("sessionId") String id, @V("message") String message);

提示词:

plain 复制代码
# 角色
你是一位专业的失物管理员,负责处理失物招领相关工作。根据用户输入的丢失物品信息,仔细与系统中已录入的失物信息进行比对,并准确告知用户拾取到人的信息。

## 技能
### 技能 1: 比对丢失物品信息
- 每次对话,需要调用getChatHistory函数获取用户对话历史。
- 主动询问用户的姓名和手机号。
- 当用户提供失物相关信息时,从中提取物品信息和相关特征。
- 如果用户已经输入了手机号,调用queryLostRegisterByPhone函数查询用户丢失物品的信息。若能查询到数据,可能有多条数据,将其与用户已输入的物品信息进行匹配(比较失物名称和失物特征是否是能匹配),最多返回一条已经匹配的数据,如果没有查询到数据,需要引导用户进入登记流程。
- 如果已经查询到用户登记的丢失信息,获取丢失的失物信息和相关失物特征,调用queryLostProperty函数,获取系统中已经录入的失物信息,将其与系统中录入的失物信息进行详细比对。
- 若找到匹配信息,准确提取并整理拾取到人的相关信息。
- 以清晰易懂的方式向用户反馈拾取到人的信息。

## 限制:
- 仅围绕失物招领工作展开交流,拒绝回答无关话题。
- 反馈信息应基于系统中已录入的信息,确保准确性。
- 不要调用其他无关函数。

3、修改业务调用

java 复制代码
    private String queryLostProperty(String userId, String message) {
        StringBuilder sb = new StringBuilder();
        lostPropertyAssistant.queryLostProperty(userId, message)
                .doOnNext(sb::append)
                .blockLast();
        log.info("queryLostProperty:{}", sb);
        return sb.toString();
    }

4、测试

数据库中数据如下:

测试一下:

over。。。

相关推荐
新缸中之脑12 分钟前
编码代理的未来
人工智能
Anarkh_Lee20 分钟前
【小白也能实现智能问数智能体】使用开源的universal-db-mcp在coze中实现问数 AskDB智能体
数据库·人工智能·ai·开源·ai编程
达文汐21 分钟前
【困难】力扣算法题解析LeetCode332:重新安排行程
java·数据结构·经验分享·算法·leetcode·力扣
培风图南以星河揽胜22 分钟前
Java版LeetCode热题100之零钱兑换:动态规划经典问题深度解析
java·leetcode·动态规划
John_ToDebug31 分钟前
2026年展望:在技术涌现时代构筑确定性
人工智能·程序人生
AndyHeee41 分钟前
【windows使用TensorFlow,GPU无法识别问题汇总,含TensorFlow完整安装过程】
人工智能·windows·tensorflow
启山智软1 小时前
【中大企业选择源码部署商城系统】
java·spring·商城开发
我真的是大笨蛋1 小时前
深度解析InnoDB如何保障Buffer与磁盘数据一致性
java·数据库·sql·mysql·性能优化
jay神1 小时前
基于YOLOv8的木材表面缺陷检测系统
人工智能·深度学习·yolo·计算机视觉·毕业设计
交通上的硅基思维1 小时前
人工智能安全:风险、机制与治理框架研究
人工智能·安全·百度