获取向量模型


向量数据库
📊 主流向量数据库概览
相关依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-advisors-vector-store</artifactId> </dependency>
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-markdown-document-reader</artifactId> </dependency>
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pdf-document-reader</artifactId> </dependency>
|
RagController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentReader; import org.springframework.ai.ollama.OllamaEmbeddingModel; import org.springframework.ai.reader.TextReader; import org.springframework.ai.reader.markdown.MarkdownDocumentReader; import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux;
import java.util.List;
@Slf4j @RestController @RequestMapping("/rag") public class RagController {
@Resource private OllamaEmbeddingModel ollamaEmbeddingModel;
@Resource private VectorStore vectorStore;
@Resource private ChatClient ollamaChatChatClient;
@RequestMapping("/test1") public String test1() { float[] embedded = ollamaEmbeddingModel.embed("我是中国人"); log.info("长度:{},内容:{}", embedded.length, embedded); return "success"; }
@RequestMapping("/test2") public String test2() { saveData2VectorStore(); List<Document> documents = vectorStore.similaritySearch("鼠标多少钱?"); documents.forEach(item -> { log.info("检索内容:{},得分:{}", item.getText(), item.getScore()); });
return null; }
private void saveData2VectorStore() { Document doc = Document.builder().text(""" 咨询服务费用: - 每小时100元 """).build(); vectorStore.add(List.of(doc)); doc = Document.builder().text(""" 商品价格: - 每个100元 """).build(); vectorStore.add(List.of(doc)); }
@RequestMapping(value = "/test3", produces = "text/stream;charset=utf8") public Flux<String> test3() { saveData2VectorStore(); String message = "鼠标多少钱?"; return ollamaChatChatClient.prompt().user("鼠标多少钱?").advisors( SimpleLoggerAdvisor.builder().build(), QuestionAnswerAdvisor.builder(vectorStore).searchRequest(SearchRequest.builder().query(message).similarityThreshold(0.5).topK(1).build()).build()).stream().content(); }
@Value("classpath:rag/test.txt") private org.springframework.core.io.Resource txtResource;
@RequestMapping(value = "/txt", produces = "text/stream;charset=utf8") public void txt() { DocumentReader reader = new TextReader(txtResource); List<Document> documents = reader.read(); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); }
@Value("classpath:rag/test.md") private org.springframework.core.io.Resource mdResource;
@RequestMapping(value = "/md", produces = "text/stream;charset=utf8") public void md() {
MarkdownDocumentReaderConfig readerConfig = MarkdownDocumentReaderConfig.builder() .withHorizontalRuleCreateDocument(true) .withIncludeBlockquote(true) .withIncludeCodeBlock(true) .build(); DocumentReader reader = new MarkdownDocumentReader(mdResource, readerConfig); List<Document> documents = reader.read(); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); }
@Value("classpath:rag/textsplit.txt") private org.springframework.core.io.Resource textSplit;
@RequestMapping(value = "/textSplitter", produces = "text/stream;charset=utf8") public void textSplitter() { DocumentReader reader = new TextReader(textSplit); List<Document> documents = reader.read(); TokenTextSplitter splitter = new TokenTextSplitter(200, 100, 10, 5000, true); documents = splitter.apply(documents); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); } }
|
TokenTextSplitter
场景分析与策略推荐
1. 通用文档检索与问答
场景:处理混合型知识库文档(如产品手册、公司wiki、综合文章),用于构建RAG系统进行问答。
目标:在信息完整性和检索精度间取得平衡。
推荐策略:
2. 法律文档与合同分析
场景:处理法律条文、合同条款、法规文件。
特点:文本结构严谨,逻辑关系紧密,术语定义精确。
推荐策略:
分块大小:256-512 tokens
重叠大小:50-100 tokens
额外建议:优先按自然段落分割,保持条款完整性
理由:较小的分块提高法律条文检索的精确度。
3. 学术论文与技术文档
场景:科研论文、技术规范、API文档处理。
特点:包含公式、代码、图表引用,结构层次分明。
推荐策略:
分块大小:800-1200 tokens
重叠大小:150-250 tokens
额外建议:尊重章节边界,保持技术概念的完整性
理由:较大的分块确保复杂技术概念的完整表达。
4. 对话记录与聊天分析
场景:客服对话、会议记录、聊天日志分析。
特点:多轮对话,上下文依赖性强,话轮转换明显。
推荐策略:
分块大小:200-400 tokens
重叠大小:包含完整的对话轮次
额外建议:按对话主题或时间窗口分割
理由:较小的分块匹配对话的自然单元。
5. 代码分析与程序理解
场景:源代码分析、代码文档生成。
特点:语法结构严格,函数/方法为自然单元。
推荐策略:
分块大小:按函数/方法单元,而非固定token数
重叠大小:0-50 tokens
额外建议:优先保持代码结构的完整性
理由:代码的理解依赖于完整的语法结构。
6. 新闻文章与博客内容
场景:新闻聚合、内容推荐、舆情分析。
⚙️ 实践配置示例
法律文档处理的Spring AI配置:
1 2 3 4 5 6 7
| TokenTextSplitter legalSplitter = new TokenTextSplitter.Builder() .defaultChunkSize(400) .chunkOverlap(80) .minChunkSizeChars(200) .keepSeparator(true) .maxNumChunks(5000) .build();
|
技术文档处理的配置:
1 2 3 4 5 6
| TokenTextSplitter techSplitter = new TokenTextSplitter.Builder() .defaultChunkSize(1000) .chunkOverlap(200) .minChunkSizeChars(500) .keepSeparator(true) .build();
|
获取向量模型


向量数据库
📊 主流向量数据库概览
相关依赖
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-advisors-vector-store</artifactId> </dependency>
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-markdown-document-reader</artifactId> </dependency>
<dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-pdf-document-reader</artifactId> </dependency>
|
RagController
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
| import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.ai.chat.client.ChatClient; import org.springframework.ai.chat.client.advisor.SimpleLoggerAdvisor; import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor; import org.springframework.ai.document.Document; import org.springframework.ai.document.DocumentReader; import org.springframework.ai.ollama.OllamaEmbeddingModel; import org.springframework.ai.reader.TextReader; import org.springframework.ai.reader.markdown.MarkdownDocumentReader; import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig; import org.springframework.ai.transformer.splitter.TokenTextSplitter; import org.springframework.ai.vectorstore.SearchRequest; import org.springframework.ai.vectorstore.VectorStore; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import reactor.core.publisher.Flux;
import java.util.List;
@Slf4j @RestController @RequestMapping("/rag") public class RagController {
@Resource private OllamaEmbeddingModel ollamaEmbeddingModel;
@Resource private VectorStore vectorStore;
@Resource private ChatClient ollamaChatChatClient;
@RequestMapping("/test1") public String test1() { float[] embedded = ollamaEmbeddingModel.embed("我是中国人"); log.info("长度:{},内容:{}", embedded.length, embedded); return "success"; }
@RequestMapping("/test2") public String test2() { saveData2VectorStore(); List<Document> documents = vectorStore.similaritySearch("鼠标多少钱?"); documents.forEach(item -> { log.info("检索内容:{},得分:{}", item.getText(), item.getScore()); });
return null; }
private void saveData2VectorStore() { Document doc = Document.builder().text(""" 咨询服务费用: - 每小时100元 """).build(); vectorStore.add(List.of(doc)); doc = Document.builder().text(""" 商品价格: - 每个100元 """).build(); vectorStore.add(List.of(doc)); }
@RequestMapping(value = "/test3", produces = "text/stream;charset=utf8") public Flux<String> test3() { saveData2VectorStore(); String message = "鼠标多少钱?"; return ollamaChatChatClient.prompt().user("鼠标多少钱?").advisors( SimpleLoggerAdvisor.builder().build(), QuestionAnswerAdvisor.builder(vectorStore).searchRequest(SearchRequest.builder().query(message).similarityThreshold(0.5).topK(1).build()).build()).stream().content(); }
@Value("classpath:rag/test.txt") private org.springframework.core.io.Resource txtResource;
@RequestMapping(value = "/txt", produces = "text/stream;charset=utf8") public void txt() { DocumentReader reader = new TextReader(txtResource); List<Document> documents = reader.read(); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); }
@Value("classpath:rag/test.md") private org.springframework.core.io.Resource mdResource;
@RequestMapping(value = "/md", produces = "text/stream;charset=utf8") public void md() {
MarkdownDocumentReaderConfig readerConfig = MarkdownDocumentReaderConfig.builder() .withHorizontalRuleCreateDocument(true) .withIncludeBlockquote(true) .withIncludeCodeBlock(true) .build(); DocumentReader reader = new MarkdownDocumentReader(mdResource, readerConfig); List<Document> documents = reader.read(); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); }
@Value("classpath:rag/textsplit.txt") private org.springframework.core.io.Resource textSplit;
@RequestMapping(value = "/textSplitter", produces = "text/stream;charset=utf8") public void textSplitter() { DocumentReader reader = new TextReader(textSplit); List<Document> documents = reader.read(); TokenTextSplitter splitter = new TokenTextSplitter(200, 100, 10, 5000, true); documents = splitter.apply(documents); documents.forEach(item -> { log.info("内容:{}", item.getText()); }); } }
|
TokenTextSplitter
场景分析与策略推荐
1. 通用文档检索与问答
场景:处理混合型知识库文档(如产品手册、公司wiki、综合文章),用于构建RAG系统进行问答。
目标:在信息完整性和检索精度间取得平衡。
推荐策略:
2. 法律文档与合同分析
场景:处理法律条文、合同条款、法规文件。
特点:文本结构严谨,逻辑关系紧密,术语定义精确。
推荐策略:
分块大小:256-512 tokens
重叠大小:50-100 tokens
额外建议:优先按自然段落分割,保持条款完整性
理由:较小的分块提高法律条文检索的精确度。
3. 学术论文与技术文档
场景:科研论文、技术规范、API文档处理。
特点:包含公式、代码、图表引用,结构层次分明。
推荐策略:
分块大小:800-1200 tokens
重叠大小:150-250 tokens
额外建议:尊重章节边界,保持技术概念的完整性
理由:较大的分块确保复杂技术概念的完整表达。
4. 对话记录与聊天分析
场景:客服对话、会议记录、聊天日志分析。
特点:多轮对话,上下文依赖性强,话轮转换明显。
推荐策略:
分块大小:200-400 tokens
重叠大小:包含完整的对话轮次
额外建议:按对话主题或时间窗口分割
理由:较小的分块匹配对话的自然单元。
5. 代码分析与程序理解
场景:源代码分析、代码文档生成。
特点:语法结构严格,函数/方法为自然单元。
推荐策略:
分块大小:按函数/方法单元,而非固定token数
重叠大小:0-50 tokens
额外建议:优先保持代码结构的完整性
理由:代码的理解依赖于完整的语法结构。
6. 新闻文章与博客内容
场景:新闻聚合、内容推荐、舆情分析。
⚙️ 实践配置示例
法律文档处理的Spring AI配置:
1 2 3 4 5 6 7
| TokenTextSplitter legalSplitter = new TokenTextSplitter.Builder() .defaultChunkSize(400) .chunkOverlap(80) .minChunkSizeChars(200) .keepSeparator(true) .maxNumChunks(5000) .build();
|
技术文档处理的配置:
1 2 3 4 5 6
| TokenTextSplitter techSplitter = new TokenTextSplitter.Builder() .defaultChunkSize(1000) .chunkOverlap(200) .minChunkSizeChars(500) .keepSeparator(true) .build();
|