【Task02】:四步构建简单rag(第一章3节)

1. 基于LangChain框架的RAG实现

围绕 "数据准备、索引构建、查询检索、生成集成" 四步,实现 LangChain 框架下的 RAG 应用,通过嵌入模型将文本转为向量索引,检索相关信息后结合大语言模型生成答案。

1.1 初始化设置

  • 核心操作 :导入依赖库(如TextLoaderHuggingFaceEmbeddings)、加载环境变量(load_dotenv()),为后续模块做基础配置。

1.2 数据准备 (Data Preparation)

  • 加载文档 :通过TextLoader加载指定路径的 Markdown 文件(如easy-rl-chapter1.md),获取原始文档数据(docs)。
  • 文本分块 :使用RecursiveCharacterTextSplitter(默认参数)分割长文档,核心规则如下:
    • 分隔符顺序:\n\n(段落)→\n(行)→(空格)→空字符,优先保留语义单元。
    • 默认配置:chunk_size=4000(单块最大长度)、chunk_overlap=200(块间重叠,减少上下文丢失),保留分隔符(keep_separator=True)。

1.3 索引构建 (Index Construction)

1. 初始化嵌入模型 :加载中文嵌入模型BAAI/bge-small-zh-v1.5,配置 CPU 运行、启用向量归一化(normalize_embeddings=True)。

python 复制代码
embeddings = HuggingFaceEmbeddings(
    model_name="BAAI/bge-small-zh-v1.5",
    model_kwargs={'device': 'cpu'},
    encode_kwargs={'normalize_embeddings': True}
)

2. 构建向量存储 :通过InMemoryVectorStore,将分块文本(texts)经嵌入模型转为向量,存储到内存中,形成可查询的向量索引。

1.4 查询与检索 (Query and Retrieval)

  1. 定义查询:设置用户问题(如 "文中举了哪些例子?")。
  2. 相似性检索 :调用向量存储的similarity_search方法,查询与问题最相关的k=3个文本块(retrieved_docs)。
  3. 准备上下文 :用双换行符(\n\n)连接检索到的文本块内容(doc.page_content),清晰区分不同语义片段,便于大模型理解。

3.5 生成集成 (Generation Integration)

  1. 构建提示模板 :用ChatPromptTemplate定义规则,要求模型基于上下文回答,信息不足时返回指定话术。
  2. 配置大模型 :初始化ChatDeepSeek,指定模型(deepseek-chat)、温度(0.7)、最大 Token 数(2048),从环境变量加载 API 密钥。
  3. 生成并输出答案 :将问题和上下文传入提示模板,调用llm.invoke()生成答案并打印。

2. 低代码(基于LlamaIndex)

python 复制代码
import os
# os.environ['HF_ENDPOINT']='https://hf-mirror.com'  # 注释掉的HF镜像配置(国内访问加速用)
from dotenv import load_dotenv  # 用于加载环境变量
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings  # LlamaIndex核心组件
from llama_index.llms.deepseek import DeepSeek  # DeepSeek大语言模型集成
from llama_index.embeddings.huggingface import HuggingFaceEmbedding  # HuggingFace嵌入模型
load_dotenv()  # 从.env文件加载环境变量(通常存放API密钥等敏感信息)
# 配置大语言模型(LLM)为DeepSeek
Settings.llm = DeepSeek(
    model="deepseek-chat",  # 使用的DeepSeek模型名称
    api_key=os.getenv("DEEPSEEK_API_KEY")  # 从环境变量获取API密钥
)

# 配置嵌入模型(用于将文本转换为向量)
Settings.embed_model = HuggingFaceEmbedding(
    "BAAI/bge-small-zh-v1.5"  # 百度的中文嵌入模型
)
documents = SimpleDirectoryReader(
    input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]  # 指定要加载的文档路径
).load_data()  # 加载文档内容
index = VectorStoreIndex.from_documents(documents)
query_engine = index.as_query_engine()
print(query_engine.get_prompts())  # 打印当前查询引擎使用的提示词模板
print(query_engine.query("文中举了哪些例子?"))  # 查询文档中提到的例子并打印结果

练习

  • 修改Langchain代码中RecursiveCharacterTextSplitter()的参数chunk_sizechunk_overlap,观察输出结果有什么变化。
  1. 分块数量与大小变化

    chunk_size=1000, chunk_overlap=100(默认):平衡的分块策略,适合大多数场景

chunk_size=300, chunk_overlap=50(小块):分块数量显著增加,每块更短

​​​​​​​chunk_size=2000, chunk_overlap=300(大块):分块数量减少,每块更长

  1. 对回答的影响

    • 小块配置
      • 优点:检索到的内容更精确,相关性更高
      • 缺点:可能因上下文片段过短导致信息不完整,例子可能被分割到多个块中,导致回答不全面
    • 大块配置
      • 优点:上下文更完整,能保留例子的完整背景
      • 缺点:可能包含过多无关信息,降低检索精度,甚至超出模型上下文窗口
  • LangChain代码最终得到的输出携带了各种参数,查询相关资料尝试把这些参数过滤掉得到content里的具体回答。
python 复制代码
# 原代码
answer = llm.invoke(prompt.format(question=question, context=docs_content))
print(answer)

# 修改后
response = llm.invoke(prompt.format(question=question, context=docs_content))
# 提取纯文本回答
pure_answer = response.content
print(pure_answer)

根据上下文信息,文中举了以下例子:

  1. **走迷宫机器人**:用于说明离散动作空间(只有往东、往南、往西、往北4种移动方式)和连续动作空间(可以向360度中的任意角度移动)。

  2. **雅达利游戏(Pong)**:用于说明策略函数的输入(游戏的一帧)和输出(决定向左或向右移动),以及序列决策中奖励的延迟性(只有到游戏结束时才知道球是否被击打过去)。

  3. **象棋**:作为奖励在事件结束时给出的例子(赢棋得正奖励,输棋得负奖励)。

  4. **股票管理**:作为奖励由获取的奖励与损失决定的例子。

  5. **走迷宫(从起点到终点)**:具体用于解释基于策略的强化学习(每个状态得到最佳动作)和基于价值的强化学习(每个状态返回一个价值)方法如何解决问题。

  6. **Black jack游戏**和**自动驾驶**:用于说明部分可观测环境(智能体只能看到部分观测,如牌面上的牌或传感器信息)。

相关推荐
麻辣清汤4 分钟前
结合BI多维度异常分析(日期-> 商家/渠道->日期(商家/渠道))
数据库·python·sql·finebi
ankleless7 分钟前
Spring Boot 实战:从项目搭建到部署优化
java·spring boot·后端
野生技术架构师1 小时前
2025年中高级后端开发Java岗八股文最新开源
java·开发语言
静若繁花_jingjing1 小时前
JVM常量池
java·开发语言·jvm
_祝你今天愉快2 小时前
Android FrameWork - 开机启动 & Init 进程 初探
android
2501_916007472 小时前
iOS App 上架实战 从内测到应用商店发布的全周期流程解析
android·ios·小程序·https·uni-app·iphone·webview
David爱编程2 小时前
为什么线程不是越多越好?一文讲透上下文切换成本
java·后端
Kan先生2 小时前
对象存储解决方案:MinIO 的架构与代码实战
数据库·python
A尘埃2 小时前
Redis在地理空间数据+实时数据分析中的具体应用场景
java·redis
超级迅猛龙2 小时前
保姆级Debezium抽取SQL Server同步kafka
数据库·hadoop·mysql·sqlserver·kafka·linq·cdc