当前位置: 首页 > news >正文

AI 超级智能体全栈项目阶段四:学术分析 AI 项目 RAG 落地指南:基于 Spring AI 的本地与阿里云知识库实践

简介:

github项目地址: 学术分析AI应用
本文使用的AI大模型均为阿里云的灵积模型(Qwen-Plus)

一、需求分析

需求场景 :需精准学术引用或数据支撑

需求特征
  • 分析结果需附带具体文献来源(如 “论证‘注意力机制提升模型效率’时,需引用某篇论文的实验数据”)。
  • 需验证某结论的真实性(如 “判断‘某算法准确率达 95%’是否有文献依据”)。
为什么需要 RAG
  • 大模型单独生成时易产生 “学术幻觉”(编造不存在的作者、论文标题或数据),不符合学术分析的严谨性要求。
  • RAG 可检索目标文献的原文片段(如摘要、实验部分),直接作为分析的支撑依据,同时输出引用格式(APA、GB/T 等)。

二、初识RAG

1. RAG核心定义

1.1 RAG概念阐释

RAG(Retrieval-Augmented Generation,检索增强生成)是一种融合“信息检索技术”与“AI内容生成技术”的混合架构。其核心逻辑是:让AI在生成回答前,先从外部知识库中检索相关事实信息,再基于这些信息生成内容,最终解决传统大模型“知识时效性不足”和“易产生幻觉(虚假信息)”的核心问题。

通俗理解:RAG相当于给AI配备了一本“可实时更新的外部小抄本”,确保AI的回答基于真实、具体的资料,而非仅依赖训练数据的凭空想象。

1.2 RAG与传统大模型的差异对比

对比维度传统大语言模型RAG增强模型
知识时效性受训练数据截止日期限制(知识固定)可接入最新知识库(实时更新)
领域专业性以泛化知识为主,专业深度有限可接入垂直领域知识库(如医疗、法律)
响应准确性可能生成“幻觉”(无依据信息)基于检索到的事实依据生成
输出可控性依赖原始训练数据,难定制输出风格可通过知识库调整输出(如特定语气、话术)
资源消耗较高(需大参数量模型支撑)模型可更小,依赖外部知识降低计算成本

2. RAG核心工作流程

RAG的技术实现需经过4个环环相扣的核心步骤,形成“知识准备-知识存储-知识检索-知识应用”的完整闭环,具体流程如下:

2.1 步骤1:文档收集和切割(准备“可检索的知识原料”)

该步骤的目标是将原始知识转化为适合后续检索的“小颗粒度片段”,分为3个关键操作:

  1. 文档收集:从网页、PDF文件、数据库、企业内部系统等来源,获取AI需要调用的原始知识(如产品手册、专业文献、政策文件);
  2. 文档预处理:对原始文档进行清洗(去除乱码、冗余内容)、格式标准化(统一字体、段落结构),确保数据可用性;
  3. 文档切割:将长文档拆分为小片段(行业内称为Chunks),避免文本过长影响检索精度,常见3种切割方式:
    • 固定长度切割:按固定token数拆分(如每段512个token);
    • 语义边界切割:按段落、章节、标题拆分,保留内容的语义完整性;
    • 递归分割策略:通过递归字符n-gram等方式,平衡片段长度与语义连贯性。

2.2 步骤2:向量转换和存储(将“文字”转化为“可搜索的数字”)

该步骤的核心是让计算机“理解文字语义”,并实现高效存储,分为2个关键操作:

  1. 向量转换:使用Embedding模型(如文本领域的Word2Vec、图像领域的ResNet),将切割后的文本片段转化为“高维向量”。这类向量能体现文字的语义特征——语义越接近的文本,对应的向量在数学空间中的距离越近(例如“鱼皮”与“鱼肉”的向量距离,远小于“鱼皮”与“帅哥”);
  2. 向量存储:将“文本片段+对应向量”存入向量数据库(而非传统数据库),这类数据库专门优化了高维向量的相似性搜索效率,常见工具包括Milvus、Pinecone,或传统数据库的向量插件(如PGVector、Redis Stack的RediSearch)。

2.3 步骤3:文档过滤和检索(找到“与问题最相关的知识”)

该步骤的目标是从向量数据库中,精准定位与用户问题匹配的知识片段,分为4个关键操作:

  1. 查询处理:用与“文本片段转换”相同的Embedding模型,将用户的问题也转化为向量;
  2. 过滤机制:通过元数据(如文档发布时间、类型)、关键词等初步筛选,缩小检索范围(例如仅检索“2024年医疗政策”相关文档);
  3. 相似度搜索:使用余弦相似度、欧氏距离等算法,在向量数据库中检索与“问题向量”最相似的多个文本片段;
  4. 上下文组装:将检索到的多个相关片段,整理成逻辑连贯的“知识上下文”,为后续生成回答做准备。

2.4 步骤4:查询增强和关联(基于“检索知识”生成回答)

该步骤是RAG的“最终应用环节”,确保AI基于检索到的事实生成内容,分为4个关键操作:

  1. 提示词组装:将“用户问题+检索到的知识上下文”组合成“增强提示词”,传递给大模型;
  2. 上下文融合:大模型基于增强提示词生成回答,强制其参考检索到的事实,避免凭空创造信息;
  3. 源引用(可选):在回答中标注信息来源(如“数据来自《2024年人工智能产业报告》第3章”),提升内容可信度;
  4. 后处理:对生成的回答进行格式化(如分点、加粗重点)、摘要提炼,优化用户阅读体验。

3. RAG典型应用场景

RAG的核心优势是“可接入外部知识、可定制化”,因此其应用场景集中在对“准确性、专业性、实时性”有高要求的领域,具体包括:

3.1 特定内容问答场景

  • 企业内部知识查询:员工检索公司规章制度、HR政策、产品参数(如客服查询产品售后流程);
  • 教育/科研答疑:学生查询教材知识点、科研人员检索专业文献(如医学学生查询《临床诊疗指南》内容)。

3.2 实时信息需求场景

  • 金融领域:分析师基于最新股市数据、政策文件生成市场解读;
  • 新闻领域:AI基于实时报道,对突发事件(如赛事、会议)进行总结;
  • 政务领域:市民查询最新社保政策、补贴申请要求,AI基于官方文件回复。

3.3 垂直领域专业服务场景

  • 医疗领域:AI接入最新病例库、诊疗指南,为患者提供基础健康咨询(需强调“不能替代医生诊断”);
  • 法律领域:律师通过RAG检索现行法条、过往判例,快速生成案件分析初稿;
  • 编程领域:开发者查询最新开发文档(如Python新库用法),AI推荐解决方案。

3.4 定制化交互场景

  • 品牌客服:AI使用品牌专属话术(如“XX品牌为您服务”)与用户沟通,同时检索产品手册解答问题;
  • 教育推荐:AI根据用户学习问题(如“如何理解微积分导数”),检索并推荐相关课程、习题资源。

4. RAG关键技术名词补充

为帮助理解文档内容,对核心技术名词进行补充解释:

名词定义
Embedding模型执行“文字/图像→向量”转换的机器学习模型,能捕捉数据的语义特征,如Word2Vec(文本)、ResNet(图像)
向量数据库专门存储、检索高维向量的数据库,优化了相似性搜索效率,支持快速定位语义相近的向量
召回(Recall)信息检索的第一阶段,从大规模数据中快速筛选“可能相关”的候选集,强调“速度和广度”,不追求绝对精准
精排(Reranking)检索的最后阶段,用复杂算法(如BERT模型)对候选集排序,考虑用户行为、内容相关性等,提升结果精准度
混合检索策略结合多种检索方式(如关键词检索+语义检索),提升检索效果,如Dify平台的“全文检索+向量检索”组合

5. 总结

  1. RAG的核心价值是“用外部检索补充AI生成”,解决传统大模型的时效性和幻觉问题;
  2. 其工作流程围绕“文档准备→向量存储→知识检索→回答生成”展开,4个步骤缺一不可;
  3. 应用场景集中在“需精准事实支撑”的领域,如企业知识查询、垂直行业服务、实时信息问答;
  4. 关键技术依赖Embedding模型、向量数据库,同时需结合召回、精排等策略提升检索效果。

6. 附录:常用工具推荐

工具类型推荐工具说明
Embedding模型OpenAI Embeddings、Word2VecOpenAI Embeddings适用于通用文本,Word2Vec适合轻量型文本向量转换
向量数据库Milvus、PGVector、PineconeMilvus开源且支持大规模数据,PGVector可作为PostgreSQL插件使用,门槛低
RAG开发框架Spring AI、LangChainSpring AI适合Java生态,LangChain支持多语言,简化RAG开发流程

三、RAG实战:Spring AI+本地知识库

  1. 参考文档:SpringAI 和 Spring Ai Alibaba
  1. 实现步骤:
文档准备
文档读取
向量转换和存储
查询增强

1. 文档准备

  1. 因为是测试项目所以文档数据采用Ai生成
  2. 资源已经上传CSDN:https://download.csdn.net/download/weixin_45793745/92063666

帮我生成 3 篇 Markdown 文章,主题是【学术分析常见问题和回答】,3 篇文章的问题分别针对学术入门、学术进阶、学术转化阶段,内容形式为 1 问 1 答,每个问题标题使用 4 级标题,每篇内容需要有至少 5 个问题,要求每个问题中推荐一个相关的课程,课程来源为哔哩哔哩网站

2. 文档读取

  1. SpringAI官方文档介绍:https://docs.spring.io/spring-ai/reference/api/etl-pipeline.html#_markdown
  2. 步骤分为了:

reader

transformer

write

  1. 可以读取的文档有:JSON、HTML、Text、md、PDF、TIka
  • 导入依赖
    • 我存储的文件为md,所以导入的是markdown,可以按需修改
<dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-markdown-document-reader</artifactId><version>1.0.0-M6</version>
</dependency>
  • 读取官方示例
@Component
class MyMarkdownReader {private final Resource resource;MyMarkdownReader(@Value("classpath:code.md") Resource resource) {this.resource = resource;}List<Document> loadMarkdown() {MarkdownDocumentReaderConfig config = MarkdownDocumentReaderConfig.builder().withHorizontalRuleCreateDocument(true).withIncludeCodeBlock(false).withIncludeBlockquote(false).withAdditionalMetadata("filename", "code.md").build();MarkdownDocumentReader reader = new MarkdownDocumentReader(this.resource, config);return reader.get();}
}/*
The MarkdownDocumentReaderConfig allows you to customize the behavior of the MarkdownDocumentReader:horizontalRuleCreateDocument: When set to true, horizontal rules in the Markdown will create new Document objects.includeCodeBlock: When set to true, code blocks will be included in the same Document as the surrounding text. When false, code blocks create separate Document objects.includeBlockquote: When set to true, blockquotes will be included in the same Document as the surrounding text. When false, blockquotes create separate Document objects.additionalMetadata: Allows you to add custom metadata to all created Document objects.*/
  • 修改官网示例
package cn.varin.varaiagent.rag;import lombok.extern.slf4j.Slf4j;
import org.springframework.ai.document.Document;
import org.springframework.ai.reader.markdown.MarkdownDocumentReader;
import org.springframework.ai.reader.markdown.config.MarkdownDocumentReaderConfig;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.stereotype.Component;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;/*** 文档加载器*/
@Component
@Slf4j
public class IALDAAppDocumentLoader {// 价值本地资源private  final ResourcePatternResolver resourcePatternResolver;public IALDAAppDocumentLoader(ResourcePatternResolver resourcePatternResolver) {this.resourcePatternResolver = resourcePatternResolver;}public List<Document> loadDocuments() {List<Document> documents = new ArrayList<>();try {Resource[] resources = this.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);documents.addAll(reader.read());}} catch (IOException e) {throw new RuntimeException(e);}return documents;}}

3. 文档转换并写入

  1. 使用SimpleVectorStore基于内存存储的向量数据库,根据查看源码,我们可以发现,该数据库在执行add方法时,回调用embeddingModel
  2. 直接将md数据转为向量

具体实现

package cn.varin.varaiagent.config;import cn.varin.varaiagent.rag.IALDAAppDocumentLoader;
import jakarta.annotation.Resource;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;@Configuration
/**
* SimpleVectorStore基于内存读写的向量数据库
*/public class IALDAAppVectorStoreConfig {@Resourceprivate IALDAAppDocumentLoader iALDAAppDocumentLoader;// 注册VectorSotre//注意:EmbeddingModel使用SpringAI的,不要使用alibaba的@BeanVectorStore iALDAAppVectorStore(EmbeddingModel environment) {VectorStore  vectorStore = SimpleVectorStore.builder(environment).build();List<Document> documents = iALDAAppDocumentLoader.loadDocuments();vectorStore.add(documents);return vectorStore;}
}

4. 调用本地向量数据库查询

Spring AI 通过⁠ Advisor 特性提供了开箱即用的 RAG 功‌能。主要是 **QuestionAnswerAdvisor **问答拦截器和 RetrievalAug‎mentationAdvisor 检索增强拦截器‌,前者更简单易用、后者更灵活强大。

本文使用:QuestionAnswerAdvisor

// 类:IALDAApp@Resource
private VectorStore iALDAAppVectorStore;
public String  localhostVectorSaveMessage(String content,String chatId) {ChatResponse chatResponse = this.chatClient.prompt().user(content).advisors(advisor -> advisor.param("chat_memory_conversation_id", chatId)// 自定义日志.param("chat_memory_response_size", 10)).advisors(new MyLogAdvisor())// 本地知识库.advisors(new QuestionAnswerAdvisor(iALDAAppVectorStore)).call().chatResponse();String text = chatResponse.getResult().getOutput().getText();log.info("text:{}", text);return text;
}

5. 测试

@Test
void localhostVectorSaveMessage() {String uuid= UUID.randomUUID().toString();String message = ialdaApp.localhostVectorSaveMessage( "我在编写论文,遇到研究瓶颈(如实验数据不理想、理论支撑不足)时要怎么办",uuid  );System.out.println(message);}

5. 效果

从返回的结果查看,Ai大模型已经实现了查询本地向量数据库

============message ============
当你在编写论文时遇到研究瓶颈,比如实验数据不理想或理论支撑不足,可以按照“两步破局法”来有效应对:1. **诊断瓶颈类型并调整思路**- **若实验数据不理想**(如结果与假设相反),首先检查实验设计是否存在偏差,例如样本是否具有代表性、变量控制是否严密。如果实验设计合理,不要急于否定结果,而是尝试从新的角度解读数据——“反常结果”可能揭示了更有价值的研究问题。例如,AI教学工具使用率低,可能并非技术本身问题,而是教师培训不足所致,这反而可成为研究的创新点。- **若理论支撑不足**,建议拓展理论视野,不要局限于本领域常用理论。例如研究“AI教育公平”时,除了教育技术理论,还可引入“数字鸿沟理论”或“社会公平理论”,增强论文的解释力和学术深度。2. **寻求外部支持**- 与导师沟通时,避免只说“数据不好”这类笼统表达,应具体说明“哪部分数据不符合预期”“已排除哪些干扰因素”“目前的解释方向是什么”,以便获得有针对性的指导。- 参加小型学术研讨会或研究组会,通过同行交流获取新视角,有时他人的一句话可能激发你的突破性思路。此外,推荐你学习《**学术研究瓶颈突破与思路调整(进阶实战课)**》,该课程系统讲解瓶颈诊断方法、真实案例的破局路径以及如何高效与导师沟通,帮助你从“卡壳”走向“突围”。记住:研究瓶颈不是失败,而是深化思考的契机。关键在于主动分析、开放沟通、灵活调整。
============message ============

三、RAG实战:Spring AI+云知识库服务

云知识库服务采用:阿里云服务

阿里云云知识库链接:https://bailian.console.aliyun.com/?tab=app#/knowledge-base

需要使用到SpringAI 提供的Advisor:RetrievalAugmentationAdvisor

官网文档地址:https://docs.spring.io/spring-ai/reference/api/retrieval-augmented-generation.html#_retrievalaugmentationadvisor_incubating

  1. 步骤1 建立知识库
// 官网地址:
https://bailian.console.aliyun.com/?tab=app#/knowledge-base

  1. 步骤2:建立DocumentRetriever
// 官网说明:https://java2ai.com/docs/1.0.0-M6.1/tutorials/retriever/#%E7%A4%BA%E4%BE%8B%E7%94%A8%E6%B3%95
// 官网示例代码:
var dashScopeApi = new DashScopeApi(System.getenv("DASHSCOPE_API_KEY"));
DocumentRetriever retriever = new DashScopeDocumentRetriever(dashScopeApi,DashScopeDocumentRetrieverOptions.builder().withIndexName("spring-ai知识库").build());List<Document> documentList = retriever.retrieve(new Query("What's spring ai"));
  1. 步骤三:将DocumentRetriever放入到SpringAI中的Advisor中
// 官网文档说明:https://docs.spring.io/spring-ai/reference/api/retrieval-augmented-generation.html#_retrievalaugmentationadvisor_incubating
// 示例代码:
Advisor retrievalAugmentationAdvisor = RetrievalAugmentationAdvisor.builder().documentRetriever(VectorStoreDocumentRetriever.builder().similarityThreshold(0.50).vectorStore(vectorStore).build()).build();String answer = chatClient.prompt().advisors(retrievalAugmentationAdvisor).user(question).call().content();
  1. 步骤四:将二三步骤合并并创建一个配置文件,注入到Spring容器中
package cn.varin.varaiagent.config;import cn.varin.varaiagent.rag.IALDAAppDocumentLoader;
import com.alibaba.cloud.ai.dashscope.api.DashScopeApi;
import com.alibaba.cloud.ai.dashscope.rag.DashScopeDocumentRetriever;
import com.alibaba.cloud.ai.dashscope.rag.DashScopeDocumentRetrieverOptions;
import jakarta.annotation.Resource;
import org.springframework.ai.chat.client.advisor.RetrievalAugmentationAdvisor;
import org.springframework.ai.chat.client.advisor.api.Advisor;
import org.springframework.ai.document.Document;
import org.springframework.ai.embedding.EmbeddingModel;
import org.springframework.ai.vectorstore.SimpleVectorStore;
import org.springframework.ai.vectorstore.VectorStore;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;import java.util.List;@Configuration
/**
* 从阿里云上读取知识库,并使用对应的advisor
* 知识库地址:https://bailian.console.aliyun.com/?tab=app#/knowledge-base
*/public class IALDAAppRagAlibabaAdvisorConfig {@Value("${spring.ai.dashscope.api-key}")private String apikey;@Beanpublic Advisor iALDAAppRagAlibabaAdvisor() {DashScopeApi dashScopeApi = new DashScopeApi(apikey);final String DOCUMENT_NAME = "学术分析"; // 注意,该名称要和阿里云中的知识库名称一致DashScopeDocumentRetriever dashScopeDocumentRetriever = new DashScopeDocumentRetriever(dashScopeApi,new DashScopeDocumentRetrieverOptions.Builder().withIndexName(DOCUMENT_NAME).build() );return RetrievalAugmentationAdvisor.builder().documentRetriever(dashScopeDocumentRetriever).build();}}
  1. 步骤五:实现方法
/*** 读取阿里云知识库*/
@Resource
private Advisor iALDAAppRagAlibabaAdvisor;public String  cloudAlibabaDoChatWithRag(String content,String chatId) {ChatResponse chatResponse = this.chatClient.prompt().user(content).advisors(advisor -> advisor.param("chat_memory_conversation_id", chatId)// 自定义日志.param("chat_memory_response_size", 10)).advisors(new MyLogAdvisor())// 本地知识库.advisors(iALDAAppRagAlibabaAdvisor).call().chatResponse();String text = chatResponse.getResult().getOutput().getText();log.info("text:{}", text);return text;
}
  1. 步骤六:测试方法
@Test
void cloudAlibabaDoChatWithRag() {String uuid= UUID.randomUUID().toString();String message = ialdaApp.cloudAlibabaDoChatWithRag( "我是软件工程专业,怎么开始写论文",uuid  );System.out.println(message);
}
  1. 步骤起:效果
    1. 查询结果中,已经实现了查询云知识库了。
cloudAlibabaDoChatWithRag:=================== 
作为软件工程专业的学生,开始写论文可遵循以下步骤:1. **确定研究方向与选题**  结合专业特点和个人兴趣,初步锁定一个具体领域,例如“基于人工智能的代码缺陷检测”“软件测试自动化工具优化”或“开源项目中的协作模式分析”。避免选题过于宽泛(如“软件工程的发展”)或过窄(如“某公司某项目的界面颜色设计”)。通过CNKI、Web of Science等平台检索近3年文献,识别研究热点(如“大模型在代码生成中的应用”)和研究空白(如“生成代码的安全性评估”),并咨询导师意见,验证选题的学术价值和可行性。2. **明确研究问题与方法**  根据研究问题选择合适的方法。若问题是“某类算法的性能如何”,适合定量方法(如实验对比、统计分析);若问题是“开发者为何不愿采用某类工具”,则适合定性方法(如访谈、案例研究)。确保方法与问题匹配,避免误用。例如,研究“程序员对新型开发框架的态度”应采用访谈而非仅靠问卷打分。3. **构建论文基本框架**  采用IMRaD结构组织内容:- **引言**:从行业背景(如“软件迭代速度加快”)引出具体问题(如“传统测试难以覆盖复杂场景”),说明研究意义与创新点。- **方法**:详细描述实验设计、数据来源(如GitHub项目)、样本选择标准、分析工具(如Python、JIRA数据分析)等,保证可复现。- **结果**:客观呈现数据,使用图表展示性能指标、用户反馈等。- **讨论**:解释结果如何回应研究问题,与已有研究比较,指出局限性与未来方向。4. **参考核心文献与投稿准备**  查阅《软件学报》《计算机学报》《IEEE Transactions on Software Engineering》等期刊中类似主题的论文,学习其结构与表达。完成初稿后,根据“四步筛选法”选择目标期刊:匹配主题、查看投稿要求、评估录用难度、参考相似文献发表期刊,提高录用概率。建议学习相关课程系统掌握写作与研究方法,如:[《学术选题与研究价值评估(零基础入门课)》](https://www.bilibili.com/)[《学术论文IMRaD框架构建与逻辑优化(进阶课)》](https://www.bilibili.com/),帮助快速建立规范的研究思维与写作能力。
cloudAlibabaDoChatWithRag:=================== 

http://www.dtcms.com/a/431519.html

相关文章:

  • 南山商城网站建设多少钱广告设计与制作是做什么的
  • React18学习笔记(四) 路由案例--记账本
  • display ospf lsdb 概念及题目
  • 做爰全过程免费的视网站郑州汉狮做网站的大公司
  • 前端网站大全gps建站步骤
  • python基础语法速通
  • 中国地级市旅游人数、收入数据(2000-2023年)
  • 计算机毕设做网站难吗广州seo托管
  • 高端网站设计如何兼顾美学与转化率?
  • 软件下载网站如何履行安全管理义务确保提供的软件广州冼村为什么有钱
  • 嵌入式开发笔记(1)
  • 泉州 网站建设公司首选北京海淀区的科技有限公司
  • 数字化先期质量策划:论全星APQP系统对传统PLM理念的超越与重塑
  • C++lambda函数
  • 第 5 天:C 语言运算符与表达式 —— 数据处理的工具集
  • [深度学习] 大模型学习5-高效微调框架Unsloth使用指北
  • 家教网站代理做彩票网站是违法的吗
  • 南康网站建设wplms wordpress
  • 专注网站建设16年网站多级栏目
  • 四川建设厅电子证书官方网站我想做卖鱼苗网站怎样做
  • 所有字符的ASCII码值(0-127,按照序号、字符、描述、十进制、十六进制列表显示)(完整版)
  • 门控融合机制
  • 做本地的分类信息网站网络营销的特点是什么
  • grep 命令
  • 网站开发运营专业做足球体彩网站
  • 做外贸网站的价格最新新闻热点事件2021年10月
  • iBizModel 实体值规则模型(PSDEFVALUERULE)详解与应用
  • 大数据Spark(六十五):Transformation转换算子groupByKey和filter
  • sward入门到实战(11) - 如何有效保障文档的安全可靠
  • Qt---尺寸调整函数汇总