写一个简单的RAG问答
AI小白,想通过费曼学习法,加深自己的印象,有不足的希望大家指出
RAG 的概念
RAG(Retrieval-Augmented Generation,检索增强生成)是一种结合信息检索与文本生成的技术,旨在通过动态检索外部知识库来增强生成式模型的输出准确性和相关性。传统生成模型(如GPT)仅依赖预训练参数生成内容,而RAG在生成过程中引入实时检索机制,从外部数据源获取相关信息作为上下文,从而减少“幻觉”错误并提升事实性。
简单的来说就是:用户发送问题到Embedding模型后,Embedding模型会把问题转换成向量,然后在向量数据库中查询,最匹配的返回给用户。
准备工作![]()
Miniconda 安装与配置(轻量级的python环境管理工具)
Miniconda 是一个轻量级的 Conda 发行版,用于管理包和环境。它仅包含 Conda、Python 及其依赖项,用户可按需安装其他工具或库,适合需要灵活控制环境的场景。
Miniconda - Anaconda
确保 Miniconda 已正确安装并配置环境变量。可通过以下命令验证是否安装成功:
conda --version创建一个独立的 Python 环境(例如名为rag_env)并激活:
conda create -n rag_env python=3.9 conda activate rag_envVSCode 环境配置
- 安装 VSCode 的 Python 插件(如官方 Python 扩展)。
- 手动告诉 VS Code 你的 Python 在哪:
- 按下键盘快捷键
Ctrl + Shift + P(打开命令面板)。 - 在输入框里输入:
Python: Select Interpreter(或者中文的“Python: 选择解释器”),然后回车。 - 此时列表里应该会出现带有
conda字样的选项(例如Python 3.x.x ('base': conda))。 - 选中那个带 conda 的选项。
- 按下键盘快捷键
选好后,VS Code 左下角的状态栏就会显示 Python 的版本号,这就说明连接成功了,不需要再下载任何东西。
vsCode终端输入命令:
python -m pip install langchain openai pandas
该命令用于通过 Python 的包管理工具pip安装三个库:langchain、openai和pandas。以下是每个库的功能和用途:
安装的
langchain
LangChain:用于构建大语言模型应用的框架。openai
用于调用 OpenAI API(如 GPT 系列模型)。pandas
用于数据处理和分析的“瑞士军刀”。
其中,LangChain 确实具备将长文本进行 Chunk(分块)的功能,这是 RAG 应用开发中的关键一步。简单来说,LangChain 不仅能帮你把长文切成小块,还能通过智能策略和重叠机制,确保切出来的每一块都“表意一致”,从而让大模型在检索时能更精准地找到相关信息。
ChromaDB 向量数据库安装(它完全免费、无需 API Key、零配置,非常适合新手入门)
- 传统数据库(如 MySQL):擅长精确匹配。你查“订单号 12345”,它能瞬间找到。但如果你问“帮我找去年买过的蓝色运动鞋”,除非商品描述里恰好有这几个字,否则它无法理解“耐克跑鞋”和“运动鞋”是一回事。
- 向量数据库:专为“相似性搜索”而生。它能在数百万甚至数十亿个向量中,毫秒级快速找到最相似的数据点。
在vsCode中安装 Chroma :
pip install langchain-chroma文本切块(Chunking)是 RAG 流程中至关重要的一步,它决定了你的向量数据库检索效果的好坏。如果切得太碎,语义会丢失;如果切得太大,检索到的上下文会包含太多无关信息,干扰大模型回答。LangChain-text-splitters(文本分割器)的核心作用就是:把长长的文本,按照一定的逻辑和规则,切成一块一块适合AI处理的小碎片。
推荐使用 LangChain 提供的RecursiveCharacterTextSplitter(递归字符文本分割器),这是目前最通用、最稳妥的切分策略。它会优先按段落换行符切分,切不动再按句子切分,最后才按字符硬切,能最大程度保留语义完整性。
pip install -U langchain-text-splitters下载:sentence-transformers和 LangChain 的 HuggingFace 集成包
pip install sentence-transformers langchain-community pip install langchain-huggingface把切好的文本变成向量(也就是 Embedding)
langchain-community它不是“调用模型的工具”,而是“让 LangChain 能调用各种模型的桥梁”。没有它,你的代码就无法识别ChatZhipuAI这样的类。
pip install sentence-transformers langchain-communitysentence-transformers负责将文本转换为向量(嵌入,Embeddings)
langchain-text-splitters负责切文本
langchain-community提供的接口,调用底层的嵌入模型(可以是sentence-transformers这类本地模型,也可以是云端大模型),将切好的文本块转化为向量,并存入向量数据库。
安装了调用模型的代码库。真正的 BGE 模型文件(通常几百 MB 到几 GB)会在你第一次运行代码时自动触发下载。
由于 Hugging Face 的服务器在国外,国内直接下载可能会很慢或超时。你可以设置环境变量使用国内镜像源加速:
在终端运行以下命令后再执行 Python 脚本:
set HF_ENDPOINT=https://hf-mirror.com或者在 Python 代码最开头加上:
import os os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'这样就能通过国内镜像高速下载了。快去运行那段代码吧,看到“成功!”两个字,下载 BGE 模型文件,且这个模型是免费的,不需要 API Key
安装Chroma
Chroma 是一个开源的向量数据库,专注于存储和检索高维向量数据。它被设计用于支持机器学习、自然语言处理(NLP)和人工智能应用,尤其是在需要快速搜索和匹配向量数据的场景中。
pip install langchain-chroma简单的来说就是:用sentence-transformers+BGE模型将文本“翻译”成向量,然后将生成的向量“存储”到Chroma数据库
RAG 基础代码结构
创建一个简单的 RAG 示例文件(如rag_demo.py),包含以下模块:
import os from langchain_community.document_loaders import TextLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_huggingface import HuggingFaceEmbeddings from langchain_community.vectorstores import Chroma # 【新增】导入 LLM 和 QA 链 # 这里以智谱AI为例,因为它对中文支持好且容易申请Key # 如果你想用 OpenAI,请换成 ChatOpenAI from langchain_community.chat_models import ChatZhipuAI from langchain_classic.chains import RetrievalQA # ================= 第一步:准备数据 ================= print(">>> 正在加载文档...") loader = TextLoader("./knowledge.txt", encoding="utf-8") documents = loader.load() print(">>> 正在切分文本...") text_splitter = RecursiveCharacterTextSplitter(chunk_size=500, chunk_overlap=50) chunks = text_splitter.split_documents(documents) print(f"切分完成,共得到 {len(chunks)} 个文本块。") # ================= 第二步:初始化 Embedding 模型 (BGE) ================= print(">>> 正在初始化 Embedding 模型 (BGE)...") # 使用 BAAI/bge-large-zh-v1.5,第一次运行会自动下载 embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-large-zh-v1.5") # ================= 第三步:存入 Chroma 数据库 ================= print(">>> 正在进行向量化并存入 Chroma 数据库...") vectorstore = Chroma.from_documents( documents=chunks, embedding=embeddings, persist_directory="./chroma_db" ) print(">>> 存入成功!") # ================= 第四步:构建问答系统 (关键步骤) ================= print("\n========================================") print(" RAG 智能问答系统已启动") print(" 输入 'exit' 退出程序") print("========================================\n") # 1. 配置大模型 (LLM) # 如果你有 ZhipuAI 的 Key,请在这里填入,或者设置环境变量 # 如果没有 Key,你可以尝试使用 Ollama 运行本地模型 (见下方注释) zhipu_api_key = "xxx" # <--- 请替换为你的 API Key llm = ChatZhipuAI( temperature=0.1, # 温度越低,回答越严谨 api_key=zhipu_api_key, model="glm-4-flash" # 使用轻量级模型,速度快 ) # 2. 创建检索问答链 qa_chain = RetrievalQA.from_chain_type( llm=llm, retriever=vectorstore.as_retriever(search_kwargs={"k": 3}), # k=3 表示每次找最相关的3段话 return_source_documents=True # 允许查看引用来源 ) # ================= 第五步:开始对话循环 ================= while True: query = input("请输入你的问题: ") if query.lower() == 'exit': print("再见!") break if not query.strip(): continue print("正在思考中...\n") try: # 调用链条获取回答 result = qa_chain.invoke({"query": query}) # 打印最终回答 print(f"【AI 回答】: {result['result']}\n") # (可选) 打印参考了哪些原文片段 # print("--- 参考依据 ---") # for i, doc in enumerate(result["source_documents"]): # print(f"[片段 {i+1}]: ...{doc.page_content[:60]}...") # print("----------------\n") except Exception as e: print(f"出错了: {e}") print("提示: 可能是 API Key 无效或网络连接问题。")依赖项整理
生成 knowledge.txt文件:
pip freeze > requirements.txt【童话档案】《发条夜莺与玻璃玫瑰》 在遥远的北方,有一座被冰雪终年环绕的城堡,名叫“霜语堡”。城堡里住着一位名叫艾莉亚的小公主。艾莉亚公主有一头像月光般银白的头发,但她却很少笑,因为她的父王是一位极其严厉的国王,他下令禁止城堡里有任何音乐和鲜花。 在城堡最阴暗的阁楼里,住着一位名叫巴纳比的老钟表匠。巴纳比的眼睛已经花了,手指也布满老茧,但他有一双能听懂机械心跳的耳朵。他偷偷收集了国王废弃的怀表零件、黄铜齿轮和银丝,在无数个寂静的深夜里,敲打出了一只精巧的发条夜莺。这只夜莺的羽毛是纯银打造的,只要转动它背后的红宝石发条,它就会唱出比真正的夜莺还要婉转的歌声,歌声里带着齿轮咬合的清脆回音。 除了发条夜莺,巴纳比还用从冰湖里打捞上来的水晶碎片,吹制了一朵永不凋零的玻璃玫瑰。这朵玫瑰的花瓣薄如蝉翼,在月光下会折射出七彩的光芒。巴纳比把这两件宝物藏在一个铺着天鹅绒的旧木盒里,那是他留给这个冰冷世界唯一的温柔。 一个风雪交加的夜晚,艾莉亚公主为了躲避父王的责骂,悄悄溜进了阁楼。她发现了那个旧木盒,当她转动发条夜莺背后的红宝石时,清脆的歌声瞬间填满了整个阁楼。公主激动地流下了眼泪,她拿起那朵玻璃玫瑰,却发现玫瑰的刺不小心划破了她的手指。一滴鲜血落在了玻璃花瓣上,奇迹发生了——玻璃玫瑰竟然散发出了温暖的红光,像一颗跳动的心脏。 就在这时,国王带着卫兵踹开了阁楼的门。他看到老钟表匠和公主在一起,勃然大怒,下令要将巴纳比流放,并砸碎那只发条夜莺。就在卫兵举起铁锤的瞬间,艾莉亚公主挡在了老钟表匠面前。她高高举起那朵吸收了鲜血的玻璃玫瑰,大声宣告:“如果这朵玫瑰代表的是爱与创造,那么它就是城堡里最珍贵的宝物!” 奇迹再次发生,玻璃玫瑰的光芒照亮了整个阁楼,连国王手中的宝剑也融化成了水滴。国王看着女儿坚定的眼神,终于低下了高傲的头。从那以后,霜语堡里再也没有禁令。老钟表匠巴纳比成了城堡的皇家工匠,而艾莉亚公主的银发上,永远别着那朵散发着微光的玻璃玫瑰。 【附录:霜语堡物品清单】 1. 发条夜莺:纯银打造,动力源为红宝石发条,声音带有齿轮回音。 2. 玻璃玫瑰:由冰湖水晶碎片吹制,被公主的鲜血激活后散发红光。 3. 旧木盒:用来装宝物的容器,内衬为天鹅绒。 4. 铁锤:卫兵原本用来砸碎夜莺的工具。总结一下就是:
环境准备 (步骤 1-3)
- 图示内容:Miniconda -> Python -> VS Code。
- 实际情况:这是所有 Python 开发的标准起手式。Miniconda 负责管理环境隔离(防止包冲突),VS Code 负责写代码。
核心框架与模型下载 (步骤 4)
- 图示内容:安装 LangChain + Hugging Face 下载 BGE 模型。
- 实际情况:安装了
langchain系列库,并且通过 HuggingFace 的接口加载了BAAI/bge-large-zh-v1.5这个 Embedding 模型(用来把文字变成向量)。
数据处理流水线 (步骤 5-7) ——这是最关键的部分
- 步骤 5 (Text Splitters):代码里用了
RecursiveCharacterTextSplitter,把长文章切成了小块(Chunk)。 - 步骤 6 (Vectorization):虽然图中写的是
langchain-community做转换,但实际上是HuggingFaceEmbeddings在工作,它把文本变成了[0.11, 0.23...]这样的数字数组。 - 步骤 7 (ChromaDB):使用了
Chroma.from_documents,把这些带向量的数据存进了本地数据库。
- 步骤 5 (Text Splitters):代码里用了
