news 2026/5/4 13:42:41

LLM AI大模型 -- RAG

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
LLM AI大模型 -- RAG

RAG

  • jupyter lab的搭建使用
  • RAG系统的基本搭建流程
    • 文档的加载与切割
    • LLM接口封装
    • Prompt模板
  • 向量检索
    • 什么是向量
      • 文本向量
      • 文本向量怎么得到的
    • 向量间的相似度计算
    • 嵌入模型的选择
  • 向量数据库
    • Chroma向量数据库
    • Chroma向量数据库服务
      • 主流向量数据库功能对比
    • 基于向量检索的RAG
  • RAG系统进阶知识
    • 文本分割的粒度

国内模型库: https://www.modelscope.cn

jupyter lab的搭建使用

首先需要创建一个conda环境 进到环境中再执行 不能再base环境下

pip install jupyterlab

切换到想要保存的磁盘

cd F:\LLM


使用以下命令启动jupyterlab:

jupyter lab

RAG系统的基本搭建流程

搭建过程:

  1. 文档加载,并按一定条件切割成片段
  2. 将切割的文本片段灌入检索引擎
  3. 封装检索接口
  4. 构建调用流程:Query->检索->Prompt->LLM->回复

文档的加载与切割

安装下边的两个库

!pip install--upgrade openai# 安装 pdf 解析库!pip install pdfminer.six
frompdfminer.high levelimportextract_pagesfrompdfminer.layoutimportLTTextContainer
defextract_text_from_pdf(filename,page_numbers=None,min_line_length=1):'''从 PDF 文件中(按指定页码)提取文字'''paragraphs=[]buffer=""full_text=""# 提取全部文本fori,page_layoutinenumerate(extract_pages(filename)):# 如果指定了页码范围,跳过范围外的页ifpage_numbersisnotNoneandinotinpage_numbers:continueforelementinpage_layout:ifisinstance(element,LTTextContainer):full_text+=element.get_text()+"\n"# 按空行分隔,将文本重新组织成段落Lines=full_text.split("\n")fortextinlines:iflen(text)>=min_line_length:buffer+=(""+text)ifnottext.endswith("")elsetext.strip("-")elifbuffer:paragraphs.append(buffer)buffer=""ifbuffer:paragraphs.append(buffer)returnparagraphs paragraphs=extract_text_from_pdf("llama2.pdf",min_line_length=10)forparainparagraphs[:4]:print(para+"\n")

LLM接口封装

pip install-U python-dotenv
fromopenaiimportOpenAIimportos#加载环境变量fromdotenvimportload_dotenv,find_dotenv _=load_dotenv(find_dotenv(),verbose=True)client=OpenAI()#封装openai接口defget_completion(prompt,model="gpt-3.5-turbo",temperature=0.7,max_tokens=150,top_p=1.0,frequency_penalty=0.0,presence_penalty=0.0,stop=["\n"]):messages=[{"role":"user","content":prompt}]response=client.chat.completions.create(messages=messages,model=model,temperature=temperature,#模型输出的随机性max_tokens=max_tokens,top_p=top_p,frequency_penalty=frequency_penalty,presence_penalty=presence_penalty,stop=stop)returnresponse.choices[0].message.content

Prompt模板

#创建提示词模板defbuild_prompt(prompt_template,**kwargs):inputs={}fork,vinkwargs.items():ifisinstance(v,list)andall(isinstance(i,str)foriinv):val='\n\n'.join(v)else:val=v inputs[k]=valreturnprompt_template.format(**inputs)

prompt_template = “”
你是一个问答机器人。你的任务是根据下述给定的己知信息回答用户问题
已知信息: 从向量数据库检索出来的原始文档
{context}
用户问:
{query}
如果已知信息不包含用户问题的答案,或者已知信息不足以回答用户的问题,请直接回复"我无法回答您的问题"请不要输出已知信息中不包含的信息或答案。请用中文回答用户问题。

向量检索

什么是向量

向量是一种有大小和方向的数学对象。它可以表示为从一个点到另一个点的有向线段。例如:二维空间中的向量可以表示为(x,y),表示从原点(0,0)到点(x,y)的有向线段。

以此类推,我可以用一组坐标(x0,x1,x2…xn)表示一个 N 维空间中的向量,N 叫向量的维度

文本向量

将文本转成一组N维浮点数,即文本向量又叫Embeddings
向量之间可以计算距离,距离远近对应语义相似度大小

文本向量怎么得到的

1.构建相关(正例)与不相关(负例)的句子对样本
2.训练双塔式模型,让正例间的距离小,负例间的距离大

向量间的相似度计算

importnumpyasnpfromnumpyimportdotfromnumpy.linalgimportnorm
defcos_sim(a,b):#余弦距离 越大越相似'''余弦距离 越大越相似'''returndot(a,b)/(norm(a)*norm(b))defl2(a,b):'''欧式距离 越小越相似'''x=np.asarray(a)-np.asarray(b)returnnorm(x)defget_embeddings(texts,model="text-embedding-ada-002",dimensions=None):'''封装openai的Embedding模型接口'''ifmodel=="text-embedding-ada-002":dimensions=Noneifdimensions:data=client.embeddings.create(input=texts,model=model,dimensions=dimensions).dataelse:data=client.embeddings.create(input=texts,model=model).datareturn[x.embeddingforxindata]
test_query=["测试文本"]vec=get_embeddings(test_query)[0]print(f"Total dimensions:{len(vec)}")print(f"First 10 dimensions:{vec[:10]}")

嵌入模型的选择

  • 标准:找需求相关的语料库来进行文本向量的转换测试,进行评估
    维度越大,标识特征细节提取越丰富

大多数场景下,开源的嵌入模型使用体验都很差
要提升检索召回率,建议对模型进行微调

向量数据库

向量数据库,是专门为向量检索设计的中间件!
向量数据库其实最早在传统的人工智能和机器学习场景中就有所应用。在大模型兴起后,由于目前大模型的token数限制,很多开发者倾向于将数据量庞大的知识、新闻、文献、语料等先通过嵌入(embedding)算法转变为向量数据,然后存储在Chroma等向量数据库中。当用户在大模型、输入问题后,将问题本身也embedding,转化为向量,在向量数据库中査找与之最匹配的相关知识,组成大模型的上下文,将其输入给大模型,最终返回模型处理后的文本给用户,这种方式不仅降低大模型的计算量,提高响应速度,也降低成本,并避免了大模型的tokens限制,是一种简单高效的处理手段。此外向量数据库还在大模型记忆存储等领域发挥其不可替代的作用。

Chroma向量数据库

官方文档:https://docs.trychroma.com/docs/overview/introduction

安装数据库

pip install chromadb
#为了演示方便 取两页paragraphs=extract_text_from_pdf("llama2.pdf",page_numbers=[2,3],min_line_length=10)
importchromadbfromchromadb.configimportSettingsclassMyVectorDBConnector:def__init__(self,collection_name,embedding_fn):#内存模式 实际不能这么用 只能自己玩用 否则服务器一出问题 全丢chroma_client=chromadb.Client(Settings(allow_reset=True))#数据持久化#chroma_client = chromadb.PersistentClient(path="./chroma")#注意:为了演示,实际不需要每次都reset() 不可逆chroma_client.reset()# reset重置数据库 慎用self.collection=chroma_client.get_or_create_collection(name=collection_name)self.embedding_fn=embedding_fndefadd_documents(self,documents):# 向collection中添加文档与向量self.collection.add(embeddings=self.embedding_fn(documents),#每个文档的向量documents=documents#文档的原文ids=[f"id{i}"foriinrange(len(documents))]#每个文档的 id)defsearch(self,query,top_k=10):# 检索向量数据库results=self.collection.query(query_embedding=self.embedding_fn([query]),n_results=top_n)returnresults
#创建一个向量数据库对象vector_db=MyVectorDBConnector(collection_name="llama2",embedding_fn=get_embeddings)#向向量数据库中添加文档vector_db.add_documents(paragraphs)user_query="Llama 2有多少参数"#user_query = "Does Llama 2 have a conversational variant?"results=vector_db.search(user_query,2)forparainresults['documents'][0]:print(para+"\n")

澄清几个关键概念:

  • 向量数据库的意义是快速的检索;
  • 向量数据库本身不生成向量,向量是由 Embedding 模型产生的:
  • 向量数据库与传统的关系型数据库是互补的,不是替代关系,在实际应用中根据实际需求经常同时使用。

Chroma向量数据库服务

Server 端

chroma run--path/db_path

Client 端

importchromadb chromadb_client=chromadb.HttpClient(host='localhost',port=8000)

主流向量数据库功能对比

  • FAISS: Meta 开源的向量检索引擎 https://github已添加到剪贴板research/faiss。
  • Pinecone:商用向量数据库,只有云服务 https:/www.pinecone.io/
  • Milvus: 开源向量数据库,同时有云服务 https://milvus.io/
  • Weaviate:开源向量数据库,同时有云服务 https://weaviate.io/
  • Qdrant: 开源向量数据库,同时有云服务 https://qdrant.tech/
  • PGVector: Postgres 的开源向量检索引擎 https://github.com/pgvector/pgvector
  • RediSearch: Redis 的开源向量检索引擎 https://qithub.com/RediSearch/Redisearch
  • ElasticSearch 也支持向量检索 https://www.elastic.co/enterprise-search/vector-search
    企业推荐标示的向量数据库

基于向量检索的RAG

classRAG_Bot:def__init__(self,vector_db,llm_api,n_results=2):self.vector_db=vector_db self.llm_api=llm_api self.n_results=n_resultsdefchat(self,user_query):# 检索search_results=self.vector_db.search(user_query,self.n_results)# 构建 Promptprompt=build_prompt(prompt_template,search_results=search_results['documents'][0],query=user_query)#调用LLMresponse=self.llm_api(prompt)returnresponse
#创建一个RAG机器人bot=RAG_Bot(vector_db,llm_api=get_completion)user_query="Llama 2有多少参数?"response=bot.chat(user_query)print(response)

RAG系统进阶知识

文本分割的粒度

缺陷

  • 粒度太大可能导致检索不精准,粒度太小可能导致信息不全面
  • 问题的答案可能跨越两个片段
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/4/30 1:39:24

12、Linux 网络数据包过滤与流量控制:eBPF 实战指南

Linux 网络数据包过滤与流量控制:eBPF 实战指南 1. 网络数据包过滤 1.1 编写自定义代码过滤数据包 除了分析 tcpdump 生成的汇编代码,我们还可以编写自己的代码来过滤网络数据包。不过,调试代码执行以确保其符合预期是一大挑战。在 Linux 内核源代码树的 tools/bpf 目…

作者头像 李华
网站建设 2026/4/29 10:02:30

HunyuanVideo-Foley与MoFos内容平台结合?探讨合法应用场景边界

HunyuanVideo-Foley与内容平台的融合:智能音效的边界与可能 在短视频日均产量突破千万条的今天,一个看似微小却影响深远的问题浮出水面:为什么那么多视频听起来“干巴巴”的? 答案并不复杂——音效制作太贵、太慢、太专业。传统…

作者头像 李华
网站建设 2026/5/2 12:30:05

小白前端必看:5种CSS图片垂直居中方案(附实战技巧+避坑指南)

小白前端必看:5种CSS图片垂直居中方案(附实战技巧避坑指南)小白前端必看:5种CSS图片垂直居中方案(附实战技巧避坑指南)引言:一张图如何逼疯一群前端先搞清楚:浏览器到底怎么算“居中…

作者头像 李华
网站建设 2026/5/3 19:26:05

DOCX.js前端Word文档生成完整指南:零服务器依赖的终极解决方案

DOCX.js前端Word文档生成完整指南:零服务器依赖的终极解决方案 【免费下载链接】DOCX.js Generate Microsoft Word DOCX files in pure client-side JavaScript. Try in Chrome 项目地址: https://gitcode.com/gh_mirrors/do/DOCX.js 在当今数据驱动的时代&a…

作者头像 李华
网站建设 2026/4/25 19:41:55

wiliwili跨平台B站客户端终极使用指南:从入门到精通

wiliwili作为专为手柄控制设计的第三方跨平台B站客户端,目前可以运行在PC全平台、PSVita、PS4和Nintendo Switch上。这款开源应用以其独特的操作体验和全面的功能支持,为用户带来了全新的B站观看方式。无论您是游戏设备爱好者还是PC用户,本指…

作者头像 李华
网站建设 2026/4/30 4:54:00

高效会议管理:3步告别冗长低效,拯救你的会议时间

高效会议管理:3步告别冗长低效,拯救你的会议时间行业痛点分析当前,会议服务领域正面临着一系列深刻的技术与管理挑战。随着混合办公模式的普及与会议复杂度的提升,传统会议模式在效率、协同及成果转化方面的短板日益凸显。首要痛点…

作者头像 李华