2025/5/18

繼續研究一下大佬的RAG項目。開始我的碎碎念。

RAG可以分成兩部分:一個是問答,一個是數據處理。

問答是人提問,然后查數據庫,把查的東西用大模型組織成人話,回答人的提問。

數據處理是把當下知識庫里的東西(不管是什么類型的數據),全弄成計算機話(代碼能明白的格式)存到數據庫,然后方便人提問的時候(也就是問答)給出可以回答的知識。

如果想讓項目跑起來,必須把ES服務啟動起來,該項目是用ES存的數據。

項目啟動時,會先運行LoadStartup(在Springboot應用啟動時),初始化向量存儲(具體初始化向量存儲用vectorstorage的initCollection()方法,指定名稱和維度,向量維度是1024為了適配智譜AI)。總之就是自動初始化一個向量數據庫的集合(Collection),用于存儲后續的向量數據(如文本嵌入向量)。

我們看到LoadStartup類有一個注解@Component

所以@Service、@Repository等等這些注解,本質上都是@Component。只是根據層次有不同叫法。

這個collection是森馬樣子?回頭再寫吧。


首先,就是輸入的問題。我們要存的知識不一定是什么類型,可能使txt,可能是word,甚至是pdf。那我們就需要把輸入的東西先變成文本。

項目運行起來之前,點擊運行下載好的es的bin文件夾下elasticsearch.bat,啟動服務。

此時可以再終端看到可交互的shell命令行。這個應該是通過spring shell工具包實現的,項目的pom.xml文件里可以看到已經配置了shell的起步依賴。怎么用這個shell包呢?可以通過自己編寫java類,自己做命令。前面說過把RAG分成兩部分:問答,數據處理。使用add命令完成數據處理部分的工作,使用chat命令完成問答部分的工作。新建command文件夾來存放這兩個類:add命令類,chat命令類。

通過 @ShellMethod 注解將 Java 方法暴露為 Shell 命令。

@ShellMethod(value = "add local txt data")  // 聲明這是一個Shell命令,描述為"add local txt data"
public String add(String doc) {            // 定義命令方法,接收一個字符串參數doc(文件路徑或文本內容)log.info("start add doc.");            // 打印日志:開始處理文檔// 1. 文本分塊(Chunking)List<ChunkResult> chunkResults = txtChunk.chunk(doc);  // 調用分塊工具,將文檔拆分為多個文本塊// 2. 向量化(Embedding)List<EmbeddingResult> embeddingResults = zhipuAI.embedding(chunkResults);  // 使用智譜AI(或其他模型)將文本塊轉為向量// 3. 向量存儲String collection = vectorStorage.getCollectionName();  // 獲取向量數據庫的集合名(類似表名)vectorStorage.store(collection, embeddingResults);     // 將向量存儲到數據庫中log.info("finished");                  // 打印日志:處理完成return "finished docId:{}" + doc;      // 返回處理結果(格式有誤,應為String.format)
}

數據處理的三步:文本分塊、向量化、向量存儲。最后返回結果。

這幾步全調用方法,現在看是一個黑盒,知道輸入輸出和功能就行,后面再具體看黑盒里面的代碼。

doc參數是文件內容還是文件路徑搞不懂?試著輸出了doc,發現是文件名。但是,根據文件名就能找著??

發現有一個默認路徑/data,然后再默認路徑/data下找doc文件名。找一下哪里設置的默認路徑。

/data在chunk這里。

所以這個意思是,add 文件名。add這個方法就收到了參數doc文件名。然后進行文本分塊(數據處理的具體代碼放在/compoents文件夾),調用了chunk方法,然后根據默認路徑+文件名+.txt,就得到一條完整的路徑(相對路徑)。

讀取文件流classpathresource(path)

來回流轉的數據,封裝在對象中,而這些對象的代碼都放在/domain文件夾里。

明天再寫。


繼續這個chunk。

然后為什么要chunk?小塊文本比長文本更高效,節省計算資源。按照256個字符分割字符串。

AtomicInteger 是 Java 中一個線程安全的原子整數類,屬于 java.util.concurrent.atomic 包。它的核心作用是提供原子操作(不可中斷的單一操作),確保在多線程環境下對整數的操作(如遞增、遞減、賦值等)不會出現競態條件(Race Condition)。

很明顯,把每個chunk后的小塊文本封裝成一個chunkresult對象,然后返回這些對象構成的集合。

然后調用智譜AI的embedding方法。可以看到傳進去的參數是chunkresult對象的集合,返回的是embeddingresult的集合。具體看embedding方法里的代碼:觀察集合是否為空,空的話返回空集合;非空返回embedding后的集合(這里就有一個embedding方法了)。我們具體看這個embedding方法,上一個embedding返回的是集合,這個里面embedding方法返回的單個向量化后的結果。方法的重載,參數不同。說不明白,具體看代碼就懂了。

    /*** 批量* @param chunkResults 批量文本* @return 向量*/public List<EmbeddingResult> embedding(List<ChunkResult> chunkResults){log.info("start embedding,size:{}",CollectionUtil.size(chunkResults));if (CollectionUtil.isEmpty(chunkResults)){return new ArrayList<>();}List<EmbeddingResult> embeddingResults=new ArrayList<>();for (ChunkResult chunkResult:chunkResults){embeddingResults.add(this.embedding(chunkResult));}return embeddingResults;}public EmbeddingResult embedding(ChunkResult chunkResult){String apiKey= this.getApiKey();//log.info("zp-key:{}",apiKey);OkHttpClient.Builder builder = new OkHttpClient.Builder().connectTimeout(20000, TimeUnit.MILLISECONDS).readTimeout(20000, TimeUnit.MILLISECONDS).writeTimeout(20000, TimeUnit.MILLISECONDS).addInterceptor(new ZhipuHeaderInterceptor(apiKey));OkHttpClient okHttpClient = builder.build();EmbeddingResult embedRequest=new EmbeddingResult();embedRequest.setPrompt(chunkResult.getContent());embedRequest.setRequestId(Objects.toString(chunkResult.getChunkId()));// 智譜embeddingRequest request = new Request.Builder().url("https://open.bigmodel.cn/api/paas/v3/model-api/text_embedding/invoke").post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), GSON.toJson(embedRequest))).build();try {Response response= okHttpClient.newCall(request).execute();String result=response.body().string();ZhipuResult zhipuResult= GSON.fromJson(result, ZhipuResult.class);EmbeddingResult ret= zhipuResult.getData();ret.setPrompt(embedRequest.getPrompt());ret.setRequestId(embedRequest.getRequestId());return  ret;} catch (IOException e) {throw new RuntimeException(e);}}

前面embedding方法只是封裝成集合,就不看了。后面的embedding才是真正的向量化,重頭戲。(但是人家的API咱直接用就行,embedding具體回頭再看吧)

直接用的智譜的API,我們直接給參就好了。

先獲取密鑰。//咱們寫好的getapikey方法,而它里面是調用了LLmProperties里面的東西。(回頭再看吧,反正肯定這個注解指定有點東西//綁定前綴“llm”開頭的配置,然后再yaml配置文件里定義屬性)👇

使用 OkHttpClient.Builder 構建一個 HTTP 客戶端,配置了連接、讀取和寫入的超時時間(均為 20 秒)。

添加了一個自定義攔截器 ZhipuHeaderInterceptor,用于在請求頭中添加 API 密鑰等認證信息。


  • 創建一個?EmbeddingResult?對象作為請求體。

  • 設置?prompt?為輸入文本塊的內容(chunkResult.getContent())。

  • 設置?requestId?為文本塊的 ID(chunkResult.getChunkId()),轉換為字符串。

EmbeddingResult embedRequest=new EmbeddingResult();
embedRequest.setPrompt(chunkResult.getContent());
embedRequest.setRequestId(Objects.toString(chunkResult.getChunkId()));


我們在這里用到了一個攔截器。回頭再仔細看。

Lombok 注解:簡化代碼。比如@AllArgsConstructor注解,就是默認全參構造。

具體見:Lombok-CSDN博客

向量化返回的結果👇是地址。。。

數組變成字符串打印出來👇變成這樣的向量了。

理論上每個數組大小為1024,事實上也是。具體向量怎么算的,回頭看。

接下來把這些向量存起來。存在哪?怎么存?可以看到這回用到了vectorStorage,調用了它的store,參數是collectionName(下面講//可以get得到)和embedding后的向量。(最開始我們說該項目是用ES存的)

可以看到initCollection方法的兩個參數,一個是名字(固定前綴+時間),另一個是維度。傳進去這倆參數,會返回一個布爾值(T or F)。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/pingmian/81472.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/81472.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/81472.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

在 Vue 中插入 B 站視頻

前言 在 Vue 項目中&#xff0c;有時我們需要嵌入 B 站視頻來豐富頁面內容&#xff0c;為用戶提供更直觀的信息展示。本文將詳細介紹在 Vue 中插入 B 站視頻的多種方法。 使用<iframe>標簽直接嵌入,<iframe>標簽是一種簡單直接的方式&#xff0c;可將 B 站視頻嵌…

OpenCv高階(八)——攝像頭調用、攝像頭OCR

文章目錄 前言一、攝像頭調用通用方法1、導入必要的庫2、創建攝像頭接口 二、攝像頭OCR1.引入庫2、定義函數&#xff08;1&#xff09;定義顯示opencv顯示函數&#xff08;2&#xff09;保持寬高比的縮放函數&#xff08;3&#xff09;坐標點排序函數&#xff08;4&#xff09;…

特斯拉虛擬電廠:能源互聯網時代的分布式革命

在雙碳目標與能源轉型的雙重驅動下&#xff0c;特斯拉虛擬電廠&#xff08;Virtual Power Plant, VPP&#xff09;通過數字孿生技術與能源系統的深度融合&#xff0c;重構了傳統電力系統的運行范式。本文從系統架構、工程實踐、技術挑戰三個維度&#xff0c;深度解析這一顛覆性…

【漫話機器學習系列】258.拐點(Inflection Point)

拐點&#xff08;Inflection Point&#xff09;詳解&#xff1a;定義、原理與應用 在數學分析與數據建模中&#xff0c;“拐點&#xff08;Inflection Point&#xff09;”是一個非常重要的概念。今天這篇文章&#xff0c;我們將結合圖示&#xff0c;深入理解拐點的定義、數學…

語音識別——聲紋識別

通過將說話人的聲音與數據庫中的記錄聲音進行比對&#xff0c;判斷說話人是否為數據庫白名單中的同一人&#xff0c;從而完成語音驗證。目前&#xff0c;3D-Speaker 聲紋驗證的效果較為出色。 3D-Speaker 是一個開源工具包&#xff0c;可用于單模態和多模態的說話人驗證、說話…

DeepSeek 賦能軍事:重塑現代戰爭形態的科技密碼

目錄 一、引言&#xff1a;AI 浪潮下的軍事變革與 DeepSeek 崛起二、DeepSeek 技術原理與特性剖析2.1 核心技術架構2.2 獨特優勢 三、DeepSeek 在軍事偵察中的應用3.1 海量數據快速處理3.2 精準目標識別追蹤3.3 預測潛在威脅 四、DeepSeek 在軍事指揮決策中的應用4.1 戰場態勢實…

uWSGI是什么?

uWSGI 是一個功能強大的應用服務器&#xff0c;專為部署高性能 Web 應用設計&#xff0c;尤其適合 Python 生態系統。以下是對其核心介紹及適用場景的總結&#xff1a; uWSGI 是什么&#xff1f; uWSGI 是一個實現了 WSGI&#xff08;Web Server Gateway Interface&#xff09…

Digi XBee XR 系列介紹

Digi 延續了 20 多年來亞 GHz 射頻模塊的傳統&#xff0c;推出了 Digi XBee XR 系列遠距離模塊&#xff0c;包括 Digi XBee XR 900 - 已通過多個地區的預先認證 - 以及 Digi XBee XR 868 - 已通過歐洲地區應用的預先認證。 這些先進的射頻模塊專為遠距離抗干擾無線通信而設計。…

RabbitMq C++客戶端的使用

介紹 RabbitMQ 是一個開源的消息代理和隊列服務器&#xff0c;用于在分布式系統之間傳遞消息。它實現了高級消息隊列協議(AMQP)&#xff0c;同時也支持其他協議如 STOMP、MQTT 等。 核心概念 Producer(生產者): 發送消息的應用程序 Consumer(消費者): 接收消息的應用程序 Q…

HTML 中的 input 標簽詳解

HTML 中的 input 標簽詳解 一、基礎概念 1. 定義與作用 HTML 中的 <input> 標簽是表單元素的核心組件&#xff0c;用于創建各種用戶輸入字段。作為一個空標簽&#xff08;沒有閉合標簽&#xff09;&#xff0c;它通過 type 屬性來決定呈現何種輸入控件&#xff0c;是實…

基于Piecewise Jerk Speed Optimizer的速度規劃算法(附ROS C++/Python仿真)

目錄 1 時空解耦運動規劃2 PJSO速度規劃原理2.1 優化變量2.2 代價函數2.3 約束條件2.4 二次規劃形式 3 算法仿真3.1 ROS C仿真3.2 Python仿真 1 時空解耦運動規劃 在自主移動系統的運動規劃體系中&#xff0c;時空解耦的遞進式架構因其高效性與工程可實現性被廣泛采用。這一架…

2025云上人工智能安全發展研究

隨著人工智能&#xff08;AI&#xff09;技術與云計算的深度融合&#xff0c;云上AI應用場景不斷擴展&#xff0c;但安全挑戰也日益復雜。結合2025年的技術演進與行業實踐&#xff0c;云上AI安全發展呈現以下關鍵趨勢與應對策略&#xff1a; 一、云上AI安全的主要挑戰 數據泄露…

MCU裸機程序如何移植到RTOS?

目錄 1、裸機編程 2、實時操作系統 3、移植裸機程序到RTOS的步驟 步驟1&#xff1a;分析裸機代碼 步驟2&#xff1a;選擇并設置RTOS環境 步驟3&#xff1a;設計任務架構 步驟4&#xff1a;實現任務間通信 步驟5&#xff1a;處理硬件交互 步驟6&#xff1a;測試和調試 …

LangPDF: Empowering Your PDFs with Intelligent Language Processing

LangPDF: Empowering Your PDFs with Intelligent Language Processing Unlock Global Communication: AI-Powered PDF Translation and Beyond In an interconnected world, seamless multilingual document management is not just an advantage—it’s a necessity. LangP…

什么是dom?作用是什么

DOM 的定義 DOM&#xff08;Document Object Model&#xff0c;文檔對象模型&#xff09;是 HTML 和 XML 文檔的編程接口。它將文檔解析為一個由節點和對象組成的樹狀結構&#xff0c;允許開發者通過編程方式動態訪問和操作文檔的內容、結構和樣式。 DOM 的作用 DOM 的主要作…

當AI自我糾錯:一個簡單的“Wait“提示如何讓模型思考更深、推理更強

原論文&#xff1a;s1: Simple test-time scaling 作者&#xff1a;Niklas Muennighoff, Zitong Yang, Weijia Shi等&#xff08;斯坦福大學、華盛頓大學、Allen AI研究所、Contextual AI&#xff09; 論文鏈接&#xff1a;arXiv:2501.19393 代碼倉庫&#xff1a;GitHub - simp…

MYSQL之基本查詢(CURD)

表的增刪改查 表的增加 語法: INSERT [INTO] table_name [(column [, column] ...)] VALUES (value_list) [, (value_list)] ... value_list: value, [, value] ...全列插入和指定列插入 //創建一張學生表 CREATE TABLE students (id INT UNSIGNED PRIMARY KEY AUTO_INCREM…

STM32簡易計算機設計

運用 A0上拉按鈕和 A1 A2下拉按鈕設計按鍵功能 加上獨特的算法檢測設計&#xff0c;先計算&#xff08;&#xff09;內在計算乘除在計算加減的值在計算乘除優先級最后計算加減優先級 #include "stm32f10x.h" #include <stdio.h> #include <stdlib.h>…

sparkSQL讀入csv文件寫入mysql

思路 示例 &#xff08;年齡>18改成>20) mysql的字符集問題 把user改成person “讓字符集認識中文”

計算機視覺與深度學習 | Python 實現SO-CNN-BiLSTM多輸入單輸出回歸預測(完整源碼和源碼詳解)

SO-CNN-BiLSTM **一、代碼實現****1. 環境準備****2. 數據生成(示例數據)****3. 數據預處理****4. 模型構建****5. 模型訓練****6. 預測與評估****二、代碼詳解****1. 數據生成****2. 數據預處理****3. 模型架構****4. 訓練配置****5. 結果可視化****三、關鍵參數說明****四、…