最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

使用Java實現(xiàn)RAG(檢索增強生成)的完整指南

 更新時間:2026年04月26日 09:34:15   作者:花千樹_010  
RAG(Retrieval-Augmented Generation,檢索增強生成) 是目前最主流的企業(yè) AI 應(yīng)用模式,這篇文章主要為大家詳細(xì)介紹了使用Java實現(xiàn)RAG的相關(guān)方法,文中的示例代碼講解詳細(xì),有需要的小伙伴可以了解下

適合人群:需要構(gòu)建知識庫問答系統(tǒng)的 Java 開發(fā)者

核心技術(shù):RAG、向量數(shù)據(jù)庫 Milvus、文本 Embedding

什么是 RAG?

RAG(Retrieval-Augmented Generation,檢索增強生成) 是目前最主流的企業(yè) AI 應(yīng)用模式。

解決的問題:大模型的訓(xùn)練數(shù)據(jù)有截止日期,且不包含你的私有數(shù)據(jù)(內(nèi)部文檔、產(chǎn)品手冊、規(guī)章制度等)。RAG 的思路是:

用戶提問 → 在私有知識庫中檢索相關(guān)內(nèi)容 → 將檢索結(jié)果 + 問題一起發(fā)給 LLM → 得到基于私有知識的回答

優(yōu)勢

  • 無需微調(diào)模型,成本極低
  • 知識庫可隨時更新,實時生效
  • 可溯源,能告訴用戶答案來自哪個文檔

完整 RAG 流程

PDF/Word文檔
     ↓
[文檔加載器] PdfboxLoader / ApachePoiDocxLoader
     ↓
[文本切分器] StanfordNLPTextSplitter
     ↓
[Embedding 模型] OllamaEmbeddings
     ↓
[向量數(shù)據(jù)庫] Milvus(存儲)
     ↓ (查詢時)
用戶問題 → [向量檢索] → 相關(guān)文檔塊 → [LLM] → 最終回答

前置配置

RAG Pipeline 依賴 Milvus 向量數(shù)據(jù)庫和 Tesseract OCR,需要在 application.yml 中顯式開啟:

rag:
  ocr:
    tesseract:
      use: true   # 啟用 Tesseract OCR(PDF 圖片文字識別)
  vector:
    milvus:
      use: true   # 啟用 Milvus 向量數(shù)據(jù)庫

說明:j-langchain 通過 @ConditionalOnProperty 控制這兩個組件的初始化,默認(rèn)不加載。只有配置 use: true 后,TesseractActuatorMilvusContainer Bean 才會被注冊到 Spring 容器中。未開啟時運行 RAG 相關(guān)代碼會因 Bean 缺失而報錯。

Step 1:加載文檔

j-langchain 內(nèi)置多種文檔加載器:

加載 PDF

@Test
public void loadPdfDocuments() {
    PdfboxLoader loader = PdfboxLoader.builder()
        .filePath("./files/pdf/en/Transformer.pdf")
        .build();
    loader.setExtractImages(false);  // 不提取圖片,只提取文本

    List<Document> documents = loader.load();

    System.out.println("總頁數(shù):" + documents.size());
    // 每個 Document 對應(yīng) PDF 的一頁
}

加載 Word 文檔

ApachePoiDocxLoader loader = ApachePoiDocxLoader.builder()
    .filePath("./files/docx/en/Transformer.docx")
    .build();

List<Document> documents = loader.load();

每個 Document 對象包含:

  • pageContent:頁面文本內(nèi)容
  • metadata:來源、頁碼等元數(shù)據(jù)

Step 2:文本切分

PDF 文檔一頁可能有幾千字,直接 Embedding 效果差,而且超出 LLM 的 context window。需要將長文檔切分為小塊:

@Test
public void splitDocuments() {
    List<Document> documents = loader.load();
    System.out.println("切分前:" + documents.size() + " 頁");

    StanfordNLPTextSplitter splitter = StanfordNLPTextSplitter.builder()
        .chunkSize(1000)    // 每塊最多 1000 字符
        .chunkOverlap(100)  // 相鄰塊重疊 100 字符,保證上下文連貫
        .build();

    List<Document> splits = splitter.splitDocument(documents);
    System.out.println("切分后:" + splits.size() + " 塊");
}

為什么需要 chunkOverlap?

如果一句話跨兩個塊,重疊部分確保這句話完整出現(xiàn)在至少一個塊中,避免語義截斷。

Step 3:向量化并存入 Milvus

將每個文本塊轉(zhuǎn)換為向量(浮點數(shù)數(shù)組),存入向量數(shù)據(jù)庫:

@Test
public void embedAndStore() {
    // ... 加載、切分文檔 ...

    VectorStore vectorStore = Milvus.fromDocuments(
        splits,
        OllamaEmbeddings.builder()
            .model("nomic-embed-text")  // 本地 Embedding 模型,免費
            .vectorSize(768)            // 向量維度
            .build(),
        "MyKnowledgeBase"               // Milvus collection 名稱
    );

    System.out.println("向量化完成!");
}

為什么用本地 Embedding?

nomic-embed-text 是一個高質(zhì)量的開源 Embedding 模型,通過 Ollama 本地運行:

  • 零成本:不需要調(diào) OpenAI API
  • 隱私安全:數(shù)據(jù)不出本地
  • 效果好:在中英文 Embedding 上表現(xiàn)優(yōu)秀

啟動 Milvus(Docker 一鍵啟動):

docker run -d --name milvus \
  -p 19530:19530 \
  milvusdb/milvus:latest standalone

Step 4:完整 RAG 問答鏈

這是核心步驟:用用戶的問題檢索相關(guān)文檔塊,拼接上下文,讓 LLM 基于上下文回答:

@Test
public void retrieveAndAsk() {
    // 假設(shè)文檔已經(jīng)存入 Milvus...
    BaseRetriever retriever = vectorStore.asRetriever();

    BaseRunnable<StringPromptValue, ?> prompt = PromptTemplate.fromTemplate(
        """
        請根據(jù)以下文檔內(nèi)容回答問題。如果文檔中沒有相關(guān)信息,請說"文檔中未找到相關(guān)信息"。
        
        文檔內(nèi)容:
        ${context}
        
        問題:${question}
        
        回答:
        """
    );

    Function<Object, String> formatDocs = input -> {
        List<Document> docs = (List<Document>) input;
        StringBuilder sb = new StringBuilder();
        for (Document doc : docs) {
            sb.append(doc.getPageContent()).append("\n\n");
        }
        return sb.toString();
    };

    FlowInstance ragChain = chainActor.builder()
        .next(retriever)   // 向量檢索:輸入問題,返回相關(guān)文檔列表
        .next(formatDocs)  // 將文檔列表拼接為字符串
        .next(input -> Map.of(
            "context",  input,
            "question", ContextBus.get().getFlowParam()  // 獲取原始問題
        ))
        .next(prompt)
        .next(llm)
        .next(new StrOutputParser())
        .build();

    ChatGeneration result = chainActor.invoke(
        ragChain,
        "Transformer 模型中的注意力機制是如何工作的?"
    );

    System.out.println(result.getText());
}

鏈路圖解

"Transformer注意力機制..." 
    → retriever(相似度檢索,返回最相關(guān)的5個文檔塊)
    → formatDocs(拼接文檔塊為字符串)
    → prompt(組裝 Prompt:上下文 + 問題)
    → LLM(基于上下文生成回答)
    → StrOutputParser(提取文本)
    → "注意力機制通過計算 Query、Key、Value..."

Step 5:文檔摘要(輕量版)

不需要向量庫的簡單場景——直接讓 LLM 讀文檔摘要:

@Test
public void documentSummary() {
    // 加載 PDF
    List<Document> documents = loader.load();
    String content = documents.stream()
        .map(Document::getPageContent)
        .collect(Collectors.joining("\n"));

    // 長文檔截取首尾
    String textToSummarize = content.length() < 2000 ? content
        : content.substring(0, 1000) + "\n...\n" + content.substring(content.length() - 1000);

    FlowInstance chain = chainActor.builder()
        .next(PromptTemplate.fromTemplate("請對以下內(nèi)容摘要(100字以內(nèi)):\n\n${text}"))
        .next(ChatOllama.builder().model("qwen2.5:0.5b").build())
        .next(new StrOutputParser())
        .build();

    ChatGeneration result = chainActor.invoke(chain, Map.of("text", textToSummarize));
    System.out.println(result.getText());
}

RAG vs 直接問 LLM

對比項直接問 LLMRAG
私有知識不知道知道(來自你的文檔)
知識時效性訓(xùn)練截止日期實時更新
回答可溯源不行可以(返回來源文檔)
成本稍高(Embedding + 向量庫)
幻覺風(fēng)險低(基于真實文檔)

完整架構(gòu)

離線階段(建庫):
文檔 → 加載 → 切分 → Embedding → Milvus

在線階段(問答):
問題 → Embedding → Milvus檢索 → 拼接上下文 → LLM → 回答

到此這篇關(guān)于使用Java實現(xiàn)RAG(檢索增強生成)的完整指南的文章就介紹到這了,更多相關(guān)Java實現(xiàn)RAG內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 滴滴二面之Kafka如何讀寫副本消息的

    滴滴二面之Kafka如何讀寫副本消息的

    這篇文章主要給大家介紹了關(guān)于滴滴二面之Kafka如何讀寫副本消息的相關(guān)資料,文中通過實例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2022-01-01
  • Java實現(xiàn)中序表達式的實例代碼

    Java實現(xiàn)中序表達式的實例代碼

    這篇文章主要介紹了Java實現(xiàn)中序表達式的實例代碼,需要的朋友可以參考下
    2018-08-08
  • springboot項目同時啟動web服務(wù)和grpc服務(wù)的方法

    springboot項目同時啟動web服務(wù)和grpc服務(wù)的方法

    本文主要介紹了springboot項目同時啟動web服務(wù)和grpc服務(wù)的方法,通過實際代碼示例展示了實現(xiàn),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2024-02-02
  • 詳解MyBatis動態(tài)代理機制

    詳解MyBatis動態(tài)代理機制

    MyBatis的動態(tài)代理機制是其核心特性之一,通過該機制,開發(fā)者可以專注于定義接口和 SQL 映射,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2026-03-03
  • Java如何實現(xiàn)支付寶電腦支付基于servlet版本

    Java如何實現(xiàn)支付寶電腦支付基于servlet版本

    這篇文章主要介紹了Java如何實現(xiàn)支付寶電腦支付基于servlet版本,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用場景分析

    SpringBoot 攔截器 (Interceptor)與切面 (AOP)示例、作用及適用

    攔截器是SpringMVC框架的組件,基于Java動態(tài)代理實現(xiàn),作用于Web層(Controller 層),僅能攔截HTTP請求的處理過程,生命周期與 SpringMVC的請求處理流程綁定,本文介紹SpringBoot攔截器 (Interceptor)與切面(AOP)示例、作用及適用場景分析,感興趣的朋友一起看看吧
    2026-01-01
  • Java并發(fā)編程中的ConcurrentLinkedQueue詳解

    Java并發(fā)編程中的ConcurrentLinkedQueue詳解

    這篇文章主要介紹了Java并發(fā)編程中的ConcurrentLinkedQueue詳解,GetThread線程不會因為ConcurrentLinkedQueue隊列為空而等待,而是直接返回null,所以當(dāng)實現(xiàn)隊列不空時,等待時,則需要用戶自己實現(xiàn)等待邏輯,需要的朋友可以參考下
    2023-12-12
  • Springboot整合通用mapper過程解析

    Springboot整合通用mapper過程解析

    這篇文章主要介紹了springboot整合通用mapper過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-11-11
  • Android中幾種圖片特效的處理的實現(xiàn)方法

    Android中幾種圖片特效的處理的實現(xiàn)方法

    這篇文章主要介紹了 Android中幾種圖片特效的處理的實現(xiàn)方法的相關(guān)資料,這里有放大縮小圖片,獲得圓角圖片,獲得帶倒影圖片的幾種方法,需要的朋友可以參考下
    2017-08-08
  • 詳解Spring Batch 輕量級批處理框架實踐

    詳解Spring Batch 輕量級批處理框架實踐

    這篇文章主要介紹了詳解Spring Batch 輕量級批處理框架實踐,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-06-06

最新評論

海安县| 正阳县| 康定县| 米泉市| 拉孜县| 修武县| 宜昌市| 文水县| 五家渠市| 黔东| 蓬溪县| 江北区| 湘潭县| 清徐县| 钟山县| 柘荣县| 冕宁县| 安达市| 南阳市| 辽阳市| 潼关县| 浙江省| 大安市| 封丘县| 香港 | 肥西县| 青铜峡市| 平远县| 石楼县| 句容市| 红河县| 繁昌县| 沭阳县| 张家港市| 沾化县| 五指山市| 祁连县| 西乡县| 邯郸县| 岱山县| 烟台市|