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

AI应用学习-RAG基础

1.RAG的概念及作用1.大模型的缺陷首先要知道RAG是什么能做什么他是如何应用的我们需要先了解一下大模型的缺陷我们在用一些ai对话工具时你有时候问一个问题会发现1.偶尔他回答的就是胡说八道更过分可能风马牛不相及俗称幻觉2.你问一下比较新的知识他回答不上来3.问一个你擅长的小众的领域知识或者黑话他不知道为啥呢这中间存在很多因素就会造成这些问题下面简单说明一下包括但不限于例如1.工具背后的模型训练参数不够或者吸取了无效知识然后它本身目标生成是找最符合上下文概率分布的没有明确答案的时候它可能随便捏造一个.2.本身知识更新有点缓慢小参数模型或者私有部署的更明显.3.训练时可能更多的追求广度去学习一些基本的公开的数据对于极个别专业的领域深度不够.2.RAG引入上面简单引入了一些问题和对它产生问题的分析不一定完全准确只是阐述下大概的意思重点是能理解就行还有没有其他的原因呢也许有不过没必要深究那对于产生问题的几点因素如何解决呢1.提示词工程2.RAG 检索增强生成3.模型微调这三个分别由易到难排列大佬除外然后附上各自对应解决的问题类型提示词在上一篇分享中有可以参靠但是我个人理解提示词主要针对的问题点是教会和指导你如何提问解决的是因为你不会提问导致的回答不准在这部分我主要介绍RAG问题类型最佳方案解决胡说八道幻觉提示词约束 RAG新知识不懂RAG实时更新小众领域不行RAG快速注入或微调深度内化3.什么是RAG?RAG(检索增强生成)的初衷是为了增强大模型的事实性时效性减少幻觉引入专业知识优化生成回复举个大白话例子你入职一个公司做点人事, 想问大模型我们公司内部裁员的流程或者各种套路那它肯定不知道后面你找老板说把秘密.PDF发给你然后你给到了大模型学习一下后面再问的时候他就知道了Q如何降本增效A: 多增加管理流程制定各种考核试试服从性Q: 哇哦学到了这里注意不要搞混了1.模型微调的过程会改变模型中数十亿甚至数千亿个连接的权重。训练完成后这些新知识就固化在模型里了模型变得“不同”了。就像让学生复读一年用新的教材、新的习题集你的专业数据重新学习。2.RAG不改变模型。它只是把检索到的内容和你的问题拼在一起形成一个更长的、包含答案线索的提示词再发给模型。模型只是基于这个更丰富的输入来生成答案。就类似学生不改变还是原来的知识水平。但在考试的时候你允许他带一本专门针对这场考试的书他做到一个不会的问题翻书翻到了把问题答案一起给大模型然后又大模型组织输出给你。2.RAG的工作流程RAG的发展过程也分为3个阶段朴素RAGNaive、高级RAGAdvanced、模块化RAGModular目前只学习了普通和高级这里用普通的作为实战参考后续会继续高级部分朴素RAGNaive从图中可以看出如果总结一下它主要包含3个重要阶段1.索引化在准备阶段将文档切分切割成片段再编码为向量存储在向量数据库里。2.检索问答阶段在向量数据库中检索到与问题相似度最高的top k的片段只有一次检索只用向量相似度。3.生成将原始问题和检索得到的块所有内容都作为LLM的输入提示词令其生成最终的回答。但它在实际应用中会有不少坑比如检索到的内容不相关翻错页了检索到的内容太多或太少翻到的页数不对多个资料矛盾参考书前后说法不一大模型忽略了检索到的资料类似学生没看参考书那这时就可以用Advanced RAG来进行优化高级RAGAdvanced)在高级RAG优化增强了各个阶段就是再把普通RAG的每个阶段都增强。1.索引优化在数据准备阶段做的更精细切分数据更智能可以按段落、句子、语义边界切并保留重叠保留元数据标题、章节、时间、作者检索时能按照元数据过滤。2.检索可以查询改写让大模型先把问题优化成更适合检索的多个子问题或者关键词不只是直接返回top k判断而是用一个更精准的排序模型对召回结果重新打分检索先找相关文档再在文档内部找段落或根据第一次结果二次检索递归迭代。3.生成将原始问题和检索得到的块进行上下文压缩只保留与问题最相关的句子控制长度。生成后让模型自查答案是否基于资料有幻觉就重新生成进行自我纠错多个答案用投票或大模型总结的方式统一多个来源的答案。1.数据准备文档分块策略1.按照句子来切分import re text拖延症作为现代人类与截止日期之间的一场漫长博弈致力于将“稍后再做”这一概念发挥到极致。在这个领域大脑的奖励机制发挥着至关重要的误导作用。利用多样的借口我们得以逃避、推迟乃至遗忘那些本该完成的任务。从深夜刷手机到整理并不乱的桌面从计划明天的健身到发呆拖延症的应用已遍布各个生活场景。随着焦虑情绪的飞速逼近我们的工作效率与心态均遭遇了巨大挑战。如今部分尖端的拖延症患者甚至能够处理极其复杂的赶工任务如在最后一小时完成整篇论文、在通勤路上解决所有邮件和会议等。拖延症的研究推进不仅优化了我们“生死时速”的心理素质也对提升我们在高压环境下的爆发力起到了关键作用。 sent re.split(r(。|||\...\...), text) print(f分割后的数据是:{sent}) chunks [] print(type(chunks)) for sen,pun in zip(sent[::2],sent[1::2]): chunks.append(senpun) print(f拼接后的数据是{chunks})2.按照字符数来切分text.......... chunks [] for i in range (0,len(text),50): chunks.append(text[i:i50]) print(chunks)3.按固定字符数 结合overlapping windowdef overlap_split(text, n, stride): for i in range(0, len(text), stride): print(text[i: i n]) text ...... overlap_split(text, 100, 20)4.递归方法 使用langchain的RecursiveCharacterTextSplitterfrom langchain.text_splitter import RecursiveCharacterTextSplitter text.........需要被索引的文档数据 split_data RecursiveCharacterTextSplitter( chunk_size 50, chunk_overlap10, length_functionlen, # text_splitterTextSplitter, ) print(split_data) data split_data.split_text(text) print(data)3.向量和Embedding1.向量在数学中向量也称为欧几里得向量、几何向量指具有大小magnitude和方向的量。它可以形象化地表示为带箭头的线段。箭头所指代表向量的方向线段长度代表向量的大小。1.将文本转成一组浮点数每个下标 i对应一个维度 2.整个数组对应一个 n 维空间的一个点即文本向量又叫 Embeddings 3.向量之间可以计算距离距离远近对应语义相似度大小上面的这段话摘抄自专业术语我也不知道对不对大白话理解向量就是一个特征代号清单AI眼中电脑不懂如何定义具体对象和物品他只认识数字例如我需要描述一只猫怎么描述是不是活的1 代表是0 代表不是 - 1有没有毛 - 1会不会抓老鼠体型大小0-1--0.3凶猛程度那他的清单向量就是[110.90.30.1]同理我们再扩展2个老虎和汽车按照清单老虎可以是[110.80.90.8]汽车就是 [0,0,0,0.5,0]可以发现猫和老虎有些层面他们一致甚至很相似但是和汽车却相差很远换句话说如果2个对象或者2段话他们的意思差不多那么转化的那串数字长得就很像在数学空间里他们距离就近反之就离得远。这种利用距离表示相似度的计算方式有2种一个叫余弦距离Cosine一种叫欧式距离L2他们都是值越小越相似与余弦距离还有一个紧密相关的概念余弦相似度 (Cosine Similarity)就不是它是值越大越相似。那么大模型是怎么回答问题的呢?我们所提的问题会转换成向量, 然后会拿这个向量在向量空间进行对比,找到和小猫相近的内容,比方说老鼠,有没有毛,离的比较近那么大模型会根据概率的问题把这句话完整的写出来(当然其中还需要很多其他的东西)。2.Embedding数据的向量其实是非常复杂的,表示学习会对向量进行优化得到的一个新的向量内容我们会叫做嵌入。嵌入:表示学习的一种形式通常用于将高维数据映射到低维空间中的表示形式。嵌入可以是词嵌入、图像嵌入、图嵌入等。例如在自然语言处理中词嵌入将词语映射到低维向量空间以捕捉词语之间的语义和句法关系。在图像处理中图像嵌入将图像映射到低维向量空间以表示图像的视觉特征。它和向量的关系就是通过Embedding把具体描述的对象转换为向量数字。我们在使用时不需要过多关注Embedding都是使用现成的转换工具可以使用自己部署的私有向量模型也可以使用一些厂商提供的我下面就是使用百炼的免费向量模型。from openai import OpenAI from dotenv import load_dotenv import os load_dotenv() # 2. 获取配置信息 API_KEY os.getenv(QW_KEY) API_URL os.getenv(QW_URL) # 3. 初始化客户端 client OpenAI(api_keyAPI_KEY, base_urlAPI_URL) def get_embedding(text): data client.embeddings.create(inputtext,modeltext-embedding-v2) return [i.embedding for i in data.data] test_query [小猫] vecget_embedding(test_query) print(vec) print(len(vec[0])) test_query [老虎] vecget_embedding(test_query) print(vec) print(len(vec[0]))最终调用输出就是这样的数据上面只用了5个维度举例这里结果数组有1536个也可以理解为用了1536个维度来表示小猫或者老虎维度越多代表越细至于有哪些我也没研究过内部计算肯定是非常复杂的而且和不同模型有关从成本权衡的角度出发维度越多计算越慢占用的存储空间也越大。3.本地部署向量模型1.可以访问魔塔社区[1] 去选择文本向量然后选择需要的下载自己需要的模型2.安装魔塔的下载器然后下载到具体目录 先设置下目录的下载参数export MODELSCOPE_CACHE/Users/yui/3.Resources/Demo/llm/embdding/bge-large-zhv15 #把所有文件下载这里 export MODELSCOPE_DOWNLOAD_THREADS10 #开启10个线程一起下pip install modelscope # 下载模型到本地 # pip install modelscope from modelscope import snapshot_download #这里是mac的路径windows直接输入具体路径 model_dir snapshot_download(BAAI/bge-large-zh-v1.5, cache_dir/Users/yui/3.Resources/Demo/llm/embdding/bge-large-zhv15) print(f模型下载完成)3.本地嵌入模型# pip install sentence-transformers 下载用来加载模型库的包 from sentence_transformers import SentenceTransformer # 1. 加载本地模型 # 注意Mac 路径使用正斜杠 /且不需要 r 前缀 model SentenceTransformer(/Users/yui/3.Resources/Demo/llm/embdding/bge-large-zhv15/BAAI/bge-large-zh-v1___5) # 2. 准备数据 data [你好] # 3. 转换成向量 embedding model.encode(data) # 4. 打印结果 print(embedding.shape)4.向量距离计算就是将输入的问题以及对存在的多个答案或者一堆答案进行向量化然后将输入的向量和答案的向量根据不同的算法进行相似度计算具体看下面吧~余弦距离Cosine基于两个向量夹角的余弦值来衡量相似度,计算公式: 两个向量的乘积 / 两个向量范数的乘积 A×B / ∥A∥ × ∥B∥ 范数: l1(绝对值), l2(勾股定理), l无穷欧式距离L2通过计算向量之间的欧几里得距离来衡量相似度。点积计算两个向量的点积适合归一化后的向量。import os import numpy as np from numpy import dot from numpy.linalg import norm from openai import OpenAI from dotenv import load_dotenv # 1. 初始化配置 load_dotenv() API_KEY os.getenv(QW_KEY) API_URL os.getenv(QW_URL) client OpenAI(api_keyAPI_KEY, base_urlAPI_URL) # 2. 定义相似度计算函数 def cos_sim(a, b): 余弦相似度 范围: [-1, 1]越大越相似 (1 表示完全相同) return dot(a, b) / (norm(a) * norm(b)) def l2_distance(a, b): 欧氏距离 范围: [0, ∞)越小越相似 (0 表示完全相同) return norm(np.asarray(a) - np.asarray(b)) # 3. 定义获取向量的函数 def get_embedding(texts): 调用 API 获取文本向量 # 如果传入的是字符串转为列表以统一处理 if isinstance(texts, str): texts [texts] response client.embeddings.create(inputtexts, modeltext-embedding-v2) return [item.embedding for item in response.data] # 4. 准备数据 query 人工智能的发展对就业市场的影响 documents [ 全球气候变化导致极端天气事件频发, 某科技公司发布了新一代智能手机, 专家预测AI将取代部分重复性工作同时创造新的岗位, 国际足联宣布2026年世界杯举办地, 本地超市推出夏季促销活动 ] # 5. 计算向量 # 获取查询向量 (取第一个元素因为返回的是列表) query_vec np.array(get_embedding(query)[0]) # 获取文档向量列表 doc_vecs [np.array(vec) for vec in get_embedding(documents)] # 6. 打印结果 print(f--- 查询: {query} ---\n) print(【余弦相似度】(越大越相似最大为 1):) for i, doc in enumerate(documents): score cos_sim(query_vec, doc_vecs[i]) print(f{score:.4f} - {doc}) print(\n【欧氏距离】(越小越相似最小为 0):) for i, doc in enumerate(documents): dist l2_distance(query_vec, doc_vecs[i]) print(f{dist:.4f} - {doc})可以看第一个距离其中最大的是第三个0.6第二个距离最小的也是第三个0.8所以就匹配成功这一步咱们已经能把提问和答案进行向量化后续就需要把向量存起来那就需要使用到向量数据库这里容易有个误区向量数据库存储的是“答案”而问题不需要存起来~4.向量数据库使用向量数据库已成为数据管理和AI模型不可或缺的一部分。向量数据库是一种专门设计用来存储和查询向量嵌入数据的数据库他的作用就是存储被向量化的非结构化数据并没有很神秘就像mysqlsqlserver一样存储的一般是结构化的数据只不过侧重点不同而已。我们来熟悉一下在AI中通常使用哪些向量数据库数据库名称类型核心优势适用场景Milvus专用开源性能怪兽分布式架构支持千亿级向量高可用生态最完善。超大规模企业级应用、海量数据检索。Qdrant专用开源Rust 编写内存效率高速度极快API 设计现代支持复杂的过滤查询。对性能敏感、资源受限、追求现代化的 RAG 系统。Weaviate专用开源AI 原生内置向量化模块不用自己调 API支持图数据库功能知识图谱。快速构建 RAG、需要语义与知识图谱结合的场景。Chroma专用开源极简轻量Python 开发者最爱可嵌入代码运行无需独立服务器开发调试极快。本地开发测试、快速原型验证、中小型应用。Pinecone全托管 SaaS开箱即用完全托管自动扩缩容稳定性极高无需运维。初创团队、不想运维、追求极致稳定的生产环境。ElasticSearch传统扩展混合搜索之王全文检索关键词 向量检索结合得最好生态成熟。已有 ELK 技术栈、需要复杂关键词过滤语义搜索的场景。Redis传统扩展极速缓存基于内存读写速度微秒级支持向量索引。实时推荐、作为缓存层加速、对延迟要求极高的场景。PostgreSQL传统扩展SQL 融合通过pgvector插件支持既能存用户数据又能存向量用 SQL 就能查。已有 PG 架构、中小规模数据、不想引入新数据库的团队。建议•想省事、不差钱 ➡️ Pinecone•数据量巨大亿级、追求极致性能 ➡️ Milvus•追求轻量高性能 ➡️ Qdrant•Python 开发、做个 Demo 或内部工具 ➡️ Chroma•不想引入新组件、已有 PG 数据库 ➡️ pgvector•需要“关键词语义”混合搜索 ➡️ ElasticSearch•缓存加速 ➡️ Redis1. chroma演示在学习阶段就是用chroma来作为向量数据库比较方便1.安装chromapip install chromadb0.5.32.chroma基本操作使用import chromadb # 创建客户端存内存 client chromadb.Client() #创建客户端存本地文件系统 #client chromadb.PersistentClient(/Users/yui/3.Resources/Demo/llm/db/chroma) # 创建或者获取当前db cli client.get_or_create_collection(namechroma_test) # 添加数据 cli.add( documents[张三,李四,王五] # 添加元素 ,embeddings[[1,2,3],[4,5,6],[7,8,9]] #对应3个向量[7,8,9]:王五 ,ids[1,2,3])#对应id 1张三... # 查询收据 getData cli.get(ids[3],include[embeddings,documents],where_document{$contains:五}) print(f查询数据{cli.get()}) #删除数据 cli.delete(ids[3]) print(f删除后的数据{cli.get()}) #修改数据 cli.update( documents[赵6,李四,王五] ,embeddings[[1,2,3],[4,5,6],[7,8,9]] ,ids[1,2,3] ) print(f修改后的数据{cli.get()})2.结合Chroma、Embedding操作结构化数据思路1.准备结构化json文件数据,在真正的RAG中这些数据的来源可能从数据库也可能从接口请求来2.将文件数据的问题进行向量化答案作为文档数据然后存入向量数据库3.把用户提问的问题进行向量化然后搜索向量库1.先准备一些结构化的json数据。{instruction: 这段时间去上厕所本来想小便的可是每次都会拉大便, input: , output: 这可能是因为你的饮食习惯或者消化系统的问题导致的。建议你试着调整一下饮食增加膳食纤维的摄入量多喝水避免过度依赖泻药。同时如果问题持续存在建议去医院检查一下排除肠道疾病等可能性。} {instruction: 医生呀我刚被查出得了白癜风不知道初期治疗需要多少钱, input: , output: 白癜风的治疗费用因个体差异和治疗方案的不同而有所差异。初期治疗主要以口服药物和外用药物为主费用相对较低一般几百元左右。但是如果采用激光治疗、光疗等高端治疗方法费用会更高。建议您咨询专业医生根据自己的情况进行治疗方案的选择同时了解相关的费用情况。} {instruction: 男朋友31岁前列腺B超数据是34*48*31包膜完整平滑内部回声均匀未见明显异常回声结论是前列腺肥大增生请问情况很严重嘛该怎么治疗呢, input: , output: 根据您提供的数据男朋友的前列腺B超结果表明前列腺肥大增生但是并未出现明显异常回声所以情况并不算严重。前列腺增生是男性常见的一种生理现象是由于年龄增长和性激素水平变化引起的。具体治疗方案需要根据症状和严重程度来确定一般包括药物治疗和手术治疗两种方式。\n\n药物治疗可以采用口服药物或者局部治疗如口服α1-受体阻滞剂、5α-还原酶抑制剂、荷尔蒙治疗等。手术治疗主要包括经尿道电切术、经皮穿刺前列腺电子治疗、经皮穿刺前列腺热疗、经直肠前列腺切除术等。\n\n建议男朋友及时就医并由专业医生根据具体情况制定合适的治疗方案。同时男性朋友应该保持良好的生活习惯如均衡饮食、适量运动、避免过度劳累等有助于减缓前列腺肥大增生的进程。} {instruction: 左大腿脾经内侧疼痛大概有6寸左右有几天了不知道怎么导致的表面没什么就是一按就刺痛这怎么回事, input: , output: 左大腿内侧疼痛可能是由多种因素引起的例如\n\n1. 肌肉劳损或拉伤如果您最近进行了剧烈的运动或活动可能会导致肌肉劳损或拉伤从而引起疼痛。\n\n2. 腰椎间盘突出腰椎间盘突出也可能会引起大腿内侧疼痛尤其是在坐姿或弯腰时更加明显。\n\n3. 神经痛大腿内侧疼痛可能是由于神经受损或受压所致。神经痛通常表现为刺痛或针刺感。\n\n4. 骨折或骨裂如果您最近遭受了外伤或摔倒可能会导致骨折或骨裂引起大腿内侧疼痛。\n\n建议您及时到医院进行检查确定疼痛的原因并针对性治疗。同时您可以适当休息、热敷或按摩缓解疼痛。} {instruction: 你好全身没劲没精神吃不下饭只想睡觉是什么情况, input: , output: 这些症状可能是身体出现了一些问题建议您去看医生进行检查。这些症状可能和许多疾病有关比如抑郁症、贫血、甲状腺问题等等。医生可以为您进行全面的身体检查帮助您找到病因并给出相应的治疗建议。同时您可以尝试保持良好的生活习惯例如规律作息、均衡饮食、适量运动等这些都有助于提高身体的免疫力和健康状况。} {instruction: 喉咙发紧干精神有点紧绷早上起来手也没有力气。一直在担心。, input: , output: 您可能需要注意以下几点\n\n1. 饮食方面注意多喝水并避免食用刺激性食物如辣椒、咖啡、酒等。\n\n2. 保持室内空气湿润可以使用加湿器或者放置一盆水。\n\n3. 适当休息避免过度疲劳。可以尝试进行一些轻度的运动或者放松的活动如瑜伽、冥想等。\n\n4. 如果症状持续或者加重建议就医或者咨询医生。可能需要进一步的检查和治疗。} {instruction: 女宝宝十个半月体重十六斤多身高67cm是不是发育太慢了最近三个月身高没有变法一颗牙都没有扎也不流口水, input: , output: 根据你提供的数据宝宝的体重和身高处于正常范围内。一般来说女宝宝的身高增长速度会在出生后逐渐变慢尤其是在10个月左右时会明显减缓。此外宝宝的牙齿生长时间也有差异有些宝宝可能在10个月左右才开始长牙。因此你不必过于担心宝宝的发育情况但如果你还是有疑虑建议咨询儿科医生的意见。} {instruction: 就是庠没有其他问题然后想知道用什么药或者怎么样才能好还有是什么原因弄成这样的, input: , output: 很抱歉我不清楚您所指的具体情况是什么。如果您有身体不适或疾病建议您咨询医生或专业医疗机构以便获得准确的诊断和治疗建议。} {instruction: 我是早段时候觉得我总是脚疼一开始没在意后来是疼的厉害就去医院看了检查下来是尿酸高我想知道这样的话需要注意什么还有饮食方面可以吃咸菜吧。, input: , output: 如果您被诊断为尿酸高需要注意以下几点\n\n1. 饮食方面尿酸高的人需要避免高嘌呤食物如猪肝、肾脏、海鲜、肉类、鱼子酱等。此外您应该控制蛋白质的摄入量每天的摄入量不应超过100克。咸菜中含有较高的盐分不建议长期食用。\n\n2. 控制体重肥胖是尿酸高的重要因素之一因此您需要控制体重保持健康的体重。\n\n3. 饮水增加饮水量有助于尿酸的排出。\n\n4. 合理运动适量的运动可以帮助减轻体重降低尿酸水平。\n\n5. 避免饮酒饮酒可以增加尿酸的产生和减少排出所以需要避免饮酒。\n\n如果您的尿酸值很高建议您去医院找专业医生进行诊治。同时也要注意饮食和生活习惯的改变以降低尿酸水平保持身体健康。}2.通过调用embedding模型来进行向量化 3.根据具体问题搜索import chromadb import json from openai import OpenAI from dotenv import load_dotenv import os class MyVectoryDbConnector: def __init__(self): # 初始化 ChromaDB 持久化客户端 self.db chromadb.PersistentClient(Users/yui/3.Resources/Demo/llm/db/chroma) # 获取或创建集合 self.collection self.db.get_or_create_collection(case_db) pass # 原始代码保留 def get_embedding(self, text, modeltext-embedding-v2): # 初始化 OpenAI 客户端从环境变量读取 Key 和 URL client OpenAI(api_keyos.getenv(QW_KEY), base_urlos.getenv(QW_URL)) # 调用 API 获取嵌入向量 data client.embeddings.create(inputtext, modelmodel).data return [x.embedding for x in data] def add_document(self, content, output): # 获取内容的向量 embeddings self.get_embedding(content) # 将文档、向量和 ID 添加到数据库 self.collection.add( documentsoutput, embeddingsembeddings, ids[fid{i} for i in range(0, len(output))] ) def search(self, query): # 获取查询语句的向量 q_embeddings self.get_embedding(query) # 在数据库中查询最相似的 n_results 条数据 result self.collection.query( query_embeddingsq_embeddings, n_results2 ) return result if __name__ __main__: # 加载 .env 环境变量 load_dotenv() # 读取 JSON 文件按行解析 with open(train_zh.json, r, encodingutf-8) as f: data [json.loads(line) for line in f] # 提取前 10 条数据的 instruction 和 output instruction [entry[instruction] for entry in data[0:10]] outputs [entry[output] for entry in data[0:10]] # 初始化数据库连接器 db MyVectoryDbConnector() # 添加文档到向量库 db.add_document(instruction, outputs) # 定义查询语句 user_query 吃不下饭 # 执行搜索 result db.search(queryuser_query) ids result[ids][0] documents result[documents][0] print(f--- 查询: {user_query} ---) # 使用 zip 同时遍历 id 和 文档内容 for i, (doc_id, doc_content) in enumerate(zip(ids, documents)): print(f\n[结果 {i 1}]) print(fID: {doc_id}) print(f文档: {doc_content})4.结果5.RAG平台搭建的方式现在有很多的平台提供的功能就把RAG包括在内例如Coze扣子、Dify、FastGPT这些平台化产品都内置了完整 RAG 能力主打低代码 / 无代码上手快 不用自己搭向量库、处理文档、做分段召回 维护简单部署省心但代价也很明显灵活性被锁死想改召回策略、模型逻辑、工作流往往改不动只能用平台给的功能。 成本不可控今天便宜明年可能涨价几倍用量一大费用直接起飞。 数据安全本质上不可靠你理解的安全 别人不知道 安全平台定义的安全你把秘密交给我我承诺不泄露 安全只要文档上传到别人服务器就不再完全属于你。1.本地部署FastGPT接下来使用FastGPT来试试RAG不需要本地部署大模型现在各大厂商都在拉用户免费的学习体验完全够用我们就用百炼的。至于fastgpt具体安装步骤建议去看官方文档上的步骤使用docker部署相对来说非常简单,写好配置文件然后Docker-compose 一键启动就完事了。2.使用知识库1.部署成功后打开docker会发现他依赖了很多中间件在内部它把这些当做插件来读取的。2.如果容器运行正常那么此时你打开http://localhost:3000/[2] 就可以登录账号root 密码12343.先创建知识库然后上传文件进行rag中间还有很多设置模型的一般都很傻瓜一看就明白4.再创建Agent选择对应知识库和模型5.保存发布选择渠道可以生成api也可以生成免登录连接6.访问链接后进行问答6.然后访问连接进行问答就好了6.结合大模型代码实战1.现在将Embedding、还有大模型一起来做一个简单的问答Embedding 和llm都是采用阿里百炼的免费模型简单的时序图如下伪代码思路主要分为几部分各自职责如下1.读取PDF或者word ,需要先下载包模块然后定义读取pdf函数和切割文档函数pip install -i https://pypi.tuna.tsinghua.edu.cn/simple python-docx pip install -i https://pypi.tuna.tsinghua.edu.cn/simple pdfminer.six# 定义读取pdf函数 def extract_text_from_pdf(filename,page_numberNone,min_size1): pass # 切割文档 使用滑动这样就不会截断句子 def sliding_window(text, chunk_size, stride): pass2.定义MyVectorDBConnector类主要用来embedding把结果添加到向量库、根据查询条件从向量库中查询class MyVectorDBConnector: def __init__(self): pass def get_embeddings(self, texts, modeltext-embedding-v3): pass def add_document(self,instruction): pass def search_document(self,query,n_results): pass3.定义问答类用来组装查询结果及调用大模型class RAG_bot: #同c#中的构造函数 def __init__(self,vector_db,n_res): pass #调用大模型 def get_complete(self,prompt,modelqwen-turbo): pass #回答输出 def chat(self,query): pass4.然后入口函数中准备提示词及调用if __name__ __main__: load_dotenv() prompt_template 你是一个问答机器人。已知信息: __INFO__用户问__QUERY__请用中文回答用户问题。 page_data extract_text_from_pdf(财务管理文档.pdf,page_number[0,1,2]) vector MyVectorDBConnector() vector.add_document(page_data) rag_bot RAG_bot(vector_dbvector,n_res2) rag_bot.chat(财务管理权限划分)完整代码如下import os import chromadb from dotenv import load_dotenv from openai import OpenAI from pdfminer.high_level import extract_pages from pdfminer.layout import LTTextContainer # --- 文本处理函数 --- def sliding_window(text, chunk_size, stride): 使用滑动窗口将文本分割成指定大小的块。 Args: text (str): 待分割的原始文本。 chunk_size (int): 每个文本块的大小。 stride (int): 滑动步长。 Returns: List[str]: 分割后的文本块列表。 result [] for i in range(0, len(text), stride): chunk text[i:i chunk_size] result.append(chunk) return result def extract_text_from_pdf(filename, page_numberNone, min_size1): 从 PDF 文件中提取文本并使用滑动窗口进行分块。 Args: filename (str): PDF 文件路径。 page_number (List[int], optional): 指定要提取的页码列表从0开始。如果为None则提取所有页。 min_size (int, optional): 未在当前逻辑中使用保留参数。 Returns: List[str]: 提取并分块后的文本列表。 paragraphs [] full_text # 读取PDF内容 content extract_pages(filename) # 将内容读取出来为文本加入 full_text for i, page_layout in enumerate(content): # 如果指定了页码且当前页不在指定页码中则跳过 if page_number is not None and i not in page_number: continue if page_layout is not None: for element in page_layout: if isinstance(element, LTTextContainer): # 提取文本并移除换行符 full_text element.get_text().replace(\n, ).replace(, ) # 如果 full_text 有内容再调用滑动切分 if full_text: text_chunks sliding_window(full_text, 250, 100) for chunk in text_chunks: paragraphs.append(chunk) return paragraphs # --- 向量数据库连接器 --- class MyVectorDBConnector: 封装 ChromaDB 操作和文本嵌入生成的类。 def __init__(self): 初始化 ChromaDB 客户端和集合。 self.db chromadb.Client() self.collection self.db.get_or_create_collection(Rag_case) def get_embeddings(self, texts, modeltext-embedding-v3): 获取文本列表的嵌入向量。使用分批处理以避免超过 API 限制。 Args: texts (List[str]): 待嵌入的文本列表。 model (str, optional): 使用的嵌入模型名称。默认为 text-embedding-v3。 Returns: List[List[float]]: 嵌入向量列表。 # 初始化 OpenAI 客户端 (使用 Qwen API) client OpenAI(api_keyos.getenv(QW_KEY), base_urlos.getenv(QW_URL)) all_embeddings [] batch_size 10 # 【关键】根据报错这里最大只能是 10 # 1. 循环切分列表 for i in range(0, len(texts), batch_size): # 取出当前批次例如 0-10, 10-20... batch_texts texts[i: i batch_size] # 2. 发送请求 try: response client.embeddings.create(inputbatch_texts, modelmodel) # 3. 提取向量并加入总列表 # 注意这里要遍历 response.data for item in response.data: all_embeddings.append(item.embedding) except Exception as e: print(f❌ 处理第 {i} 到 {i batch_size} 条数据时出错: {e}) raise e return all_embeddings def add_document(self, instruction): 将文档文本添加到向量数据库中。 Args: instruction (List[str]): 待添加的文档文本列表。 embeddings self.get_embeddings(instruction) self.collection.add( embeddingsembeddings, documentsinstruction, ids[fid{i} for i in range(len(instruction))] ) def search_document(self, query, n_results): 在向量数据库中搜索与查询最相关的文档。 Args: query (str): 查询文本。 n_results (int): 返回的结果数量。 Returns: QueryResult: ChromaDB 的查询结果对象包含匹配的文档等信息。 query_embeddings self.get_embeddings([query]) result self.collection.query( query_embeddingsquery_embeddings, n_resultsn_results ) return result # --- RAG 机器人 --- class RAG_bot: 实现 RAG (检索增强生成) 逻辑的聊天机器人。 def __init__(self, vector_db, n_res): 初始化 RAG 机器人。 Args: vector_db (MyVectorDBConnector): 向量数据库连接器实例。 n_res (int): 每次检索返回的文档数量。 self.vector_db vector_db self.n_res n_res def get_complete(self, prompt, modelqwen-turbo): 调用大语言模型生成回复。 Args: prompt (str): 发送给模型的提示词。 model (str, optional): 使用的模型名称。默认为 qwen-turbo。 Returns: str: 模型生成的文本回复。 message [{role: user, content: prompt}] client OpenAI(api_keyos.getenv(QW_KEY), base_urlos.getenv(QW_URL)) response client.chat.completions.create( modelmodel, messagesmessage, temperature0 ) return response.choices[0].message.content def chat(self, query): 处理用户聊天查询。 1. 使用查询在向量数据库中搜索相关文档。 2. 将相关文档和用户查询组合成提示词。 3. 调用大语言模型生成回复。 4. 打印回复。 Args: query (str): 用户的查询。 # 搜索相关文档 search_data self.vector_db.search_document( queryquery, n_resultsself.n_res ) # 打印搜索到的文档内容 (用于调试) print(search_data[documents][0]) # 构建提示词替换模板中的占位符 # 注意这里假设 prompt_template 已在全局定义 prompt prompt_template.replace(__INFO__, \n.join(search_data[documents][0])).replace(__QUERY__, query) # 获取模型回复 response self.get_complete(prompt) # 打印 AI 回复 print(fAI的回复{response}) # --- 主程序入口 --- if __name__ __main__: # 加载 .env 文件中的环境变量 load_dotenv() # 定义 RAG 提示词模板 prompt_template 你是一个问答机器人。 你的任务是根据下述给定的已知信息回答用户问题。 确保你的回复完全依据下述已知信息。不要编造答案。 如果下述已知信息不足以回答用户的问题请直接回复我无法回答您的问题。 已知信息: __INFO__ 用户问 __QUERY__ 请用中文回答用户问题。 # 1. 从 PDF 提取文本 page_data extract_text_from_pdf(财务管理文档.pdf, page_number[0, 1, 2]) # 2. 初始化向量数据库连接器 vector MyVectorDBConnector() # 3. 将提取的文本添加到向量数据库 vector.add_document(page_data) # 4. 初始化 RAG 机器人 rag_bot RAG_bot(vector_dbvector, n_res2) # 5. 进行聊天查询 rag_bot.chat(财务管理权限划分)学AI大模型的正确顺序千万不要搞错了2026年AI风口已来各行各业的AI渗透肉眼可见超多公司要么转型做AI相关产品要么高薪挖AI技术人才机遇直接摆在眼前有往AI方向发展或者本身有后端编程基础的朋友直接冲AI大模型应用开发转岗超合适就算暂时不打算转岗了解大模型、RAG、Prompt、Agent这些热门概念能上手做简单项目也绝对是求职加分王给大家整理了超全最新的AI大模型应用开发学习清单和资料手把手帮你快速入门学习路线:✅大模型基础认知—大模型核心原理、发展历程、主流模型GPT、文心一言等特点解析✅核心技术模块—RAG检索增强生成、Prompt工程实战、Agent智能体开发逻辑✅开发基础能力—Python进阶、API接口调用、大模型开发框架LangChain等实操✅应用场景开发—智能问答系统、企业知识库、AIGC内容生成工具、行业定制化大模型应用✅项目落地流程—需求拆解、技术选型、模型调优、测试上线、运维迭代✅面试求职冲刺—岗位JD解析、简历AI项目包装、高频面试题汇总、模拟面经以上6大模块看似清晰好上手实则每个部分都有扎实的核心内容需要吃透我把大模型的学习全流程已经整理好了抓住AI时代风口轻松解锁职业新可能希望大家都能把握机遇实现薪资/职业跃迁这份完整版的大模型 AI 学习资料已经上传CSDN朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费】

相关文章:

AI应用学习-RAG基础

1.RAG的概念及作用 1.大模型的缺陷 首先要知道RAG是什么,能做什么,他是如何应用的,我们需要先了解一下大模型的缺陷,我们在用一些ai对话工具时,你有时候问一个问题,会发现 1.偶尔他回答的就是胡说八道&a…...

视频智能分析:当多模态AI重新定义内容理解边界

视频智能分析:当多模态AI重新定义内容理解边界 【免费下载链接】video-analyzer Analyze videos using LLMs, Computer Vision and Automatic Speech Recognition 项目地址: https://gitcode.com/gh_mirrors/vi/video-analyzer 想象一下这样的场景&#xff1…...

Quartus II仿真报错:Error 201009总线宽度不匹配?手把手教你排查Verilog模块接口问题

Quartus II总线宽度不匹配错误全解析:从代码设计到工程管理的系统化解决方案 当你在Quartus II中看到"Error 201009: Bus port width mismatch"这样的报错时,这通常意味着你的Verilog设计在模块接口层面出现了不一致。这种错误看似简单&#x…...

Video-Downloader:打破平台壁垒,轻松收藏你喜爱的每一帧视频

Video-Downloader:打破平台壁垒,轻松收藏你喜爱的每一帧视频 【免费下载链接】Video-Downloader 下载youku,letv,sohu,tudou,bilibili,acfun,iqiyi等网站分段视频文件,提供mac&win独立App。 项目地址: https://gitcode.com/gh_mirrors/…...

鸿蒙PC开发的Slider组件blockSize参数的类型要求

踩坑记录06:Slider组件blockSize参数的类型要求 阅读时长:7分钟 | 难度等级:初级 | 适用版本:HarmonyOS NEXT (API 12) 关键词:Slider、blockSize、SizeOptions、原生组件 声明:本文基于真实项目开发经历编…...

传统微波IDU与数字IP微波ODU扩展单元(数字微波IDU)技术对比分析

随着半导体技术的飞速迭代,数字微波通信设备的设计架构实现了从分体式到全室外集成式的跨越式发展,核心组件的功能定位与应用场景也随之发生深刻变革。早期传统数字微波ODU(室外单元)采用IDU(室内单元)与OD…...

地平线首款舱驾融合芯片即将量产;速腾聚创发布创世架构推出双旗舰感知芯片;多项固态电池技术重大突破;蔡司研发全息透明显示技术

地平线首款舱驾融合芯片即将量产牛喀网获悉,地平线发布中国首款舱驾融合整车智能体芯片星空Starry,该芯片采用5nm车规制程,BPU算力达650TOPS,内存带宽273GB/s,集成20核CPU。其采用统一内存架构与城堡安全物理隔离架构&…...

别再只会写required了!Element UI Form表单rules的10个高级玩法(含自定义校验函数)

解锁Element UI表单校验的隐藏能力:10个高阶规则实战指南 在Vue生态中,Element UI凭借其优雅的表单组件成为中后台开发的首选。但大多数开发者仅仅停留在required: true的基础校验层面,实际上其基于async-validator的校验系统蕴藏着令人惊喜的…...

YOLO11涨点优化:Block优化 | 结合FasterNet核心PConv (Partial Convolution),大幅削减浮点运算,FPS直线飙升

一、引言:当FLOPs不再是唯一答案——轻量化部署的困局 计算机视觉领域,目标检测模型正在经历一场从“精度为王”到“效率为王”的深刻转型。根据Ultralytics官方博客介绍,YOLO11通过增强特征提取功能和更高效的架构设计,在实时物体检测、实例分割和姿态估计等多个任务上都…...

创新技术学习:如何快速掌握一个全新的技术领域

创新技术学习:如何快速掌握一个全新的技术领域 在技术飞速发展的今天,掌握新技能已成为职业发展的关键。无论是人工智能、区块链,还是云计算,快速学习新技术的能力决定了个人和企业的竞争力。面对庞杂的知识体系,许多…...

从“主动错误”到“总线关闭”:深入理解CAN节点错误状态机与计数器(TEC/REC)

从“主动错误”到“总线关闭”:深入理解CAN节点错误状态机与计数器(TEC/REC) 在汽车电子和工业控制领域,CAN总线作为经典的现场总线协议,其可靠性直接影响着整个系统的稳定性。当某个CAN节点开始频繁发送错误帧时&…...

手把手教你用Modelsim仿真验证FPGA的PLL输出:从代码到波形图的全流程避坑

FPGA设计中PLL仿真验证全攻略:从Testbench编写到波形分析实战 在FPGA开发中,锁相环(PLL)作为时钟管理的核心组件,其稳定性直接影响整个系统的可靠性。但很多工程师在完成PLL代码编写后,常常面临一个关键问题:如何确认P…...

汽车网络通讯分析与仿真工具的系统工程:Vector CANoe与ZLG ZCANPRO深度剖析

目录 摘要 第一部分:软件架构设计与仿真引擎开发 事件驱动型仿真引擎与实时调度 CAPL 编程语言 ZCANPRO 的软件架构 第二部分:硬件架构与高精度总线接口开发 基于 FPGA 的通讯控制器设计 MCU 架构与工业级稳定性 硬件同步与时间基准 第三部分&…...

Windows 11 窗口美化终极指南:让所有应用焕发 Mica 质感

Windows 11 窗口美化终极指南:让所有应用焕发 Mica 质感 【免费下载链接】MicaForEveryone Mica For Everyone is a tool to enable backdrop effects on the title bars of Win32 apps on Windows 11. 项目地址: https://gitcode.com/gh_mirrors/mi/MicaForEvery…...

零代码RPA神器taskt:如何用免费开源工具实现跨平台自动化革命

零代码RPA神器taskt:如何用免费开源工具实现跨平台自动化革命 【免费下载链接】taskt taskt (pronounced tasked and formely sharpRPA) is free and open-source robotic process automation (rpa) built in C# powered by the .NET Framework 项目地址: https:/…...

从零开始玩转Arduino:开源开发工具带你轻松进入硬件世界

从零开始玩转Arduino:开源开发工具带你轻松进入硬件世界 【免费下载链接】Arduino Arduino IDE 1.x 项目地址: https://gitcode.com/gh_mirrors/ar/Arduino 想象一下,你有一个创意想法,想要让LED灯随着音乐节奏闪烁,或者制…...

WinUtil:3步搞定Windows系统优化的终极解决方案

WinUtil:3步搞定Windows系统优化的终极解决方案 【免费下载链接】winutil Chris Titus Techs Windows Utility - Install Programs, Tweaks, Fixes, and Updates 项目地址: https://gitcode.com/GitHub_Trending/wi/winutil WinUtil是一款功能强大的Windows系…...

DDrawCompat:让经典DirectX游戏在现代Windows系统上重获新生

DDrawCompat:让经典DirectX游戏在现代Windows系统上重获新生 【免费下载链接】DDrawCompat DirectDraw and Direct3D 1-7 compatibility, performance and visual enhancements for Windows Vista, 7, 8, 10 and 11 项目地址: https://gitcode.com/gh_mirrors/dd/…...

运算放大器(二):恒流源电路的设计与负载适应性分析

1. 运算放大器恒流源的基本原理 我第一次接触恒流源电路是在调试LED灯板的时候。当时发现直接用电阻限流,亮度会随着电源电压波动而变化,这才意识到恒流源的重要性。简单来说,恒流源就像个"智能水龙头",不管水管&#x…...

B站评论区身份标签智能识别:从信息过载到精准互动的技术实践

B站评论区身份标签智能识别:从信息过载到精准互动的技术实践 【免费下载链接】bilibili-comment-checker B站评论区自动标注成分,支持动态和关注识别以及手动输入 UID 识别 项目地址: https://gitcode.com/gh_mirrors/bil/bilibili-comment-checker …...

Avalonia v11跨平台实战:从安装到多平台项目部署

1. Avalonia v11初体验:为什么选择这个跨平台UI框架? 第一次接触Avalonia是在去年一个需要同时支持Windows和macOS的项目中。当时尝试过几种跨平台方案,要么性能堪忧,要么开发体验差强人意。直到同事推荐了Avalonia,用…...

5分钟掌握ncmdump:网易云音乐NCM格式一键解密终极指南 [特殊字符]

5分钟掌握ncmdump:网易云音乐NCM格式一键解密终极指南 🎵 【免费下载链接】ncmdump 项目地址: https://gitcode.com/gh_mirrors/ncmd/ncmdump 你是否曾经遇到过这样的烦恼?辛辛苦苦在网易云音乐下载的歌曲,换了个播放器就…...

从B站视频到实操:StaMPS-PSI处理中的那些“坑”与高效调试技巧(基于Gamma和mt_prep_gamma)

从B站视频到实操:StaMPS-PSI处理中的那些“坑”与高效调试技巧 在B站等平台学习StaMPS-PSI处理的过程中,许多初学者会经历从“一看就会”到“一做就废”的典型困境。尼莫大佬等UP主的教程视频虽然详细展示了操作流程,但当用户真正动手复现时&…...

【源码深度】Android 架构设计+组件化+模块化+插件化|面试终章 第29讲

...

告别片上串口不够用:手把手教你用STM8S003F3P6的IO口模拟串口实现双机通信

突破硬件限制:STM8S003F3P6 IO模拟串口实现双机通信实战指南 在嵌入式开发中,STM8S003F3P6因其高性价比成为许多低成本项目的首选。然而这款芯片仅有一个硬件UART接口,当项目需要同时连接多个串口设备时,开发者往往陷入资源不足的…...

保姆级教程:用Termux在安卓手机上装Kali Linux(附VNC桌面配置与常见网络问题解决)

安卓手机零基础部署Kali Linux实战指南:从Termux配置到VNC远程桌面 在移动互联网时代,安全研究人员和开发者常常需要在不同场景下快速搭建渗透测试环境。本文将手把手教你如何在不Root安卓设备的情况下,通过Termux终端模拟器完整部署Kali Lin…...

PTA天梯赛L1-006连续因子:从质数到合数的边界处理,一个易错点差点让我丢分

PTA天梯赛L1-006连续因子:从质数陷阱到边界条件的深度剖析 那天深夜,当我第17次提交L1-006题解时,屏幕上刺眼的"Wrong Answer"让我彻底清醒——60这个看似简单的测试用例,竟然让我的算法输出了错误的234而非正确的345。…...

从 ArrayList 到 LinkedList:深入源码,图解 Java subList 的‘视图’魔法与性能影响

从 ArrayList 到 LinkedList:深入源码,图解 Java subList 的‘视图’魔法与性能影响 当你需要在 Java 中处理列表的部分数据时,subList 方法提供了一种看似简单却暗藏玄机的解决方案。不同于创建一个全新的列表副本,subList 生成的…...

Windows多显示器DPI独立控制:绕过系统限制的底层API实践

Windows多显示器DPI独立控制:绕过系统限制的底层API实践 【免费下载链接】SetDPI 项目地址: https://gitcode.com/gh_mirrors/se/SetDPI 在Windows多显示器工作环境中,不同分辨率的显示器需要独立的DPI缩放设置,但系统界面却将这一功…...

从Modbus到蓝牙:深入浅出图解CRC-16 CCITT的位反序到底在干什么

从Modbus到蓝牙:深入浅出图解CRC-16 CCITT的位反序到底在干什么 当你第一次在Modbus协议文档中看到"CRC-16 CCITT"这个术语时,可能会觉得它只是众多校验算法中的普通一员。但当你真正开始实现它,特别是在处理"位反序"这个…...