【Java SpringAI智能体开发学习 | 3】RAG知识库基础,SpringAI实现RAG本地知识库+云知识库
传统大语言模型的核心问题是 “” 和 “”,RAG的出现就是使回答特定的问题更加准确。RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合了与的技术框架,旨在解决传统大语言模型(LLM)在知识准确性、时效性和专业性上的局限性,让 AI 生成的内容更可靠、更贴合特定需求。RAG让AI模型回答问题前先查询特定的知识库获取知识,确保获得的资料不是凭空产生的。
基本概念
传统大语言模型的核心问题是 “知识固化” 和 “幻觉 ”,RAG的出现就是使回答特定的问题更加准确。
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合了信息检索与生成式 AI的技术框架,旨在解决传统大语言模型(LLM)在知识准确性、时效性和专业性上的局限性,让 AI 生成的内容更可靠、更贴合特定需求。
RAG让AI模型回答问题前先查询特定的知识库获取知识,确保获得的资料不是凭空产生的
工作流程
1. 文档收集和切割
要让模型能 “查到资料”,需先将原始数据(如 PDF、Word、网页、数据库等)处理成机器可高效检索的格式,核心是 “文本拆分 + 嵌入(Embedding) ”:
- 文本拆分(Chunking):将长文档(如一本手册)拆分成短片段(“Chunk”,通常 100-500 字)。拆分的目的是避免检索时因 “信息过载” 导致相关性下降(例如查 “某产品保修政策” 时,无需加载整本产品手册,只需定位到 “保修” 相关片段)。
2. 向量转换和存储
- 嵌入(Embedding):通过Embedding模型(将每个文本片段转化为 “向量(Vector)”—— 一种数值化的表示,能反映文本的语义含义(例如 “猫” 和 “狗” 的向量距离较近,“猫” 和 “飞机” 的距离较远)。
- 存储向量:将所有向量存入 “向量数据库”(如 Pinecone、Weaviate、Milvus),向量数据库的核心能力是 “相似性检索”—— 能快速找到与用户问题语义最接近的向量对应的文本片段。
3. 文档过滤和检索
当用户提出问题时,系统先通过检索定位到知识库中最相关的信息:
- 问题嵌入:将用户的问题也转化为向量。
- 相似性匹配:向量数据库对比 “问题向量” 与 “知识库向量”,返回 Top N 个语义最相似的文本片段(即 “相关证据”)。
- 可选:重排序:部分高级 RAG 会用排序模型(如 BERT 重排序)对检索结果二次筛选,进一步提升相关性(例如剔除冗余、重复的片段)。
4. 查询增强和关联
将 “用户问题” 和 “检索到的相关片段” 一起输入大模型,让模型根据这些 “证据” 生成最终回答:
- 提示词(Prompt)设计:通常会在提示词中明确要求模型 “仅基于提供的资料回答,不编造信息”,并建议 “引用资料来源”(增强可信度)。
- 后处理:格式化、摘要或其他处理以优化输出
- 生成回答:模型整合检索到的信息,用自然语言组织成逻辑连贯的回答,同时避免 “幻觉”(因为有明确的资料依据)。
RAG相关技术
Embedding
将高位离散数据(文字、图片)转换为低位连续向量的过程
Embedding模型:
执行这种算法的机器学习模型
召回
从大数据中搜集出可能相关的候选项,强调速度和广度
粗排
对召回的数据进行初步筛选
精排和Rank模型
精排是搜索的最后阶段,考虑更多的业务特征与规则,对粗排的数据进行更精细、复杂的排序
Rank模型:
对召回阶段的候选项进行精准排序。
现代Rank模型会综合查询与候选项的相关性、用户历史行为等因素做出排序
RAG Java实战
文档准备
本地知识库:
准备markdown等尽量结构化的格式
云知识库:
阿里百炼中新建云知识库,上传原始文档
文档读取
对准备好的文档进行处理,保存到向量数据库中。这个过程为ETL(抽取、转换、加载)
SpringAI提供了对ETL的支持:
DocumentReader:读取文档获得文档列表
DocumentTransformer:转换文档,得到处理后的文档列表
DocumentWriter:将文档列表保存存储里
class LoveAppDocumentLoader{
private final ResourcePatternResolver resourcePatternResolver;
LoveAppDocumentLoader(ResourcePatternResolver resourcePatternResolver) {
this.resourcePatternResolver = resourcePatternResolver;
}
public List<Document> loadMarkdowns() {
List<Document> allDocuments = new ArrayList<>();
try {
// 这里可以修改为你要加载的多个 Markdown 文件的路径模式
Resource[] resources = resourcePatternResolver.getResources("classpath:document/*.md");
for (Resource resource : resources) {
String fileName = resource.getFilename();//文档写入的元信息
MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
.withHorizontalRuleCreateDocument(true)
.withIncludeCodeBlock(false)
.withIncludeBlockquote(false)
.withAdditionalMetadata("filename", fileName)//元信息
.build();
MarkdownDocumentReader reader = new MarkdownDocumentReader(resource, config);//将原始文档转换为Document类型的转换器
allDocuments.addAll(reader.get());
}
} catch (IOException e) {
log.error("Markdown 文档加载失败", e);
}
return allDocuments;
}
}
元信息的存在便于后续实现更精准的检索
向量转换和存储
使用基于内存读写的向量数据库SimpleVectorStore
VectorStore实现了DocumentWriter,具有写功能
将文档写入数据库前,先将其转换为向量
@Resource
private LoveAppDocumentLoader loveAppDocumentLoader;
@Bean
VectorStore loveAppVectorStore(EmbeddingModel dashscopeEmbeddingModel) {
SimpleVectorStore simpleVectorStore = SimpleVectorStore.builder(dashscopeEmbeddingModel).build();
List<Document> documentList = loveAppDocumentLoader.loadMarkdowns();
simpleVectorStore.add(documentList);
return simpleVectorStore;
}
查询增强
QuestionAnswerAdvisor(loveAppVectorStore)
云知识库Advisor
@Configuration
@Slf4j
class LoveAppRagCloudAdvisorConfig {
@Value("${spring.ai.dashscope.api-key}")
private String dashScopeApiKey;
@Bean
public Advisor loveAppRagCloudAdvisor() {
DashScopeApi dashScopeApi = new DashScopeApi(dashScopeApiKey);
final String KNOWLEDGE_INDEX = "恋爱大师";
DocumentRetriever documentRetriever = new DashScopeDocumentRetriever(dashScopeApi,
DashScopeDocumentRetrieverOptions.builder()
.withIndexName(KNOWLEDGE_INDEX)
.build());
return RetrievalAugmentationAdvisor.builder()
.documentRetriever(documentRetriever)
.build();
}
}
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)