AI小白想通过费曼学习法加深自己的印象有不足的希望大家指出RAG 的概念RAGRetrieval-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 python3.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。以下是每个库的功能和用途安装的langchainLangChain用于构建大语言模型应用的框架。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把切好的文本变成向量也就是 Embeddinglangchain-community它不是“调用模型的工具”而是“让 LangChain 能调用各种模型的桥梁”。没有它你的代码就无法识别ChatZhipuAI这样的类。pip install sentence-transformers langchain-communitysentence-transformers负责将文本转换为向量嵌入Embeddingslangchain-text-splitters负责切文本langchain-community提供的接口调用底层的嵌入模型可以是sentence-transformers这类本地模型也可以是云端大模型将切好的文本块转化为向量并存入向量数据库。安装了调用模型的代码库。真正的 BGE 模型文件通常几百 MB 到几 GB会在你第一次运行代码时自动触发下载。由于 Hugging Face 的服务器在国外国内直接下载可能会很慢或超时。你可以设置环境变量使用国内镜像源加速在终端运行以下命令后再执行 Python 脚本set HF_ENDPOINThttps://hf-mirror.com或者在 Python 代码最开头加上import os os.environ[HF_ENDPOINT] https://hf-mirror.com这样就能通过国内镜像高速下载了。快去运行那段代码吧看到“成功”两个字下载 BGE 模型文件且这个模型是免费的不需要 API Key安装ChromaChroma 是一个开源的向量数据库专注于存储和检索高维向量数据。它被设计用于支持机器学习、自然语言处理NLP和人工智能应用尤其是在需要快速搜索和匹配向量数据的场景中。pip install langchain-chroma简单的来说就是用sentence-transformersBGE模型将文本“翻译”成向量然后将生成的向量“存储”到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, encodingutf-8) documents loader.load() print( 正在切分文本...) text_splitter RecursiveCharacterTextSplitter(chunk_size500, chunk_overlap50) chunks text_splitter.split_documents(documents) print(f切分完成共得到 {len(chunks)} 个文本块。) # 第二步初始化 Embedding 模型 (BGE) print( 正在初始化 Embedding 模型 (BGE)...) # 使用 BAAI/bge-large-zh-v1.5第一次运行会自动下载 embeddings HuggingFaceEmbeddings(model_nameBAAI/bge-large-zh-v1.5) # 第三步存入 Chroma 数据库 print( 正在进行向量化并存入 Chroma 数据库...) vectorstore Chroma.from_documents( documentschunks, embeddingembeddings, 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( temperature0.1, # 温度越低回答越严谨 api_keyzhipu_api_key, modelglm-4-flash # 使用轻量级模型速度快 ) # 2. 创建检索问答链 qa_chain RetrievalQA.from_chain_type( llmllm, retrievervectorstore.as_retriever(search_kwargs{k: 3}), # k3 表示每次找最相关的3段话 return_source_documentsTrue # 允许查看引用来源 ) # 第五步开始对话循环 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[片段 {i1}]: ...{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把这些带向量的数据存进了本地数据库。