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。。。

相关推荐
飞火流星020271 小时前
BERT、T5、ViT 和 GPT-3 架构概述及代表性应用
人工智能·gpt-3·bert·t5·vit·人工智能模型架构
程序小K1 小时前
自然语言处理Hugging Face Transformers
人工智能·自然语言处理
恒拓高科WorkPlus1 小时前
BeeWorks:打造安全可控的企业内网即时通讯平台
大数据·人工智能·安全
newxtc2 小时前
【指纹浏览器系列-chromium编译】
人工智能·安全
轻闲一号机2 小时前
【机器学习】机器学习笔记
人工智能·笔记·机器学习
光锥智能2 小时前
傅利叶发布首款开源人形机器人N1:开发者可实现完整复刻
人工智能
Hanson Huang2 小时前
【数据结构】堆排序详细图解
java·数据结构·排序算法·堆排序
慕容静漪3 小时前
如何本地安装Python Flask并结合内网穿透实现远程开发
开发语言·后端·golang
ErizJ3 小时前
Golang|锁相关
开发语言·后端·golang
恒拓高科WorkPlus3 小时前
一款安全好用的企业即时通讯平台,支持统一门户
大数据·人工智能·安全