在 generative-ai-for-beginners 中构建 RAG:检索增强生成与向量数据库实战指南 在 generative-ai-for-beginners 中构建 RAG检索增强生成与向量数据库实战指南【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners本指南以 generative-ai-for-beginners 课程第 15 课的 RAG 与向量数据库章节为主体结合仓库内完整的 Jupyter Notebook 实现与示例数据讲解如何将自有数据个人笔记、课程讲义接入 LLM构建一个能回答领域问题的 RAG 聊天机器人。读完本文你将掌握 RAG 的工作原理、向量数据库与嵌入embedding的概念、本地搜索索引与相似度检索的实现以及如何用 Azure OpenAI、Azure AI Search、Azure Cosmos DB 搭建并评估一套完整的检索增强生成应用。一、RAG 是什么为什么需要它一个由 LLM 驱动的聊天机器人会处理用户提示并生成回复它被设计成交互式的可以围绕大量主题与用户对话。然而它的回复被严格限制在提供的上下文和基础训练数据范围内。例如 GPT-4 的知识截止日期是 2021 年 9 月这意味着它对该日期之后发生的事件一无所知此外用于训练 LLM 的数据不包含机密信息比如个人笔记或公司的产品手册。RAGRetrieval Augmented Generation检索增强生成正是为解决这一限制而生它把检索从你自己的知识库中找到相关内容与生成LLM 基于检索内容作答两个步骤组合起来让模型回答不再只依赖训练时的静态知识。RAG 的工作流程RAG 的完整链路可以拆解为四个环节知识库Knowledge base在检索发生之前文档需要被摄取并预处理通常把大文档切分成小块chunk转换成文本嵌入text embedding再存储到数据库中。用户查询User query用户提出问题。检索Retrieval当用户提问时嵌入模型embedding model从知识库中检索相关信息为提示词补充更多上下文。增强生成Augmented generationLLM 基于检索到的数据增强其回答让回复不只建立在预训练数据上还包含新增的相关上下文最后把答案返回给用户。RAG 的架构基于 transformer 模型实现包含两部分编码器encoder和解码器decoder。当用户提问时输入文本被编码为捕获词语含义的向量这些向量被解码进我们的文档索引并基于用户查询生成新文本。LLM 正是使用编码器-解码器模型来产生输出的。依据论文《Retrieval-Augmented Generation for Knowledge intensive NLP Tasks》实现 RAG 有两种主流方案RAG-Sequence使用检索到的文档来预测用户查询的最佳答案RAG-Token使用文档生成下一个 token再重新检索以回答用户查询。为什么使用 RAG信息丰富度确保文本回复是即时、最新的通过访问内部知识库提升领域特定任务的性能减少虚构fabrication利用知识库中可验证的数据为用户查询提供上下文降低模型编造答案的概率成本效益相比微调fine-tuning一个 LLMRAG 更加经济。二、课程场景用自有数据增强 LLM第 15 课的场景设定在一个教育创业公司中我们想把自己的笔记加入聊天机器人让它对各个学科拥有更多信息学生可以借助这些笔记更好地学习、理解不同主题并为考试复习做准备。构建该场景需要以下组件Azure OpenAI用于创建聊天机器人的 LLMAI for Beginners 的神经网络课程笔记作为给 LLM 接地grounding的数据Azure AI Search 与 Azure Cosmos DB向量数据库用于存储数据并创建搜索索引。用户可以基于笔记创建练习测验practice quizzes、复习闪卡revision flash cards并把内容总结成简洁的概述。对应上述场景的完整代码在仓库的 notebook-rag-vector-databases.ipynb 中示例数据位于 data/ 目录下包含三篇文档frameworks.md神经网络框架own_framework.md多层感知机与自建框架perceptron.md感知机模型与训练。三、创建知识库向量数据库与文本嵌入向量数据库与传统数据库不同向量数据库是专门用来存储、管理和搜索嵌入向量的特殊数据库。它存储的是文档的数值表示。把数据拆解为数值嵌入可以让 AI 系统更容易理解和处理数据。之所以要把嵌入存储在向量数据库中是因为LLM 对输入的 token 数量有上限。我们无法把全部嵌入一次性传给 LLM因此需要把它们切分成块当用户提问时只把与问题最相似的嵌入连同提示词一起返回。分块还能降低 LLM 传递的 token 数量从而降低成本。常见的向量数据库包括Azure Cosmos DB、Clarifyai、Pinecone、Chromadb、ScaNN、Qdrant 和 DeepLake。使用 Azure CLI 可以这样创建 Azure Cosmos DBaz login az group create -n resource-group-name -l location az cosmosdb create -n cosmos-db-name -r resource-group-name az cosmosdb list-keys -n cosmos-db-name -g resource-group-name创建完成后可以在数据资源管理器中新建数据库和容器。Notebook 中对应使用azure-cosmosPython SDK 初始化客户端见 notebook-rag-vector-databases.ipynb 中CosmosClient(url, credentialkey)的用法并通过环境变量COSMOS_DB_ENDPOINT、COSMOS_DB_KEY读取连接信息数据库名rag-cosmos-db、容器名data。从文本到嵌入分块策略在存储数据之前需要先把它转换为向量嵌入。如果处理的是大文档或长文本可以按预期的查询方式分块。分块可以在句子级别或段落级别进行。由于块的含义来自其周围的词我们可以为块补充额外上下文比如加上文档标题或在块前后包含部分文本。def split_text(text, max_length, min_length): words text.split() chunks [] current_chunk [] for word in words: current_chunk.append(word) if len( .join(current_chunk)) max_length and len( .join(current_chunk)) min_length: chunks.append( .join(current_chunk)) current_chunk [] # 如果最后一个块未达到最小长度仍然加入 if current_chunk: chunks.append( .join(current_chunk)) return chunks在 Notebook 中实际调用为split_text(x, 400, 300)即每个块控制在 300~400 字符之间然后用splitted_df.explode(chunks)把每行的块列表展开成独立行形成后续用于检索的flattened_df列包含path、text、chunks后续还会追加embeddings、indices、distances列。分块完成后可以用不同的嵌入模型把文本转换为嵌入例如 word2vec、OpenAI 的 ada-002、Azure Computer Vision 等。选择模型取决于使用的语言、编码内容的类型文本/图像/音频、可编码的输入大小以及嵌入输出的长度。下图展示了使用 OpenAItext-embedding-ada-002模型对单词 cat 生成的嵌入示例Notebook 中的实现封装了嵌入函数见 notebook-rag-vector-databases.ipynbfrom openai import OpenAI endpoint os.getenv(AZURE_OPENAI_ENDPOINT) client OpenAI( api_keyos.getenv(AZURE_OPENAI_API_KEY), base_urlf{endpoint.rstrip(/)}/openai/v1/, ) embeddings_deployment os.getenv(AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT) chat_deployment os.getenv(AZURE_OPENAI_DEPLOYMENT) def create_embeddings(text, modelNone): # 使用你的 embeddings 部署为每个文档块创建嵌入 model model or embeddings_deployment embeddings client.embeddings.create(inputtext, modelmodel).data[0].embedding return embeddings然后对flattened_df中所有块批量生成嵌入并写回数据框embeddings [] for chunk in flattened_df[chunks]: embeddings.append(create_embeddings(chunk)) flattened_df[embeddings] embeddings四、检索与向量搜索当用户提问时检索器retriever使用查询编码器把问题转换为向量然后在文档搜索索引中查找与输入相关的向量完成后把输入向量与文档向量转换回文本一并传给 LLM。检索的三种方式检索发生在系统从索引中快速找出满足搜索条件的文档时。检索器的目标是把用于提供上下文、让 LLM 接地到数据的文档找出来。数据库内的搜索方式有关键词搜索Keyword search用于文本搜索向量搜索Vector search使用嵌入模型把文档从文本转换为向量表示支持基于词语含义的语义搜索semantic search检索时查询与用户问题向量表示最接近的文档混合搜索Hybrid关键词与向量搜索的组合。检索的挑战在于当数据库中没有与查询相似的答案时系统只能返回它能拿到的最佳信息。对此可以采取策略例如设置相关性的最大距离阈值或使用同时包含关键词与向量搜索的混合搜索。本课采用混合搜索思路数据存储在 DataFrame 中列包含分块与嵌入。向量相似度度量检索器会在知识库中寻找彼此接近的嵌入最近的邻居因为它们是语义相似的文本。用户查询先被嵌入再与相似的嵌入匹配。衡量向量相似度最常用的指标是余弦相似度cosine similarity它基于两个向量之间的夹角。其他备选方案还有欧几里得距离Euclidean distance两个向量端点之间的直线距离点积dot product两个向量对应元素乘积之和。用 NearestNeighbors 构建本地搜索索引执行检索前需要为知识库构建搜索索引。索引存储嵌入即使数据库很大也能快速返回最相似的块。本地可以用 sklearn 构建from sklearn.neighbors import NearestNeighbors embeddings flattened_df[embeddings].to_list() # 创建搜索索引 nbrs NearestNeighbors(n_neighbors5, algorithmball_tree).fit(embeddings) # 查询索引可使用 kneighbors 方法 distances, indices nbrs.kneighbors(embeddings)Notebook 中还会把indices与distances写回 DataFrameflattened_df[indices] indices.tolist()、flattened_df[distances] distances.tolist()便于后续展示与调试。重排序Re-ranking查询完数据库后可能需要按相关性对结果排序。重排序 LLM 利用机器学习改进搜索结果的相关性把最相关的结果排在最前。使用 Azure AI Search 时语义重排序器会自动完成重排序。下面是一个基于最近邻的重排序示例# 找出最相似的文档 distances, indices nbrs.kneighbors([query_vector]) index [] # 打印最相似的文档 for i in range(3): index indices[0][i] for index in indices[0]: print(flattened_df[chunks].iloc[index]) print(flattened_df[path].iloc[index]) print(flattened_df[distances].iloc[index]) else: print(fIndex {index} not found in DataFrame)在 Notebook 的检索演示中提问 what is a perceptron? 后返回的正是data/perceptron.md中关于感知机二分类模型的内容块验证了检索链路与数据接地grounding的有效性。五、把一切整合起来RAG 聊天机器人最后一步是把 LLM 加入流程得到基于我们数据的回答。核心实现如下注意仓库 Notebook 中已采用 OpenAI 的 Responses API 与部署名称user_input what is a perceptron? def chatbot(user_input): # 将问题转换为查询向量 query_vector create_embeddings(user_input) # 找出最相似的文档 distances, indices nbrs.kneighbors([query_vector]) # 将文档加入查询以提供上下文 history [] for index in indices[0]: history.append(flattened_df[chunks].iloc[index]) # 合并历史与用户输入 history.append(user_input) # 创建消息对象 messages[ {role: system, content: You are an AI assistant that helps with AI questions.}, {role: user, content: history[-1]} ] # 使用 Responses API 生成回答 response client.responses.create( modelchat_deployment, temperature0.7, max_output_tokens800, inputmessages, storeFalse, ) return response.output_text chatbot(user_input)流程可概括为问题 → 嵌入为查询向量 → 最近邻检索相似文档块 → 拼接上下文与问题 → 构造 system/user 消息 → 调用 LLM 生成回答。Notebook 中实际运行结果返回了关于感知机perceptron的完整解释说明模型能够基于课程笔记而非仅凭预训练知识作答。说明本课英文版 README15-rag-and-vector-databases/README.md中保留了基于chat.completions的旧版写法modelgpt-4而 Notebook 已迁移到 Responses APIclient.responses.create模型使用chat_deployment例如gpt-4o-mini。实际运行请以 Notebook 为准并确认AZURE_OPENAI_ENDPOINT、AZURE_OPENAI_API_KEY、AZURE_OPENAI_EMBEDDINGS_DEPLOYMENT、AZURE_OPENAI_DEPLOYMENT环境变量已正确配置。六、评估你的 RAG 应用评估指标回答质量Quality回答是否听起来自然、流畅、像人说的话数据接地Groundedness评估回答是否源自提供的文档相关性Relevance评估回答是否与所提问题匹配、相关流畅度Fluency回答在语法上是否有意义。用 MAP 做定量评估除了上述定性指标Notebook 还提供了一个基于平均精确率均值Mean Average Precision, MAP的定量评估示例见 notebook-rag-vector-databases.ipynb 的 Testing and evaluation 部分定义若干测试用例如 What is a perceptron?、What is machine learning? 等每个用例包含相关回答与不相关回答用sklearn.metrics.average_precision_score计算单查询的平均精确率再对所有用例取平均from sklearn.metrics import average_precision_score total_average_precision 0 for test_case in test_cases: query test_case[query] response chatbot(query) all_responses test_case[relevant_responses] test_case[irrelevant_responses] true_labels [1] * len(test_case[relevant_responses]) [0] * len(test_case[irrelevant_responses]) predicted_scores [1 if resp response else 0 for resp in all_responses] average_precision average_precision_score(true_labels, predicted_scores) total_average_precision average_precision mean_average_precision total_average_precision / len(test_cases)七、RAG 与向量数据库的应用场景RAG 与向量数据库可以改进很多应用例如问答系统把公司数据接地到聊天应用员工可以用它提问推荐系统创建匹配最相似值的系统例如电影、餐厅推荐等聊天机器人服务存储聊天历史基于用户数据个性化对话图像搜索基于向量嵌入的图片搜索在图像识别与异常检测中很有用。八、总结与进阶本课覆盖了 RAG 的基础领域从把数据加入应用、用户查询到最终输出。若要简化 RAG 的构建可以使用 Semantic Kernel、LangChain 或 AutoGen 等框架本仓库第 17 课 AI Agents 对 Agent 框架有进一步介绍。完成本课学习后可以通过以下练习继续深入用你选择的框架为应用构建前端使用 LangChain 或 Semantic Kernel 等框架重建你的 RAG 应用。完整代码与可运行环境见 notebook-rag-vector-databases.ipynb数据文件位于 data/ 目录英文原版讲义见 15-rag-and-vector-databases/README.md。【免费下载链接】generative-ai-for-beginners21 Lessons, Get Started Building with Generative AI项目地址: https://gitcode.com/GitHub_Trending/ge/generative-ai-for-beginners创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考