一文了解RAG———检索增强生成

前言

大家好,我是寻找光的sxy !!!

本文我们将了解Agent中的重要概念RAG,了解它的作用、概念,并通过代码去实现一个RAG流程,希望能对你有用。

为何需要

相信大家现在都或多或少的有在使用AI,现在的AI已经越来越智能了,我们问它很多问题,它都能答出来,十分厉害

但是如果你问它:我今天中午吃了什么?

它要不就回答不知道,要不可能就会捏造出一个食物。。。。。

发现了没,AI没法知道你自己的私人数据!!!

再往大点说,它只能基于它学习过的训练过的数据来生成答案,否则它很容易会回答不准确,甚至产生幻觉

此时,RAG就出现了

RAG的主要作用就是让AI在生成内容时有据可依------实时的检索传入的知识库,来提升模型的准确性

此时,你再问它:我今天中午吃了什么?它就会基于你传入的数据库来回答------吃了盖浇饭

它主要解决三类问题:

  • 上下文长度有限:大模型无法记住你的所有数据,比如,你三天前吃了什么饭
  • 知识局限:大模型的训练数据过时且没有训练过一些垂直领域的知识,比如你公司的年报
  • 降低微调成本:大模型学习新知识需要微调或者重新训练,成本很高,比如,学习你公司的数据

概念

核心概念:让语言模型在生成答案前,先从外部知识库中检索相关依据,并将检索结果作为条件输入融合进生成过程,实现"有源可溯"的智能回答

它主要有5个关键步骤:

  • 文档加载:从知识库加载原始文档
  • 文本分割:将长文档切分为小块
  • 向量化存储 :文本 → 向量 → 存入Chroma数据库
  • 检索:根据问题找到最相似的文档块
  • 生成:将文档 + 问题一起发给LLM生成回答

实践

文档加载

RAG的第一步就是加载原始文档

Agent将通过这些文档来检索信息并回答问题

py 复制代码
# 使用 DirectoryLoader 批量加载目录下的所有txt文件
loader = DirectoryLoader(
        KNOWLEDGE_BASE_DIR,           # 要加载的目录路径
        glob="**/*.txt",               # 文件匹配模式(所有txt文件)
        loader_cls=TextLoader,         # 使用TextLoader作为单文件加载器
        loader_kwargs={"encoding": "utf-8"},  # 指定编码
    )
    
documents = loader.load()  # 执行加载

文本分割

加载完文档后需要将文本进行分割以解决三个问题:

  • 嵌入模型有输入长度限制
  • 小块文本能更精确地匹配用户问题
  • 避免超出LLM的上下文窗口限制
py 复制代码
# 创建文本分割器
text_splitter = RecursiveCharacterTextSplitter(
        chunk_size=300,        # 每块最大300字符
        chunk_overlap=50,      # 相邻块重叠50字符
        length_function=len,   # 使用len函数计算长度
        separators=["\n\n", "\n", "。", "!", "?", " ", ""],  # 分割优先级
        # 先尝试按双换行分割,再按单换行,再按句号...依次尝试
)

# 执行分割
splits = text_splitter.split_documents(documents)

向量化存储

将文本块转换为向量,并存入向量数据库

例如:

py 复制代码
"RAG是检索增强生成技术" → [0.12, -0.45, 0.78, ..., 0.23] (1536维向量)
"什么是RAG?"     → [0.11, -0.43, 0.76, ...] 
"今天天气真好"     → [0.89, 0.12, -0.34, ...]

语义相似的文本会得到相似的向量,上面的第一条和第二条向量就比较接近

py 复制代码
# 创建嵌入模型(使用阿里云通义千问的嵌入模型)
 embeddings = DashScopeEmbeddings(
    dashscope_api_key=api_key,
    model="text-embedding-v2",  # 阿里云的嵌入模型
 )

# 将文本转换为向量
sample_vector = embeddings.embed_query(splits)

 # 清除旧的向量数据库(如果存在)
if os.path.exists(CHROMA_DB_DIR):
    shutil.rmtree(CHROMA_DB_DIR)

检索

将用户问题也转为向量,在数据库中搜索最相似的文本块

py 复制代码
test_queries = [
        "什么是RAG?它有什么优势?",
        "有哪些主流的大语言模型?",
        "向量数据库有哪些?",
    ]
    
    for query in test_queries:
        print(f"\n  🔍 查询: \"{query}\"")
        
        # 方法1:相似性搜索(返回最相似的K个文档)
        results = vectorstore.similarity_search(query, k=2)  # 返回最相似的2个结果
        
        print(f"  📎 检索到 {len(results)} 个相关文本块:")
        for i, doc in enumerate(results, 1):
            source = os.path.basename(doc.metadata.get("source", "未知"))
            content = doc.page_content[:80].replace("\n", " ").strip()
            print(f"    [{i}] 来源: {source}")
            print(f"        内容: {content}...")
        
        # 方法2:带相似度分数的搜索
        results_with_scores = vectorstore.similarity_search_with_score(query, k=1)
        for doc, score in results_with_scores:
            print(f"    📐 最佳匹配相似度分数: {score:.4f} (越小越相似)")
    
    # 创建检索器(Retriever)对象,方便后续使用
    retriever = vectorstore.as_retriever(
        search_type="similarity",  # 使用相似性搜索
        search_kwargs={"k": 3},    # 返回前3个结果
    )

生成

将检索到的文档和用户问题一起发给LLM生成回答

py 复制代码
 
    # 创建LLM实例
    llm = ChatOpenAI(
        model="qwen-plus",  # 通义千问模型
        api_key=api_key,
        base_url="https://dashscope.aliyuncs.com/compatible-mode/v1",
        temperature=0.7,
    )
    
    # RAG的提示词模板------这是连接"检索"和"生成"的桥梁
    rag_prompt_template = """你是一个专业的AI知识助手。请严格基于以下提供的参考资料来回答用户的问题。
如果参考资料中没有相关信息,请明确说明"根据现有资料无法回答该问题"。
请不要编造信息,确保回答的准确性。

=== 参考资料 ===
{context}
=== 参考资料结束 ===

用户问题:{question}

请用中文详细回答:"""
    
    prompt = PromptTemplate(
        template=rag_prompt_template,
        input_variables=["context", "question"],
    )
    
   response = llm.invoke(full_prompt)
        answer = response.content if hasattr(response, "content") else str(response)
        print(f"  {answer}")
相关推荐
测试工坊1 小时前
Android 内存采集避坑指南:一个命令 5ms,一个命令 15 秒,你选哪个?
python
Points1 小时前
飞哥学习人工智能之路第三讲:CNN、RNN与Transformer
人工智能
这儿有一堆花1 小时前
OpenAI 和 Paradigm 推出 EVMbench:AI 帮智能合约把关的新工具
人工智能·智能合约
JaydenAI1 小时前
[拆解LangChain执行引擎]回到过去,开启平行世界[上篇]
python·langchain
一路往蓝-Anbo1 小时前
第 4 章:串口驱动进阶——GPDMA + Idle 中断实现变长数据流接收
linux·人工智能·stm32·单片机·嵌入式硬件
shangjian0071 小时前
AI-大模型应用开发-大模型生成参数调优速查表
人工智能
刘贺同学1 小时前
Day08-龙虾哥打工日记:多 Agent 协作——什么时候该给 AI 招小弟?
aigc·ai编程
麻子1 小时前
手把手教你给 OpenCLAW 添加自定义 Skill
人工智能
Dev7z1 小时前
基于YOLO11的泳池溺水行为实时检测系统设计与实现
人工智能·深度学习·yolo11·泳池溺水