找回密码
 立即注册
首页 业界区 业界 Solon AI 五步构建 RAG 服务:2025 最新 AI + 向量数据 ...

Solon AI 五步构建 RAG 服务:2025 最新 AI + 向量数据库实战

侧胥咽 2025-6-17 14:30:35
此文参考自:https://www.toutiao.com/article/7506140643970826779/
引言:RAG 会成为 2025 年 AI 落地核心?

在2025年,检索增强生成(RAG)技术已成为企业级AI应用的标配。传统大模型受限于知识更新慢、业务适配性差,而 RAG 通过动态外接知识库,结合向量数据库与AI推理能力,显著提升回答的准确性与实时性。本文将基于 Solon AI 与 Redis Vector Search,从0到1搭建 RAG 服务,并结合电商客服场景,揭秘如何通过5步实现生产级落地。
一、项目初始化:Solon AI

核心依赖:
  1. <dependency>
  2.     <groupId>org.noear</groupId>
  3.     solon-ai</artifactId>
  4. </dependency>
  5. <dependency>
  6.     <groupId>org.noear</groupId>
  7.     solon-ai-repo-redis</artifactId>
  8. </dependency>
  9. <dependency>
  10.     <groupId>org.noear</groupId>
  11.     solon-ai-load-pdf</artifactId>
  12. </dependency>
复制代码
配置参考:
  1. solon.ai.chat:
  2.   ds3:
  3.     apiUrl: "http://127.0.0.1:11434/api/chat" # 使用完整地址(而不是 api_base)
  4.     provider: "ollama" # 使用 ollama 服务时,需要配置 provider
  5.     model: "llama3.2"
  6. solon.ai.embed:
  7.   bgem3:
  8.     apiUrl: "http://127.0.0.1:11434/api/embed" # 使用完整地址(而不是 api_base)
  9.     provider: "ollama" # 使用 ollama 服务时,需要配置 provider
  10.     model: "bge-m3:latest"
  11.         
  12. solon.ai.repo:
  13.   redis:
  14.     server: localhost:6379
复制代码
实例构建:
  1. import org.noear.redisx.RedisClient;
  2. import org.noear.solon.ai.chat.ChatModel;
  3. import org.noear.solon.ai.embedding.EmbeddingModel;
  4. import org.noear.solon.ai.rag.RepositoryStorable;
  5. import org.noear.solon.ai.rag.repository.RedisRepository;
  6. import org.noear.solon.ai.rag.repository.redis.MetadataField;
  7. import org.noear.solon.annotation.Bean;
  8. import org.noear.solon.annotation.Configuration;
  9. import org.noear.solon.annotation.Inject;
  10. import java.util.ArrayList;
  11. import java.util.List;
  12. @Configuration
  13. public class RagConfig {
  14.     @Bean
  15.     public ChatModel chatModel(@Inject("${solon.ai.chat.ds3}") ChatModel chatModel) {
  16.         return chatModel;
  17.     }
  18.     @Bean
  19.     public EmbeddingModel embeddingModel(@Inject("${solon.ai.embed.bgem3}") EmbeddingModel embeddingModel) {
  20.         return embeddingModel;
  21.     }
  22.     @Bean
  23.     public RedisClient client(@Inject("${solon.ai.repo.redis}") RedisClient client) {  //构建知识库的连接客户端
  24.         return client;
  25.     }
  26.    
  27.     @Bean
  28.     public RepositoryStorable repository(EmbeddingModel embeddingModel, RedisClient client) { //构建知识库
  29.         // 创建元数据索引字段列表(用于支持混合搜索)
  30.         List<MetadataField> metadataFields = new ArrayList<>();
  31.         metadataFields.add(MetadataField.tag("title"));
  32.         metadataFields.add(MetadataField.tag("category"));
  33.         metadataFields.add(MetadataField.numeric("price"));
  34.         metadataFields.add(MetadataField.numeric("stock"));
  35.         return RedisRepository.builder(embeddingModel, client.jedis())
  36.                 .metadataIndexFields(metadataFields)
  37.                 .build();
  38.     }
  39. }
复制代码
技术选型优势:

  • Redis Vector Search(建议 Redis 8+):支持千亿级向量毫秒检索,实时数据更新秒级可见
  • Solon AI:统一接口支持各种主流向量数据库,内置流式输出与异步处理。
二、数据处理:文档分块与向量化

1. 文档加载与分块
  1. @Component
  2. public class RagService {
  3.     public void load(){
  4.         // 加载PDF/Word文档
  5.         List<Document> docs = new PdfLoader("product-manual.pdf").load();
  6.         // 智能分块(动态调整块大小)
  7.         docs = new TokenSizeTextSplitter(500, 64).split(docs);
  8.     }
  9. }
复制代码
分块策略:


  • 动态分块:根据语义边界(如段落、表格)自动调整块大小,避免信息割裂;
  • 重叠机制:设置64 Token的重叠区,确保上下文连贯性。
2. 向量嵌入与存储

在 RagService 的基础上,进一步补充
  1. import org.noear.solon.ai.embedding.EmbeddingModel;
  2. import org.noear.solon.ai.rag.Document;
  3. import org.noear.solon.ai.rag.RepositoryStorable;
  4. import org.noear.solon.ai.rag.splitter.TokenSizeTextSplitter;
  5. import org.noear.solon.annotation.Component;
  6. import org.noear.solon.annotation.Inject;
  7. import java.io.IOException;
  8. import java.util.List;
  9. @Component
  10. public class RagService {
  11.     @Inject
  12.     private RepositoryStorable  repository;
  13.     @Inject
  14.     private EmbeddingModel embeddingModel;
  15.     public void load() throws IOException {
  16.         // 加载PDF/Word文档
  17.         List<Document> docs = new PdfLoader("product-manual.pdf").load();
  18.         // 智能分块(动态调整块大小)
  19.         docs = new TokenSizeTextSplitter(500, 64).split(docs);
  20.         // 存储(内部自动完成向量嵌入,内部支持分批入库)
  21.         repository.insert(docs);
  22.     }
  23. }
复制代码
性能优化:


  • 批量处理:数据批次插入,降低I/O开销;
  • 元数据附加:为每个向量附加来源、时间戳等字段,支持精准过滤。
三、检索增强:混合搜索

使用元信息字段 category 过滤(减少匹配范围),并使用向量检索
  1. @Component
  2. public class RagService {
  3.     @Inject
  4.     private RepositoryStorable repository;
  5.     @Inject
  6.     private EmbeddingModel embeddingModel;
  7.     public void load() throws IOException {
  8.         // 加载PDF/Word文档
  9.         List<Document> docs = new PdfLoader("product-manual.pdf").load();
  10.         // 智能分块(动态调整块大小)
  11.         docs = new TokenSizeTextSplitter(500, 64).split(docs);
  12.         // 存储(内部自动完成向量嵌入)
  13.         repository.insert(docs);
  14.     }
  15.     public List<Document> find(String category, String query) throws IOException {
  16.         return repository.search(new QueryCondition(query)
  17.                 .filterExpression("category == '" + category + "'"));
  18.     }
  19. }
复制代码
场景适配:


  • 元数据检索:处理明确实体(如商品目录);
  • 向量检索:应对复杂语义(如“性价比高的手机推荐”)。
四、生成优化:提示工程与流式输出

1. 动态Prompt设计
  1. String promptTemplate = """
  2.     你是一名电商客服专家,请根据以下上下文回答问题:
  3.     ${context}
  4.     问题:${question}
  5.     要求:回答需包含具体数据,若信息不足则回复“暂未收录”。
  6.     示例:库存查询 → “当前iPhone 20库存为500件,预计48小时发货。”
  7.     """;
复制代码
关键技巧:


  • 指令约束:限制回答范围,减少幻觉;
  • 示例引导:提供标准回答格式,提升一致性。
2. 流式响应与溯源

写一个控制器,整合 ChatModel 和 RagService
  1. import org.noear.solon.ai.chat.ChatModel;
  2. import org.noear.solon.ai.chat.message.ChatMessage;
  3. import org.noear.solon.ai.rag.Document;
  4. import org.noear.solon.annotation.Controller;
  5. import org.noear.solon.annotation.Inject;
  6. import org.noear.solon.annotation.Mapping;
  7. import reactor.core.publisher.Flux;
  8. import java.io.IOException;
  9. import java.util.List;
  10. @Controller
  11. public class RagController {
  12.     @Inject
  13.     RagService ragService;
  14.     @Inject
  15.     ChatModel chatModel;
  16.     static String promptTemplate = """
  17.         你是一名电商客服专家,请根据以下上下文回答问题:
  18.         #{context}
  19.         问题:#{question}
  20.         要求:回答需包含具体数据,若信息不足则回复“暂未收录”。
  21.         示例:库存查询 → “当前iPhone 20库存为500件,预计48小时发货。”
  22.         """;
  23.     @Mapping("/ask")
  24.     public Flux<String> streamAnswer(String question) throws IOException {
  25.         List<Document> context = ragService.find("商品", question);
  26.         
  27.         ChatMessage message = ChatMessage.ofUserTmpl(promptTemplate)
  28.                 .paramAdd("question", question)
  29.                 .paramAdd("context", context)
  30.                 .generate();
  31.         return Flux.from(chatModel.prompt(message).stream())
  32.                 .filter(resp -> resp.hasChoices())
  33.                 .map(resp -> resp.getMessage().getContent());
  34.     }
  35. }
复制代码
用户体验优化:


  • 逐字输出:响应延迟降低至100ms以内(要看模型服务的性能);
  • 来源标记:返回答案关联的文档ID与置信度。
五、实战案例:电商客服RAG系统

场景:秒杀活动问答

需求:用户询问“iPhone 20秒杀库存和优惠规则”。
RAG处理流程:

检索:从商品手册中匹配“iPhone 20”的库存条款与促销规则;
生成:返回“当前库存2000件,限购1台,叠加满减券再降500元”。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册