RAG 概念理解

RAG其实是一种解决方案,RAG(中文为检索增强生成) = 检索技术 + LLM 提示。

完整的RAG应用流程主要包含两个阶段:

  • 数据准备阶段:数据提取——>文本分割——>向量化(嵌入模型将文档数据向量化)——>数据存入向量数据库

  • 应用阶段:用户提问——>数据检索向量数据库——>召回后通过rerank模型筛选和排序——>注入Prompt——>LLM生成答案

在这里插入图片描述

LangChain 概念理解

LangChain 是一个用于开发基于大语言模型(LLMs)的应用程序的开源框架,核心目标是帮助开发者更高效地构建复杂且实用的 AI 应用。它通过模块化设计,将语言模型与外部数据、工具和流程灵活结合,解决了传统 LLM 的局限性(如信息滞后、无法调用外部功能等)。

例如,用 LangChain 构建“天气查询助手”只需几步:接入 OpenAI → 连接天气 API → 设置对话链,即可让模型理解用户意图并调用 API 返回实时数据。

一、项目整体总流程

我自己用LangChain框架写了一个简单的RAG流程代码项目;向量数据库使用的Chroma;搜索引擎使用的本地部署的SearXng搜索引擎,感兴趣的可以看我的另一篇文章,参考SearXng搜索引擎部署:

SearXng搜索引擎本地部署

👋👋👋狠狠的点我获取RAG流程代码👋👋👋,包含联网搜索。

🔭 系统架构

本地md文档数据加载
拆分文档
嵌入模型存入本地向量库
用户提问
混合检索器
本地向量库
网络搜索引擎
搜索结果排序
相似度过滤
结果聚合
模板引擎
LLM生成

目前使用的是实时检索的方式,即没有将搜索结果临时存入向量库,而是直接使用网络搜索结果。

模式代码的实现方式行业常见做法适用场景
实时检索模式直接使用网络搜索结果,不存储将搜索结果临时存入向量库时效性要求高的查询
缓存检索模式未实现定期爬取网络数据构建专用向量库领域知识库构建

🌐 输出结果示例

✅ Searxng连接正常
搜索 今天的头条新闻
测试结果示例:{'title': '今日新闻_头条新闻_今日头条_热点新闻_滚动新闻| 每日经济', 'url': 'http://cn.dailyeconomic.com/roll/', 'content': '央视新闻报道全民冰雪健身热九牧助力中国短道速滑队形象尽显! .每日经济新闻栏目发布报道今日新闻,今日头条新闻和滚动新闻,内容包括今日财经...', 'engine': '360search', 'template': 'default.html', 'parsed_url': ['http', 'cn.dailyeconomic.com', '/roll/', '', '', ''], 'engines': ['360search'], 'positions': [1], 'score': 1.0, 'category': 'general'}
🔄 初始化嵌入模型...
🔄 加载向量数据库...
🔄 加载已有数据库
🔄 初始化大语言模型...
问题: 推荐适合夏天的旅行地
答案生成:🔍 知识库检索
🔍 网络搜索
<think>
好的,我现在要帮用户推荐最适合夏天旅行地。先看看用户给的资料,有很多关于海滩、景点、山区避暑的信息。首先,海滨城市肯定是必选的,像沙滩和海滩都是亮点。然后,海洋公园是海洋生物主题,适合全家游玩,但用户可能更喜欢单个地方,所以可能更倾向于海滩。接下来,新疆的帕米尔高原和喀纳斯是夏天避暑的好地方,人少且凉爽,适合拍照。还有阿克陶县的帕米尔,风景绝美,适合独自旅行。然后是桂林的象鼻山,那里有 pandas,适合拍照和避暑。最后,哈仙岛的骑行和海边也是不错的选择。这些地方都是夏天避暑的好地方,涵盖了海滩、避暑、自然风光和山水,应该能满足用户的需求。
</think>

根据你提供的信息,以下是适合夏天旅行地的推荐:

1. **海滩与海边风光**  
   - **沙滩与海滩度假胜地**:建议选择海滩较多但不过于拥挤的地方,比如撒哈拉以沙漠为背景的海滩(如沙漠热海),或海滩较少但风景优美的地方。
   - **海边骑行与骑行景点**:在沙漠或海边骑行,感受自然风光与阳光,是夏天避暑的好地方。

2. **自然风光与山水**  
   - **山水与自然风光**:可以选择沙漠与沙漠以植被为背景的区域,如哈马斯古特沙漠或多哈沙漠,这些地方人少且风景独特。
   - **山地与自然风光**:如帕米尔高原,那里有独特的火山和森林,适合徒步与摄影。

3. **避暑与山地旅游**  
   - **避暑与山地旅游**:新疆帕米尔高原上的帕米尔之眼(木吉火山)是夏天避暑的绝佳地点,风景优美,人少且凉爽。
   - **山地与自然风光**:在阿克陶县的帕米尔,你可以独自探索山地,欣赏自然风光。

4. **热门海滩与避暑地点**  
   - **热门海滩与避暑地点**:像吉布提的阿格拉、伊克曼哈梅尔等大城市都有多个海滩,可以选择去海滩度假,享受阳光与海风的清凉。

5. **其他景点**  
   - **桂林象鼻山**:桂林的象鼻山是桂林的一个著名景点,那里有 pandas(斑马),拍照时效果棒。
   - **哈密尔顿岛**:去哈密尔顿岛可以租自行车,沿着海面骑行,或在海滩上漫步,感受海风与阳光。

这些地方都是夏季避暑的好选择,既风景如画,又让人放松。根据你的兴趣,可以更多地去探索这些地方,享受大自然的馈赠。
--------来源文档详情--------
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291NbWrwHYHKCyPQj_ei8OKC13fJZ5YRQyviUNg-jrjESnrVGQxYrjqs_0ztd7q5nl6o.
   标题:夏天去哪旅游最合适?想出去玩?这几个地方绝对让你爽翻天!|沙滩|...
内容:2024年3月27日- 我今天可是要给大家推荐几个夏天旅游的好去处,保证让你玩得开心,还不用担心晒伤!一、海滨城市:...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291OfmeUfJy4prXxMqY5OaxBZlSXICAyP3y2npOk7pcdwPg..
   标题:夏季必去的10个旅游胜地推荐(夏季适合去的旅游地 ) - 联途
内容:2023年12月15日- 夏季的迪士尼乐园有丰富的水上项目和演出,是一个适合全家游玩的地方。 2、海洋公园 海洋公园是一个以...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291PD0T3DYzJqFDoBhFbePHvernilvTOuwmlLp9sAy-_qD1vgKM4tqe0g30iymKCpks0.
   标题:五大夏季出行目的地,去过3个以上的可谓旅行达人! - 今日头条
内容:2024年6月6日- 就像新疆的旅游名片宣传的那样:新疆是个好地方。 7月的新疆是热情的季节,能歌善舞的维族姑娘,和无法抗拒...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291PD0T3DYzJqFDoBhFbePHvernilvTOuwmn-3p16fsZJqriJev3xHJIApOnLbKo4VkI.
   标题:6个夏日绝妙旅游地,最后一个一定要去 - 今日头条
内容:2024年7月2日- 评论 收藏 这些景美人少又凉快的夏日绝妙旅行胜地,最后一个一定要去 一、新疆喀纳斯 山花烂漫,雪峰碧水的人间仙境,...
🌐 [360search] https://www.sohu.com/a/476519118_116590
   标题:暑期旅行地推荐!11个最适合去的地方,走!去过20℃的夏天_上图
内容:而在新疆最西部阿克陶县木吉乡的帕米尔高原上,有一座 帕米尔之眼 之称的木吉火山, 这是新疆境内,唯一一处海拔最高的火山口,...
🌐 [360search] https://wenku.so.com/d/c6ac7b9eae96616740c545b3a9405083
   标题:十个适合夏季出游的地方- 360文库
内容:编号,时间,20,年,月,日,文案页码,第6页共6页十个适合夏季出游的地方夏天到了,我们明显的可以感觉到,气温在逐渐上升,夏季有许多人选择外出游玩避暑...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291PcpRzzGwSpthdybzgnFRtxRYtvQ-Na9cLzr-CrmS3vaSHmfGkNvdZG
   标题:夏天去哪里旅游比较好?_伊秀经验
内容:2024年6月29日-以上是一些邯郸夏季旅游的推荐,可以根据自己的兴趣和时间选择适合自己的景点前往。 舟山夏天去哪里旅游比较好? 舟山冬暖夏凉,夏天去海边...
🌐 [360search] https://www.sohu.com/a/146938787_395979
   标题:【旅途推荐】最适合夏天去的8大旅行地,广西这一处你一定要去!
内容:夏天来到哈仙岛,可以租上一辆自行车,沿着笔直清爽的海岸线慢慢骑行.象鼻山可能是我们最初认识桂林的一个地方,小学课本里印象最深的...
🌐 [360search] https://www.sohu.com/a/229912665_100149022
   标题:国内最适合夏天去的八大旅行地,你去过几个?
内容:如果你不知道去哪旅行,VX关注 1001户外旅行 .今年夏天,你打算上岛吗?打算去哪个岛呢?小编之所以没推荐南方那些出名的海岛城市,... 大长...
🌐 [360search] https://www.sohu.com/a/160322552_349209
   标题:8月最佳旅行地推荐!国内最适合夏天避暑的15个地方~
内容:夏天去恩施,高山峡谷中,各类鲜花竞相开放,看杜鹃花、看油菜花、云海……大自然赠予了她一副绝世容颜。.8月最佳旅行地,已为您准备好,拿走...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291PcpRzzGwSpthdybzgnFRtxSzUQ5dA6uf3mkEmlqXBbhSHmfGkNvdZG
   标题:夏季适合去哪旅游_伊秀经验
内容:2024年5月4日-夏季是旅游的好季节,尤其适合去海滩度假、山区避暑或探索自然风光。一些热门的夏季旅游目的地包括:1. 海滩度假胜地:比如马尔代夫、夏威夷、巴厘...
🌐 [sogou] https://www.sogou.com/link?url=hedJjaC291NLckMeq89POrCldf9gYrFNltblpRwB9U54hZnjw4-wpK3mlRzfPLR2
   标题:关于夏季旅游景点排行
内容:2024年7月29日- 旅游时间:5、6月,阳光好,适合游泳,且能避开人潮 3、桂林 漓江两岸风景如画,当你泛着竹排漫游漓江时,肯定会感觉自己置身于360的泼墨山水中...
--------------------------

二、步骤拆分及说明

1、本地数据加载及拆分文档

加载文档、拆分文档

loader = TextLoader(file_path, encoding=encoding)
documents = loader.load()
# 拆分文档
split_docs = markdown_splitter.split_text(documents[0].page_content)
# 拆分文档后,提取纯文本内容
texts = [doc.page_content for doc in split_docs]

2、向量入库(重要)

Chroma作为向量数据库,存储的是文档的嵌入向量,而不是原始文本。当用户使用from_documents方法时,Chroma会自动使用初始化时提供的嵌入模型来处理文档。之后,当进行检索时,Chroma会使用相同的嵌入模型来处理查询,因为模型实例已经绑定到数据库中了。因此,在构建RetrievalQA链时,当调用as_retriever()时,检索器会自动使用之前关联的嵌入模型,不需要再次指定。

vector_db = Chroma.from_documents(
    documents=split_docs,
    embedding=embedding_model,  # ← 这里完成模型绑定
    persist_directory=persist_dir
)

当执行相似度检索时,系统自动执行以下过程:

query_vec = embedding_model.embed_query(question)  # 使用绑定模型
results = chroma_db.query(query_vector=query_vec) 

3、配置LLM连接

项目这里使用的是作者自己本地部署的模型api后端。配置API密钥,openai_api_base地址以及模型名称。

# 从环境变量读取API密钥
os.environ["GPUSTACK_API_KEY"] = "gpustack_******_******"  # 或通过外部注入

# 初始化兼容OpenAI的客户端
llm = ChatOpenAI(
    openai_api_key=os.getenv("GPUSTACK_API_KEY"),
    model="deepseek-r1-1.5B",  # 对应GPUStack的模型名称
    openai_api_base="http://你的大语言模型服务器ip地址:端口号/v1-openai",  # API基础地址
    max_tokens=1024,
    streaming=True  # 启用流式输出
)

4、构建问答系统(重要)

  1. 定义上下文模板
def build_prompt(self) -> PromptTemplate:
    template = """
    <|system|>
    你是一个实时信息助手,请按优先级使用以下资源:
    1. 网络搜索结果(标记为🌐)
    2. 本地知识库(标记为📚)

    {context}

    **规则**:
    1. 若网络搜索结果存在,优先使用并标注来源URL
    2. 本地知识库仅用于补充网络结果
    3. 完全无关时回答“未找到有效信息”
    </s>
    <|user|>
    问题:{question}</s>
    <|assistant|>
    """
    return PromptTemplate(
        template=template,
        input_variables=["context", "question"],
    )
"""

prompt = PromptTemplate(
    template=template,
    input_variables=["context", "question"]
)
  1. 变量注入流程:
User Chain Retriever Prompt LLM 传入 {"query": "问题"} 调用 get_relevant_documents(query) 返回文档列表 自动构建 context=format_context(docs) 填充完整模板 User Chain Retriever Prompt LLM
  1. 关键填充机制详解
  • question 变量
    来源:直接来自用户输入
    传递路径:
qa_system.invoke({"query": "有什么值得一读的好书?"})
            ↓
RetrievalQA 自动提取 query 值
            ↓
映射到 prompt 的 {question} 占位符
  • context 变量
    在 RetrievalQA 链中:context 是框架预定义的保留变量名
  1. RetrievalQA 中指定llm、自定义检索器以及上下文模板。
stream_chain = RetrievalQA.from_chain_type(
    llm=llm.with_config(
        callbacks=[StreamingStdOutCallbackHandler()]
    ),
    retriever=vector_db.as_retriever(),
    chain_type_kwargs={"prompt": prompt},
    return_source_documents=True  # 流式模式也需启用
)

5、流式问答实现(重要)

召回步骤的代码定位,召回的核心实现位于:

# 关键调用点
result = stream_chain.invoke({"query": question})

这个调用背后,LangChain框架自动触发了完整的召回流程。

但是看不到实际的召回过程,添加以下代码来 验证召回过程:

# 显式调用召回过程
print("\n=== 召回阶段开始 ===")
retrieved_docs = vector_db.similarity_search(question, k=3)
for i, doc in enumerate(retrieved_docs):
    print(f"召回文档 {i + 1}:")
    print(f"  元数据: {doc.metadata}")
    print(f"  内容: {doc.page_content[:60]}...\n")

6、联网搜索配置(重要)

  1. search.py搜索类 和 hybrid_retriver.py自定义检索器
  • 添加搜索工具 search.py,import requests 包,封装好参数向搜索引擎url发送请求(本地化搜索引擎详情看OpenWebUI联网搜索配置的SearXng搜索引擎搭建),再将搜索结果转换成 langchain 的 List[Document] 格式。

  • 自定义继承自BaseRetriever的检索器 hybrid_retriver.py,用于构建RetrievalQA,将本地检索结果和网络搜索结果混合,最终输出List[Document]。

  1. _get_relevant_documents 方法调用链路分析
  • 核心调用流程图
User RetrievalQA BaseRetriever CustomRetriever LLM invoke({"query": "问题"}) get_relevant_documents() _get_relevant_documents() List[Document] 传递文档列表 生成最终上下文 User RetrievalQA BaseRetriever CustomRetriever LLM
Logo

助力广东及东莞地区开发者,代码托管、在线学习与竞赛、技术交流与分享、资源共享、职业发展,成为松山湖开发者首选的工作与学习平台

更多推荐