当前位置: 首页 > news >正文

新手入门:用 LangChain+LlamaIndex 构建 RAG,通义千问 API 免费够用

文章目录

    • 一、环境准备:从虚拟环境到 API 配置
      • 1.1 用 Conda 创建独立虚拟环境
      • 1.2 配置通义千问 API Key(免费获取)
    • 二、用 LangChain 构建 RAG:灵活定制版
      • 2.1 完整代码与步骤解析
      • 2.2 运行与验证
    • 三、用 LlamaIndex 构建 RAG:低代码版
      • 3.1 核心优势
      • 3.2 完整实现代码
      • 3.3 新手必看提示
    • 四、两种方案对比与总结
      • 后续进阶方向

在 RAG(检索增强生成)实践中,新手常被两个问题困扰:一是 API 成本高,二是代码配置复杂。本文选择 阿里通义千问 API(注册即送免费额度),结合 LangChain(灵活定制)和 LlamaIndex(低代码)两大框架,手把手教你搭建可运行的 RAG 系统,全程避开复杂运维,适合零基础入门。

一、环境准备:从虚拟环境到 API 配置

1.1 用 Conda 创建独立虚拟环境

为避免依赖冲突,先创建专门的 RAG 虚拟环境(Python 3.12.7 兼容性好,推荐新手使用):

# 1. 创建虚拟环境
conda create --name all-in-rag python=3.12.7 -y
# 2. 激活环境(Windows用:conda activate all-in-rag)
conda activate all-in-rag
# 3. 进入项目目录(自行替换为你的路径)
cd code
# 4. 安装依赖(后续会用到的库一次性装齐)
pip install -r requirements.txt

1.2 配置通义千问 API Key(免费获取)

通义千问的 API 密钥是调用模型的关键,步骤如下:

  1. 获取密钥
    访问阿里云 DashScope 控制台,注册后进入「模型广场」,选择免费的qwen-turbo系列模型(如qwen-turbo-2025-07-15),再到「秘钥管理」创建 API 密钥(保存好,只显示一次)。

  2. 配置环境变量
    vim编辑 Shell 配置文件,将密钥注入环境变量(避免硬编码):

    # 1. 打开配置文件(Linux/Mac通用)
    vim ~/.bashrc
    # 2. 按「i」进入编辑模式,在文件末尾添加(替换[你的密钥])
    export DASHSCOPE_API_KEY=[你的通义千问API密钥]
    # 3. 按「Esc」,输入「:wq」保存退出
    # 4. 让配置立即生效
    source ~/.bashrc
    
  3. 验证配置
    输入echo $DASHSCOPE_API_KEY,若显示你的密钥,则配置成功。

二、用 LangChain 构建 RAG:灵活定制版

LangChain 适合想深入理解 RAG 流程的新手,我们会按「数据准备→索引构建→检索→生成」四步实现,全程用内存向量存储(无需部署数据库,新手友好)。

2.1 完整代码与步骤解析

创建langchain_rag.py文件,代码逐段解析如下:

# 1. 导入依赖库
import os
from dotenv import load_dotenv
# 加载Markdown文档(处理格式更友好)
from langchain_community.document_loaders import UnstructuredMarkdownLoader
# 文本分块工具
from langchain_text_splitters import RecursiveCharacterTextSplitter
# 中文嵌入模型(轻量、免费、中文优化)
from langchain_huggingface import HuggingFaceEmbeddings
# 内存向量存储(无需部署,适合新手)
from langchain_core.vectorstores import InMemoryVectorStore
# 提示词模板
from langchain_core.prompts import ChatPromptTemplate
# 通义千问的LangChain封装
from langchain_community.chat_models import ChatTongyi# 加载环境变量(读取DASHSCOPE_API_KEY)
load_dotenv()# 2. 数据准备:加载本地Markdown文档
# 替换为你的MD文件路径(如技术手册、读书笔记)
markdown_path = "../../data/C1/markdown/easy-rl-chapter1.md"
# 加载文档(UnstructuredMarkdownLoader支持解析MD格式)
loader = UnstructuredMarkdownLoader(markdown_path)
docs = loader.load()
print(f"加载到文档数量:{len(docs)}")  # 新手可验证是否加载成功# 3. 文本分块:拆分长文档(避免语义断裂)
# 默认参数:chunk_size=4000(每块4000字符)、chunk_overlap=200(块间重叠200字符)
text_splitter = RecursiveCharacterTextSplitter()
chunks = text_splitter.split_documents(docs)
print(f"分块后文本片段数量:{len(chunks)}")  # 验证分块效果# 4. 索引构建:文本转向量并存储
# 选择中文友好的轻量嵌入模型(BAAI/bge-small-zh-v1.5)
embeddings = HuggingFaceEmbeddings(model_name="BAAI/bge-small-zh-v1.5",model_kwargs={'device': 'cpu'},  # 无需GPU,CPU即可运行encode_kwargs={'normalize_embeddings': True}  # 向量归一化,提升检索精度
)
# 构建内存向量存储
vectorstore = InMemoryVectorStore(embeddings)
vectorstore.add_documents(chunks)
print("向量索引构建完成")# 5. 检索:根据问题找相关文档
user_question = "文中举了哪些例子?"  # 你的查询问题
# 召回Top3最相关的文本片段(k值不宜过大,避免冗余)
retrieved_docs = vectorstore.similarity_search(user_question, k=3)
# 合并检索结果为上下文(双换行分隔,让LLM清晰区分片段)
context = "\n\n".join(doc.page_content for doc in retrieved_docs)# 6. 生成:调用通义千问生成回答
# 提示词模板(约束LLM仅用上下文回答,避免幻觉)
prompt = ChatPromptTemplate.from_template("""
请严格根据以下上下文回答问题,不添加外部知识:
1. 若上下文有相关信息,条理清晰地总结;
2. 若信息不足,直接回复:“抱歉,无法从上下文找到答案。”上下文:
{context}问题:{question}回答:
""")# 配置通义千问模型
llm = ChatTongyi(model_name="qwen-turbo-2025-07-15",  # 模型名(免费版可选qwen-turbo)temperature=0.7,  # 随机性:0(严谨)~1(灵活),新手建议0.5-0.7max_tokens=2048,  # 最大生成长度,足够回答大多数问题api_key=os.getenv("DASHSCOPE_API_KEY")  # 从环境变量读取密钥
)# 调用LLM生成回答(注意:通义千问响应需用.content获取内容)
response = llm.invoke(prompt.format(context=context, question=user_question))
print("\n===== RAG回答结果 =====")
print(response.content)

2.2 运行与验证

  1. 首次运行注意:会自动下载BAAI/bge-small-zh-v1.5模型(约 100MB),若速度慢,可启用 HF 镜像(代码中注释的os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com')。

  2. 预期输出:类似如下结构化回答(基于easy-rl-chapter1.md内容):

    文中举了以下例子:
    1. 选择餐馆:“利用”是去熟悉的喜欢的餐馆,“探索”是尝试新餐馆;
    2. 做广告:“利用”是用已知最优策略,“探索”是尝试新策略;
    3. 挖油:“利用”是在已知地点挖油,“探索”是尝试新地点;
    4. 玩《街头霸王》:“利用”是重复固定招式,“探索”是尝试新招式;
    5. 小车上山(MountainCar-v0)任务:智能体通过决策到达山顶。
    
  3. 实际输出:

content='文中举了以下例子:\n\n1. 羚羊通过试错学会奔跑,适应环境。\n2. 股票交易:通过不断买卖股票,根据市场反馈学习如何最大化奖励。\n3. 玩雅达利游戏(如 Breakout 和 Pong):通过不断试错学习如何通关。\n4. 小车上山(MountainCar-v0)任务:智能体通过决策控制小车到达山顶。\n5. 选择餐馆:利用是指去熟悉的喜欢的餐馆,探索是指尝试新的餐馆。\n6. 做广告:利用是指采用已知最优广告策略,探索是指尝试新策略以获得更好效果。\n7. 挖油:利用是指在已知地点挖油,探索是指在新地点挖油,可能发现更大油田。\n8. 玩《街头霸王》游戏:利用是指一直使用固定策略(如蹲角落出脚),探索是指尝试新招式(如大招)。' additional_kwargs={} response_metadata={'model_name': 'qwen-turbo-2025-07-15', 'finish_reason': 'stop', 'request_id': '7a7457ba-923f-9bbd-823d-f5d96059d552', 'token_usage': {'input_tokens': 6021, 'output_tokens': 202, 'total_tokens': 6223}} id='run--b7ef53bb-98b4-4997-826f-e2554d9f5d7b-0'
  1. 输出参数解析:
  • content: 这是最核心的部分,即大型语言模型(LLM)根据你的问题和提供的上下文生成的具体回答。
  • additional_kwargs: 包含一些额外的参数,在这个例子中是 {'refusal': None},表示模型没有拒绝回答。
  • response_metadata: 包含了关于LLM响应的元数据。
    • token_usage: 显示了本次调用消耗的token数量,包括完成(completion_tokens)、提示(prompt_tokens)和总量(total_tokens)。
    • model_name: 使用的LLM模型名称,当前是 deepseek-chat
    • system_fingerprint, id, service_tier, finish_reason, logprobs: 这些是更详细的API响应信息,例如 finish_reason: 'stop' 表示模型正常完成了生成。
  • id: 本次运行的唯一标识符。
  • usage_metadata: 与 response_metadata 中的 token_usage 类似,提供了输入和输出token的统计。

三、用 LlamaIndex 构建 RAG:低代码版

LlamaIndex 对 RAG 流程做了更高封装,无需手动拆分 “检索 - 生成” 步骤,适合追求效率的新手。

3.1 核心优势

  • 低代码:一行代码构建索引,一行代码执行查询;
  • 兼容性强:通过OpenAILike类适配通义千问的 OpenAI 兼容接口;
  • 少踩坑:内置文档加载、分块逻辑,无需手动配置。

3.2 完整实现代码

创建llamaindex_rag.py文件:

import os
# 1. 配置HF国内镜像(加速嵌入模型下载)
os.environ['HF_ENDPOINT'] = 'https://hf-mirror.com'
from dotenv import load_dotenv
from llama_index.core import VectorStoreIndex, SimpleDirectoryReader, Settings
# 适配“类OpenAI API”的LLM类(关键:通义千问支持此格式)
from llama_index.llms.openai_like import OpenAILike
# 中文嵌入模型
from llama_index.embeddings.huggingface import HuggingFaceEmbedding# 加载环境变量
load_dotenv()# 2. 关键配置:通义千问的OpenAI兼容接口
# 原因:LlamaIndex的OpenAILike类需对接此格式接口
os.environ["OPENAI_API_BASE"] = "https://dashscope.aliyuncs.com/compatible-mode/v1"# 3. 全局配置:LLM+嵌入模型
# 3.1 配置通义千问
Settings.llm = OpenAILike(model="qwen-turbo-2025-07-15",  # 免费版模型api_key=os.getenv("DASHSCOPE_API_KEY"),  # 通义千问密钥api_base=os.getenv("OPENAI_API_BASE"),  # 兼容接口地址temperature=0.7,max_tokens=2048,is_chat_model=True  # 关键参数:通义千问是聊天模型
)# 3.2 配置嵌入模型(同LangChain,中文友好)
Settings.embed_model = HuggingFaceEmbedding(model_name="BAAI/bge-small-zh-v1.5")# 4. 构建索引:一行代码加载文档+生成向量索引
# 替换为你的MD文件路径
docs = SimpleDirectoryReader(input_files=["../../data/C1/markdown/easy-rl-chapter1.md"]).load_data()
index = VectorStoreIndex.from_documents(docs)  # 自动完成分块、向量化、存储# 5. 执行查询:一行代码完成检索+生成
query_engine = index.as_query_engine()  # 创建查询引擎(封装RAG全流程)
print("\n===== LlamaIndex RAG回答 =====")
# 执行查询并直接打印结果(无需手动处理.content)
print(query_engine.query("文中举了哪些例子?"))

输出为:

文中举了以下例子:1. 选择餐馆:利用是去最喜欢的餐馆,探索是尝试新的餐馆。  
2. 做广告:利用是采取最优的广告策略,探索是尝试新的广告策略。  
3. 挖油:利用是在已知地方挖油,探索是在新地方挖油。  
4. 玩游戏:利用是重复使用一种有效策略,探索是尝试新的招式。

3.3 新手必看提示

  1. 接口配置错误:若提示 “API 调用失败”,检查OPENAI_API_BASE是否为https://dashscope.aliyuncs.com/compatible-mode/v1(官方最新地址)。
  2. 模型名选择:免费版通义千问支持qwen-turbo-2025-07-15,若想尝试更强模型(如qwen-plus),需确认 API 密钥是否有对应额度。
  3. 索引存储:默认存储在内存,重启脚本后需重新构建;若想持久化,可替换为MilvusFAISS(后续进阶内容)。

四、两种方案对比与总结

维度LangChain 实现LlamaIndex 低代码实现
代码量需手动写分块、检索逻辑(约 50 行)核心逻辑仅 5 行(封装度高)
灵活性高(可定制分块、检索策略)中(适合快速验证,定制需进阶)
新手友好度中等(需理解 RAG 流程)高(几乎零配置)
适用场景定制化需求(如多模态 RAG)快速原型、简单文档查询

后续进阶方向

  1. 向量数据库替换:用FAISS(本地)或Milvus(分布式)替代InMemoryVectorStore,支持大规模文档;
  2. 检索优化:添加BM25关键词检索 + 向量检索的混合策略,提升召回率;
  3. 多模态支持:扩展加载 PDF、图片文档,用 CLIP 模型处理多模态检索。

对于新手,建议先从 LlamaIndex 入手,感受 RAG 的便捷性;再用 LangChain 拆解流程,理解每一步的原理。通义千问的免费额度足够完成入门实践,赶紧动手试试吧!

http://www.dtcms.com/a/339903.html

相关文章:

  • 机器人控制基础:串级 PID 和模糊 PID介绍与对比(干货总结)
  • Java 大视界 -- Java 大数据在智能物流无人配送车路径规划与协同调度中的应用
  • [激光原理与应用-303]:光学设计 - 光路设计的输出件
  • Git#cherry-pick
  • 【C语言16天强化训练】从基础入门到进阶:Day 3
  • 光纤通信系统的光纤计量详解-连续测量更高效
  • Protobuf安装和使用
  • 把 AI 变成「图书馆管理员」——基于检索增强的离线图书语音导航小盒子
  • 更新一个GMT新增的投影类型:Spilhaus投影
  • 融智兴“RFID物流周转箱卡”荣获2025“IOTE 金奖”创新产品奖
  • 全0子数组的数目-子数组问题
  • 项目里程碑设定有哪些方法
  • 猫头虎AI分享|字节开源了一款具备长期记忆能力的多模态智能体:M3-Agent 下载、安装、配置、部署教程
  • Visual Studio 中文件属性(在解决方案资源管理器中选中文件,按 F4 或在右键菜单 -> 属性)
  • 【树莓派】【嵌入式】远程树莓派,解决ping不通问题
  • 第5.6节:awk字符串运算
  • python新工具-uv包管理工具
  • 编排之神--Kubernetes中的网络通信-Flannel插件及Calico插件演练
  • Android SystemServer 中 Service 的创建和启动方式
  • Milvus 安装和启动指南
  • 决策树学习(2)
  • almalinux9.6系统:k8s可选组件安装(1)
  • 数字ic后端设计从入门到精通14(含fusion compiler, tcl教学)半定制后端设计
  • 第三阶段数据库-2:数据库连接
  • [超表面论文快讯-200]PNAS-超表面辅助的多模态量子成像-南京大学祝世宁院士/新国立仇成伟院士团队
  • 警惕可变参数构造函数无限递归
  • Day13_【DataFrame数据组合join合并】【案例】
  • 让模型不再忽视少数类:MixUp、CutMix、Focal Loss三种技术解决数据不平衡问题
  • RabbitMQ:SpringAMQP Direct Exchange(直连型交换机)
  • RabbitMQ:SpringAMQP 入门案例