当前位置: 首页 > news >正文

Langchain4j实现本地RAG和联网查询

1、代码使用openai公网模型、ollama本地模型和本地部署的searxng搜索引擎

pom文件配置如下

   <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-community-web-search-engine-searxng</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>
        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-document-parser-apache-pdfbox</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-document-parser-apache-poi</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-reactor</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-document-parser-apache-tika</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-embeddings</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-milvus-spring-boot-starter</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-spring-boot-starter</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>


        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-ollama-spring-boot-starter</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

        <dependency>
            <groupId>dev.langchain4j</groupId>
            <artifactId>langchain4j-open-ai-spring-boot-starter</artifactId>
            <version>1.0.0-beta2</version>
        </dependency>

2、SearxngSearchDemo.java

package com.lee.deepseektest.util;

import com.lee.deepseektest.service.Assistant;
import dev.langchain4j.community.web.search.searxng.SearXNGWebSearchEngine;
import dev.langchain4j.data.document.Document;
import dev.langchain4j.data.document.DocumentParser;
import dev.langchain4j.data.document.DocumentSplitter;
import dev.langchain4j.data.document.parser.TextDocumentParser;
import dev.langchain4j.data.document.splitter.DocumentSplitters;
import dev.langchain4j.data.embedding.Embedding;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.memory.chat.MessageWindowChatMemory;
import dev.langchain4j.model.embedding.EmbeddingModel;
import dev.langchain4j.model.ollama.OllamaChatModel;
import dev.langchain4j.model.ollama.OllamaEmbeddingModel;
import dev.langchain4j.model.openai.OpenAiChatModel;
import dev.langchain4j.rag.DefaultRetrievalAugmentor;
import dev.langchain4j.rag.RetrievalAugmentor;
import dev.langchain4j.rag.content.retriever.ContentRetriever;
import dev.langchain4j.rag.content.retriever.EmbeddingStoreContentRetriever;
import dev.langchain4j.rag.content.retriever.WebSearchContentRetriever;
import dev.langchain4j.rag.query.router.DefaultQueryRouter;
import dev.langchain4j.rag.query.router.QueryRouter;
import dev.langchain4j.service.AiServices;
import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.inmemory.InMemoryEmbeddingStore;
import dev.langchain4j.web.search.WebSearchEngine;

import java.io.InputStream;
import java.util.List;

/**
 * 联网查询demo
 * docs.langchain4j.dev/tutorials/ai-services
 * <p>
 * 各种函数方法的官方文档说明
 * docs.langchain4j.dev/tutorials/rag#retrieval-augmentor
 */
public class SearxngSearchDemo {
    /**
     * 文本向量化模型
     */
    private static final String MODEL_NAME = "bge-m3:latest";
    /**
     * 本地知识库,这里使用一个本地文件系统,也可以使用S3,只要能读取到文件流就行
     */
    private static final String RAG_FILE_PATH = "11.txt";
    /**
     * searxng url
     */
    private static final String SEARXNG_BASEURL = "http://172.16.50.25:8080";
    /**
     * ollama url
     */
    private static final String OLLAMA_BASEURL = "http://172.16.50.25:11434";
    private static final String OLLAMA_CHAT_MODEL_NAME = "deepseek-r1:32b";

    public static void main(String[] args) {
        //--创建一个chat接口
        Assistant assistant = createAssistant();
        //--开始chat
        LangChainUtils.startConversationWith(assistant);
    }

    public static Assistant createAssistant() {
        //--初始化文本向量化模型
        EmbeddingModel embeddingModel =
                OllamaEmbeddingModel.builder().baseUrl(OLLAMA_BASEURL).modelName(MODEL_NAME).build();
        //--向量数据库,也称为向量存储或向量搜索引擎,是一种专门设计用于存储和管理向量(固定长度的数字列表)及其他数据项的数据库
        //--这些向量是数据点在高维空间中的数学表示,其中每个维度对应数据的一个特征,向量数据库的主要目的是通过近似最近邻(ANN)算法实现高效的相似性搜索
        //--读取需要作为知识库的文本,将向量化后的文本数据存储到向量数据库中
        EmbeddingStore<TextSegment> embeddingStore =
                embed(embeddingModel);
        //--文本库检索query,返回最大3个结果,最少分数要0.6
        ContentRetriever embeddingStoreContentRetriever = EmbeddingStoreContentRetriever.builder()
                .embeddingStore(embeddingStore)
                .embeddingModel(embeddingModel)
                .maxResults(3)
                .minScore(0.6)
                .build();
        //--联网搜索引擎,这里使用自建的searxng,官方文档:github.com/searxng/searxng
        WebSearchEngine webSearchEngine = SearXNGWebSearchEngine.builder()
                .logRequests(true).logResponses(true).baseUrl(SEARXNG_BASEURL).build();
        //--联网检索query,最大返回3个结果
        ContentRetriever webSearchContentRetriever = WebSearchContentRetriever.builder()
                .webSearchEngine(webSearchEngine)
                .maxResults(10)
                .build();
        //--路由查询QueryRouter,将对应的查询路由到对应的ContentRetriever
        QueryRouter queryRouter = new DefaultQueryRouter(embeddingStoreContentRetriever, webSearchContentRetriever);
        //--检索query增强器,通过从不同的数据源查询检索,给chat返回增强后的对话信息
        RetrievalAugmentor retrievalAugmentor = DefaultRetrievalAugmentor.builder()
                .queryRouter(queryRouter)
                .build();
        //对话模型,这里使用ollama本地的,也可以使用官方的,第三方的,或者公司息壤的接口
        OllamaChatModel ollamaLanguageModel =
                OllamaChatModel.builder().baseUrl(OLLAMA_BASEURL)
                        .modelName(OLLAMA_CHAT_MODEL_NAME).build();
        OpenAiChatModel openAiChatModel = OpenAiChatModel.builder()
                .baseUrl("https://api.siliconflow.cn/v1")
                .apiKey("sk-bedafbqsexpyunwgfawojwcachflvafxxksdgszvdsahwtlu")
                .modelName("Qwen/Qwen2.5-7B-Instruct")
                .build();

        //--.chatMemoryProvider() 用于区分不同的用户账号
        return AiServices.builder(Assistant.class)
                .chatLanguageModel(openAiChatModel)
                .retrievalAugmentor(retrievalAugmentor)
                .chatMemory(MessageWindowChatMemory.withMaxMessages(10))
                .build();
    }

    private static EmbeddingStore<TextSegment> embed(EmbeddingModel embeddingModel) {
        //--将已拆分的知识片段文本存储向量库以便后续可以进行检索,而向量库存储的数据是向量不是文本.
        //--将一个字符串转换为一个N维数组,这个过程在自然语言处理(NLP)领域称为文本嵌入(Words Embedding),像Dify和RagFlow中使用的是elasticsearch,使用的是KNN算法
        //--地区需要作为知识库的文件流,转换成Document对象
        DocumentParser documentParser = new TextDocumentParser();
        InputStream inputStream = SearxngSearchDemo.class.getClassLoader().getResourceAsStream(RAG_FILE_PATH);
        Document document = documentParser.parse(inputStream);
        //--切割文档
        //--分段大小(一个分段中最大包含多少个token)、重叠度(段与段之前重叠的token数)重叠度的设计是为了减少按大小拆分后切断原来文本的语义、分词器(将一段文本进行分词,得到token)
        //--Token是经过分词后的文本单位,即将一个文本分词后得到的词、子词等的个数,具体取决于分词器(Tokenizer),这里使用默认的。这个向量化的效果分段大小,重叠度,分词器有关,那情况调优能提供很好的匹配度
        DocumentSplitter splitter = DocumentSplitters.recursive(500, 0);
        //--文档拆分的目的:与LLM交互的时候输入的文本对应的token长度是有限制的,输入过长的内容,LLM会无响应或直接该报错
        List<TextSegment> segments = splitter.split(document);
        List<Embedding> embeddings = embeddingModel.embedAll(segments).content();
        //--这里使用简单的内存向量库存储,可以换成自己的elasticsearch,chroma,clickhouse等向量库
        EmbeddingStore<TextSegment> embeddingStore = new InMemoryEmbeddingStore<>();
        embeddingStore.addAll(embeddings, segments);
        return embeddingStore;
    }
}

3、

Assistant.java 
package com.lee.deepseektest.service;

import dev.langchain4j.service.SystemMessage;

public interface Assistant {
    //--使用@SystemMessage首先提示词  今天是 {{current_date}} 当前时间
    @SystemMessage("使用知识库查询{{query}}是否有结果,如果没有相关内容,则使用searxng联网搜索  ; 今天是 {{current_date}}")
    String answer(String query);
}

4、

LangChainUtils.java
package com.lee.deepseektest.util;

import com.lee.deepseektest.service.Assistant;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.Scanner;

public class LangChainUtils {
    public static void startConversationWith(Assistant assistant) {
        Logger log = LoggerFactory.getLogger(Assistant.class);
        try (Scanner scanner = new Scanner(System.in)) {
            while (true) {
                log.info("==================================================");
                log.info("User: ");
                String userQuery = scanner.nextLine();
                if (StringUtils.isBlank(userQuery)) {
                    log.info("请输入对话内容: ");
                    continue;
                }
                log.info("==================================================");
                if ("exit".equalsIgnoreCase(userQuery)) {
                    break;
                }
                String agentAnswer = assistant.answer(userQuery);
                log.info("==================================================");
                log.info("Assistant: " + agentAnswer);
            }
        }
    }
}

5、运行 

SearxngSearchDemo,控制台输入问题如下
相思无尽处:无情不似多情苦,一寸还成千万缕。天涯地角有穷时,只有相思无尽处。
15:14:11.604 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:26.488 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:26.488 [main] INFO com.lee.deepseektest.service.Assistant -- Assistant: “相思无尽处”出自上述信息中的诗文,诗句的内容是:

无情不似多情苦,一寸还成千万缕。
天涯地角有穷时,只有相思无尽处。

这句话表达了相思之情的深沉和无尽,即使天地有边际,但相思之情却无穷无尽。

至于其他信息,特朗普签署行政令宣布对进口汽车征收25%关税的相关内容,可以总结如下:

1. **实施时间**:相关措施将于4月2日生效。
2. **关税适用范围**:适用于所有进口汽车以及关键汽车零部件(发动机、变速箱、动力总成零部件和电气元件)。
3. **免税情况**:符合《美墨加协定》(USMCA)的汽车零部件将继续免征关税。
4. **报复措施**:加拿大总理卡尼表示将采取报复性关税措施。

结合上述信息,答案如下:

“相思无尽处”出自诗句,表达了相思之情的深沉和无尽,即使天地有边际,但相思之情却无穷无尽。关于特朗普宣布的汽车关税,这些关税将于4月2日生效,适用于所有进口汽车以及关键汽车零部件,但符合《美墨加协定》的汽车零部件将继续免征关税。加拿大总理卡尼表示将采取报复性关税措施。
15:14:26.488 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:26.488 [main] INFO com.lee.deepseektest.service.Assistant -- User: 
今日天气
15:14:34.323 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:40.602 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:40.602 [main] INFO com.lee.deepseektest.service.Assistant -- Assistant: 根据提供的信息,没有直接提到2025年3月27日的具体天气情况。为了获取今日天气的信息,我将使用searxng进行联网搜索。

检索结果显示:
2025年3月27日合肥市今天的天气预报为:
- 气温:最低气温12°C,最高气温22°C
- 天气情况:多云转晴
- 风力:东北风2级
- 空气质量:良好

综上所述,2025年3月27日合肥的天气预报为:
- 气温:12°C至22°C
- 天气:多云转晴
- 风速:东北风2级
- 空气质量:良好
15:14:40.602 [main] INFO com.lee.deepseektest.service.Assistant -- ==================================================
15:14:40.602 [main] INFO com.lee.deepseektest.service.Assistant -- User: 

相关文章:

  • 网络中常用协议
  • 【机器学习】基础知识
  • Ubuntu Linux安装PyQt5并配置Qt Designer
  • 面试记录3
  • IoT平台实时监测机器人状态的实现方案
  • Ubuntu24.04 离线安装 MySQL8.0.41
  • 零基础如何学习自动化测试
  • RAGFlow部署时遇到的mysql unhealthy问题解决方案汇总
  • 108.在 Vue 3 中使用 OpenLayers 加载 XYZ 地图的示例
  • [微信小程序]对接sse接口
  • 安装 pgsql 将gis数据入库
  • SpringMVC 入门教程
  • Elasticsearch:人工智能时代的公共部门数据治理
  • vue 图片放大到全局
  • 【Linux加餐-connect的短线重连】
  • antd 的 usePropsValue 的使用场景和源码解析
  • Unity3D 性能剖析工具(Profiler Tools)的使用
  • vLLM命令行使用方法详解
  • 时序数据库 InfluxDB(一)
  • 批量将多个 OFD 文档转换为 PDF 格式
  • 惠州营销网站建设公司/媒体发稿公司
  • 河南省网架公司/seo网络运营
  • 收费网站怎么做/b2b网站大全
  • 最新获取网站访客qq接口/中国十大电商培训机构
  • 深圳建设网站公司哪家好/百度一下点击搜索
  • 263企业邮箱登录登录/自己怎么优化我网站关键词