个人随笔
目录
SpringAI2.0RAG的简单使用
2026-11-04 22:25:19

检索增强生成(RAG)是一种有助于克服大型语言模型局限性的技术,这些局限性主要体现在处理长篇内容、确保事实准确性以及保持上下文感知能力方面。
Spring AI 使用AdvisorAPI为常见的 RAG 流程提供开箱即用的支持。

一、简单理解流程

1、获取用户输入
2、将用户输入调用模型转成向量
3、根据向量去向量数据库查询相似的内容
4、一起把内容发送到大模型
5、返回结果

二、简单例子

向量数据库就用上节用的内存数据库

1、依赖

  1. <dependency>
  2. <groupId>org.springframework.ai</groupId>
  3. <artifactId>spring-ai-vector-store-advisor</artifactId>
  4. </dependency>

2、文档获取工具类

用来获取某个目录下面的文档

  1. public class TxtDocumentLoader {
  2. /**
  3. * 静态工具方法,线程安全,无任何静态成员变量
  4. * @param dirPath 文件夹路径
  5. * @param chunkSize 分片字符数
  6. * @param chunkOverlap 重叠字符数
  7. * @return List<Document>
  8. */
  9. public static List<Document> loadFromDirectory(String dirPath, int chunkSize, int chunkOverlap) {
  10. if (chunkOverlap >= chunkSize) {
  11. throw new IllegalArgumentException("重叠长度不能大于等于分片长度");
  12. }
  13. List<Document> documentList = new ArrayList<>();
  14. File dir = new File(dirPath);
  15. if (!dir.exists() || !dir.isDirectory()) {
  16. return documentList;
  17. }
  18. File[] files = dir.listFiles((f, name) -> name.toLowerCase().endsWith(".txt"));
  19. if (files == null) {
  20. return documentList;
  21. }
  22. for (File file : files) {
  23. documentList.addAll(loadSingleTxt(file, chunkSize, chunkOverlap));
  24. }
  25. return documentList;
  26. }
  27. public static List<Document> loadSingleTxt(File txtFile, int chunkSize, int chunkOverlap) {
  28. List<Document> chunks = new ArrayList<>();
  29. String content;
  30. try {
  31. content = Files.readString(txtFile.toPath(), StandardCharsets.UTF_8);
  32. } catch (IOException e) {
  33. throw new RuntimeException("读取文件失败:" + txtFile.getAbsolutePath(), e);
  34. }
  35. if (!StringUtils.hasText(content)) {
  36. return chunks;
  37. }
  38. List<String> sliceTexts = splitText(content, chunkSize, chunkOverlap);
  39. for (int i = 0; i < sliceTexts.size(); i++) {
  40. Document doc = new Document(sliceTexts.get(i), Map.of(
  41. "file_name", txtFile.getName(),
  42. "file_path", txtFile.getAbsolutePath(),
  43. "chunk_index", String.valueOf(i)
  44. ));
  45. chunks.add(doc);
  46. }
  47. return chunks;
  48. }
  49. private static List<String> splitText(String text, int chunkSize, int chunkOverlap) {
  50. List<String> result = new ArrayList<>();
  51. int start = 0;
  52. int len = text.length();
  53. while (start < len) {
  54. int end = Math.min(start + chunkSize, len);
  55. String chunk = text.substring(start, end);
  56. result.add(chunk);
  57. start = start + chunkSize - chunkOverlap;
  58. }
  59. return result;
  60. }
  61. // 重载:给默认值,方便快速调用
  62. public static List<Document> loadFromDirectory(String dirPath) {
  63. return loadFromDirectory(dirPath, 800, 150);
  64. }
  65. }

2、简单使用

  1. //先将内容加入到向量数据库中
  2. @GetMapping("/addV")
  3. public String addV(){
  4. //加入向量数据库中
  5. List<Document> documents = TxtDocumentLoader.loadFromDirectory("C:\\Users\\86135\\Desktop\\text");
  6. vectorStore.doAdd(documents);
  7. return "ok";
  8. }
  9. @GetMapping("/getV")
  10. public List<Document> getV(String topic){
  11. //相似度查询
  12. List<Document> documents = vectorStore.similaritySearch(
  13. SearchRequest.builder()
  14. .query(topic)//要查询的结果
  15. .topK(2)//最多返回两个
  16. .build());
  17. return documents;
  18. }
  19. @GetMapping("/rag")
  20. public String rag(String topic){
  21. QuestionAnswerAdvisor questionAnswerAdvisor= QuestionAnswerAdvisor.builder(vectorStore)
  22. .searchRequest(SearchRequest.builder().
  23. similarityThreshold(0.4d).//相似度阈值,越大越严格,太大要求太高了不一定能查到内容
  24. topK(5).
  25. build())
  26. .build();
  27. String result = openaiChatClient
  28. .prompt()
  29. .user(u -> u.text("{topic}").param("topic",topic))
  30. .advisors(questionAnswerAdvisor)
  31. .call()
  32. .content();
  33. return result;
  34. }

先addV在/rag查询结果,如果没有查询到目标,有可能 similarityThreshold(0.4d)阈值设置的太高了。

 1

啊!这个可能是世界上最丑的留言输入框功能~


当然,也是最丑的留言列表

有疑问发邮件到 : suibibk@qq.com 侵权立删
Copyright : 个人随笔   备案号 : 粤ICP备18099399号-2