1. 什么是 RAG
RAG(Retrieval-Augmented Generation,检索增强生成) 并非颠覆大模型,而是为其加装了一个智能 “知识雷达”,核心思想直击痛点:“不懂就问,现查现用”。
传统大模型瓶颈:依赖训练时的静态知识,无法获取训练截止日期后的新信息,对特定领域细节(如企业专有文档)掌握不足,易产生 “幻觉”(编造答案)。
RAG 的革新:将大模型的强大语言理解与生成能力,与实时、精准的外部知识检索相结合。回答问题时,先自动从企业专属知识库中查找最相关资料,再基于这些资料生成可靠回答。
2. 为什么需要 RAG
解决大模型“静态知识瓶颈”: 通用大模型(如 DeepSeek)的训练数据截止于某个时间点,无法获取后续新知识。有了 RAG 技术,能够实时检索最新企业文档,动态注入知识。
消除“幻觉”,保障答案准确性:大模型对专业细节不熟悉时,可能编造错误答案(如虚构产品功能)。有了 RAG 技术,答案严格基于检索到的权威文档生成,源头可追溯,大幅降低错误率。
保护私有知识资产,杜绝数据泄露:知识库与检索引擎可完全部署在企业内网,避免上传到公有云,用户提问题、检索内容、生成答案全流程在私有环境闭环运行,保证数据安全性;
降低成本,快速落地:训练专属大模型需百万级标注数据和算力,中小企业难以承受。有了 RAG 技术,可直接复用开源/商用 AI 大模型能力,企业只需聚焦知识库建设(成本<5%);
提升知识利用效率:80%的企业知识散落在邮件、PDF、数据库,员工难以高效检索。有了 RAG 技术,统一接入非结构化数据,实现自然语言一键直达目标信息(如“调取 2023 年华东区退货率最高的产品报告”);
3. 处理流程
文档预先向量化
将企业内部的产品说明书、技术文档等,提前通过向量化模型,进行结构化处理(分块、清洗),存储到向量数据库中;
提出问题: 用户提出自然语言问题(例:“XX冰箱的 ‘瞬冷冻’ 功能最低能达到多少度?如何开启?”)
知识检索
向量化模型处理:将用户问题转化为数学向量(Embedding)
查询向量数据库:在预先构建并向量化的企业知识数据库(产品说明书、技术文档、客服QA记录等)中,快速查找语义最相关的文本片段(通常使用相似度计算,如余弦相似度)
知识增强:将检索到的相关文本片段(Context)与原始用户问题组合,形成增强后的提示词(Prompt),类似下面这样
“基于以下产品文档信息:[检索到的冰箱说明书段落]... 请回答用户问题:[用户原问题]。确保答案严格依据提供信息。”
答案生成:AI 大模型接收 “增强版 Prompt 提示词”,融合自身通用理解力与提供的专属知识,生成精准、可靠、符合企业语境的答案,输出示例如下:
“根据XX冰箱最新产品手册(2025版),‘瞬冷冻’功能最低可达 -32°C。开启方法:1. 在主界面选择‘速冻模式’;2. 点击‘瞬冷冻’图标;3. 设定时长(最长6小时)。具体操作示意图请参考手册第15页。”
4. 文档向量化存储与检索
4.1. 搭建项目
!-- Spring AI 依赖管理 -->
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-bom</artifactId>
<version>${spring-ai.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>4.2. 选择向量模型
我们需要先挑选一个 “向量模型”,它够将文本、图像、视频等数据转换为数学空间中的向量。通过计算向量之间的距离或夹角,可以量化数据的相似度,从而作用于精准搜索、智能推荐、自动分类及异常检测等任务。
“阿里百炼” 的模型广场,筛选 “向量模型” 分类下所有大模型,选择最新的 “通用文本向量-v4” 模型
4.3. 依赖
<!-- OpenAI -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
<!-- 整合向量数据库 Redis -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-vector-store-redis</artifactId>
</dependency>
4.4. 配置
server:
port: 8090 # 项目启动端口
spring:
data:
redis:
host: localhost # Redis URL 链接
port: 6379 # Redis 端口
ai:
openai:
base-url: https://dashscope.aliyuncs.com/compatible-mode # OpenAI 服务的访问地址,这里使用的是阿里云百炼
api-key: xxx # 填写阿里百炼的 API Key, 改成你自己的
embedding:
options:
model: text-embedding-v4 # 向量模型
vectorstore:
redis:
initialize-schema: true # 是否初始化模式
index-name: xiaoha-ai-index # 自定义索引名称
prefix: embedding # 自定义键名前缀4.5. 文档向量化处理,并存入 Redis(Redis Stack)
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.List;
import java.util.Map;
/**
* @Description: 将文档通过向量模型,向量化存储到数据库中
**/
@Component
public class InitEmbeddingIndexRunner implements ApplicationRunner {
@Resource
private VectorStore vectorStore;
@Override
public void run(ApplicationArguments args) {
// 定义 3 条文档
List<Document> documents = List.of(
new Document("冰箱首次使用指南:拆箱后静置24小时再通电,调节温控器至4℃冷藏室、-18℃冷冻室。清洁内胆时请使用中性洗涤剂。",
Map.of("章节", "安全须知", "版本", "2025")),
new Document("节能技巧:避免频繁开关门,热食冷却后再放入,定期除霜可提升制冷效率。建议每月清洁一次冷凝器。"),
new Document("故障代码手册:E1温度传感器异常,E2化霜故障,F1通讯错误。遇到E2代码请断电2小时后重启,若持续出现需联系售后。",
Map.of("章节", "故障处理", "紧急程度", "高"))
);
// 通过向量模型,将文档向量化存储到 Redis 中
vectorStore.add(documents);
}
}
4.6. 检索向量数据库
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.vectorstore.SearchRequest;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 检索向量数据库
**/
@RestController
@RequestMapping("/vector")
public class VectorSearchController {
@Resource
private VectorStore vectorStore;
/**
* 检索向量数据库
* @param key
* @return
*/
@GetMapping(value = "/search")
public List<Document> search(@RequestParam(value = "key") String key) {
// 检索与查询相似的文档
List<Document> results = vectorStore.similaritySearch(SearchRequest.builder()
.query(key) // 查询的关键词
.topK(2) // 查询相似度最高的 2 条文档
.build());
return results;
}
}
4.7. 提取 txt 文件
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.TextReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: Txt 文件读取
**/
@Component
public class MyTextReader {
@Value("classpath:/document/manual.txt")
private Resource resource;
/**
* 读取 Txt 文档
* @return
*/
public List<Document> loadText() {
// 创建 TextReader 对象,用于读取指定资源 (resource) 的文本内容
TextReader textReader = new TextReader(resource);
// 添加自定义元数据,如文件名称
textReader.getCustomMetadata()
.put("filename", "manual.txt");
// 读取并转换为 Document 文档集合
return textReader.read();
}
/**
* 读取 Txt 文档并分块拆分
* @return
*/
public List<Document> loadTextAndSplit() {
// 创建 TextReader 对象,用于读取指定资源 (resource) 的文本内容
TextReader textReader = new TextReader(resource);
// 将资源内容解析为 Document 对象集合
List<Document> documents = textReader.get();
// 使用 TokenTextSplitter 对文档列表进行分块处理
List<Document> splitDocuments = new TokenTextSplitter().apply(documents);
// 返回拆分后的文档分块集合
return splitDocuments;
}
}
import com.quanxiaoha.vector.store.reader.MyTextReader;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyTextReader textReader;
@GetMapping(value = "/txt")
public List<Document> readText() {
return textReader.loadText();
}
@GetMapping(value = "/txt2")
public List<Document> readText2() {
return textReader.loadTextAndSplit();
}
}
4.8. 读取 Json 文件
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.JsonReader;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: Json 文件读取
**/
@Component
public class MyJsonReader {
@Value("classpath:/document/tv.json")
private Resource resource;
/**
* 读取 Json 文件
* @return
*/
public List<Document> loadJson() {
// 创建 JsonReader 阅读器实例,配置需要读取的字段
JsonReader jsonReader = new JsonReader(resource, "description", "content", "title");
// 执行读取操作,并转换为 Document 对象集合
return jsonReader.get();
}
}
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyJsonReader jsonReader;
@GetMapping(value = "/json")
public List<Document> readJson() {
return jsonReader.loadJson();
}
}
4.9. 读取 Markdown
<!-- 读取 Markdown -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-markdown-document-reader</artifactId>
</dependency>import org.springframework.ai.document.Document;
import org.springframework.ai.reader.markdown.MarkdownDocumentReader;
import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: Markdown 文件读取
**/
@Component
public class MyMarkdownReader {
@Value("classpath:/document/code.md")
private Resource resource;
public List<Document> loadMarkdown() {
// MarkdownDocumentReader 阅读器配置类
MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder()
.withHorizontalRuleCreateDocument(true) // 遇到水平线 ---,则创建新文档
.withIncludeCodeBlock(false) // 排除代码块(代码块生成单独文档)
.withIncludeBlockquote(false) // 排除块引用(块引用生成单独文档)
.withAdditionalMetadata("filename", "code.md") // 添加自定义元数据,如文件名称
.build();
// 新建 MarkdownDocumentReader 阅读器
MarkdownDocumentReader reader = new MarkdownDocumentReader(resource, config);
// 读取并转换为 Document 文档集合
return reader.get();
}
}import com.quanxiaoha.vector.store.reader.MyJsonReader;
import com.quanxiaoha.vector.store.reader.MyMarkdownReader;
import com.quanxiaoha.vector.store.reader.MyTextReader;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyMarkdownReader markdownReader;
@GetMapping(value = "/md")
public List<Document> readMarkdown() {
return markdownReader.loadMarkdown();
}
}
4.10. 读取 Html
<!-- 读取 HTML -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-jsoup-document-reader</artifactId>
</dependency>import org.springframework.ai.document.Document;
import org.springframework.ai.reader.jsoup.JsoupDocumentReader;
import org.springframework.ai.reader.jsoup.config.JsoupDocumentReaderConfig;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: HTML 文件读取
**/
@Component
public class MyHtmlReader {
@Value("classpath:/document/my-page.html")
private Resource resource;
public List<Document> loadHtml() {
// JsoupDocumentReader 阅读器配置类
JsoupDocumentReaderConfig config = JsoupDocumentReaderConfig.builder()
.selector("article p") // 提取 <article> 标签内的 p 段落
.charset("UTF-8") // 使用 UTF-8 编码
.includeLinkUrls(true) // 在元数据中包含链接 URL(绝对链接)
.metadataTags(List.of("author", "date")) // 提取 author 和 date 元标签
.additionalMetadata("source", "my-page.html") // 添加自定义元数据
.build();
// 新建 JsoupDocumentReader 阅读器
JsoupDocumentReader reader = new JsoupDocumentReader(resource, config);
// 读取并转换为 Document 文档集合
return reader.get();
}
}import com.quanxiaoha.vector.store.reader.MyHtmlReader;
import com.quanxiaoha.vector.store.reader.MyJsonReader;
import com.quanxiaoha.vector.store.reader.MyMarkdownReader;
import com.quanxiaoha.vector.store.reader.MyTextReader;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyHtmlReader htmlReader;
@GetMapping(value = "/html")
public List<Document> readHtml() {
return htmlReader.loadHtml();
}
}4.11. 读取 Pdf
<!-- 读取 PDF -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-pdf-document-reader</artifactId>
</dependency>import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: PDF 文件读取
**/
@Component
public class MyPdfReader {
public List<Document> getDocsFromPdf() {
// 新建 PagePdfDocumentReader 阅读器
PagePdfDocumentReader pdfReader = new PagePdfDocumentReader("classpath:/document/profile.pdf", // PDF 文件路径
PdfDocumentReaderConfig.builder()
.withPageTopMargin(0) // 设置页面顶边距为0
.withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
.withNumberOfTopTextLinesToDelete(0) // 设置删除顶部文本行数为0
.build())
.withPagesPerDocument(1) // 设置每个文档包含1页
.build());
// 读取并转换为 Document 文档集合
return pdfReader.read();
}
}import com.quanxiaoha.vector.store.reader.*;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyPdfReader pdfReader;
@GetMapping(value = "/pdf")
public List<Document> readPdf() {
return pdfReader.getDocsFromPdf();
}
}5. Apache Tika 读取 Word、PPT 文档
5.1. Apache Tika 介绍
Apache Tika 是一个开源的 内容检测与分析工具包,用于从各种格式的文件(如 PDF, DOC/DOCX, PPT/PPTX, HTML等)中提取文本内容和元数据。它通过统一的 API 简化了文档解析的复杂性。
5.2. 依赖
<!-- Tika -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-tika-document-reader</artifactId>
</dependency>5.3. 读取 word
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: Word 文件读取
**/
@Component
public class MyTikaWordReader {
@Value("classpath:/document/55f79946a0964b89bc7ab9b55e4a49ff.docx")
private Resource resource;
public List<Document> loadWord() {
// 新建 TikaDocumentReader 阅读器
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(resource);
// 读取并转换为 Document 文档集合
List<Document> documents = tikaDocumentReader.get();
// 文档分块
TokenTextSplitter splitter = new TokenTextSplitter(); // 不设置任何构造参数,表示使用默认设置
return splitter.apply(documents);
}
}/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyTikaWordReader tikaWordReader;
@GetMapping(value = "/word")
public List<Document> readWord() {
return tikaWordReader.loadWord();
}
}5.4. 读取 ppt
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.tika.TikaDocumentReader;
import org.springframework.ai.transformer.splitter.TokenTextSplitter;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.Resource;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: PPT 文件读取
**/
@Component
public class MyTikaPptReader {
@Value("classpath:/document/XX牌云感变频空调说明书.pptx")
private Resource resource;
public List<Document> loadPpt() {
// 新建 TikaDocumentReader 阅读器
TikaDocumentReader tikaDocumentReader = new TikaDocumentReader(resource);
// 读取并转换为 Document 文档集合
List<Document> documents = tikaDocumentReader.get();
// 文档分块
// 使用自定义设置
TokenTextSplitter splitter = new TokenTextSplitter(1000, 400, 10, 5000, true);
return splitter.apply(documents);
}
}import com.quanxiaoha.vector.store.reader.*;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
/**
* @Description: 文档读取
**/
@RestController
@RequestMapping("/read")
public class ReaderController {
@Resource
private MyTikaPptReader tikaPptReader;
@GetMapping(value = "/ppt")
public List<Document> readPpt() {
return tikaPptReader.loadPpt();
}
}6. DeepSeek 整合 RAG 增强检索: 实现与 PDF 对话
6.1. 将 PDF 向量化存储到 Redis 中
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.ExtractedTextFormatter;
import org.springframework.ai.reader.pdf.PagePdfDocumentReader;
import org.springframework.ai.reader.pdf.config.PdfDocumentReaderConfig;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.List;
/**
* @Description: 将文档通过向量模型,向量化存储到数据库中
**/
@Component
public class InitEmbeddingIndexRunner implements ApplicationRunner {
@Resource
private VectorStore vectorStore;
@Override
public void run(ApplicationArguments args) {
// 新建 PagePdfDocumentReader 阅读器
PagePdfDocumentReader pdfReader = new PagePdfDocumentReader("classpath:/document/profile.pdf", // 类路径PDF文件
PdfDocumentReaderConfig.builder()
.withPageTopMargin(0) // 设置页面顶边距为0
.withPageExtractedTextFormatter(ExtractedTextFormatter.builder()
.withNumberOfTopTextLinesToDelete(0) // 设置删除顶部文本行数为0
.build())
.withPagesPerDocument(1) // 设置每个文档包含1页
.build());
// 读取并转换为 Document 文档集合
List<Document> documents = pdfReader.get();
// 防止重复添加到 Redis 中
for (Document document : documents) {
// 从向量数据中,查询当前文档
List<Document> results = vectorStore.similaritySearch(SearchRequest.builder()
.query(document.getText())
.topK(1) // 查询一条最高得分的
.build());
// 如果结果不为空,并且得分大于 0.99,则表示文档较高几率重复,直接跳过
if (!results.isEmpty() && results.get(0).getScore() > 0.99)
continue;
// 通过向量模型,将文档向量化存储到 Redis 中
vectorStore.add(List.of(document));
}
}
}6.2. 整合 DeepSeek
<!-- DeepSeek 模型 -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-deepseek</artifactId>
</dependency>
spring:
ai:
deepseek:
base-url: https://api.deepseek.com # DeepSeek 的请求 URL, 可不填,默认值为 api.deepseek.com
api-key: xxx # 填写 DeepSeek Api Key,改成你自己的
chat:
options:
model: deepseek-reasoner # 使用哪个模型
temperature: 0.0 # 温度值 在 RAG 场景下,较低的温度值可降低生成内容的随机性,减少幻觉率(import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.deepseek.DeepSeekChatModel;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* @Description: ChatClient 配置
**/
@Configuration
public class ChatClientConfig {
/**
* 初始化 ChatClient 客户端
* @param chatModel
* @return
*/
@Bean
public ChatClient chatClient(DeepSeekChatModel chatModel) {
return ChatClient.builder(chatModel)
.build();
}
}6.3. RAG 增强检索
添加向量 Advisor 依赖
<!-- 向量 Advisor -->
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-advisors-vector-store</artifactId>
</dependency>import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.ChatClient;
import org.springframework.ai.chat.client.advisor.vectorstore.QuestionAnswerAdvisor;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Flux;
/**
* @Description: RAG 增强检索
**/
@RestController
@RequestMapping("/rag")
public class RAGController {
@Resource
private VectorStore vectorStore;
@Resource
private ChatClient chatClient;
/**
* 流式对话
* @param message
* @return
*/
@GetMapping(value = "/generateStream", produces = "text/html;charset=utf-8")
public Flux<String> generateStream(@RequestParam(value = "message") String message) {
// 流式输出
return chatClient.prompt()
.system("请你扮演一名企业客服。从企业内部知识库中查阅相关资料,并回答用户,若内部资料没有相关内容,则回答 “未找到相关资料”")
.user(message) // 提示词
.advisors(new QuestionAnswerAdvisor(vectorStore)) // 检索向量库,组合增强提示词,调用 AI 大模型
.stream()
.content();
}
}
评论区