AI Agent 实战课程 之 《RAG 闭环实操:RAG 闭环实操(讲师逐字稿)DeepSeek + LangChain》

原创:朱元禄,转载必须说明来源和出处,如做培训必须说明来源,不得照抄

说在前面的话 01

进入实操前,我先把今天这一段的学习目标说清楚。

我们今天学的不是"背RAG概念",而是学会一项企业最常用、最能落地的AI工程能力:把大模型从"闭卷瞎答"变成"开卷有据"。
你学完这段,你至少能掌握三个就业能力:

第一,面试时面试官问你,什么是 RAG :你能把 RAG 用一句话讲明白:先查资料,再回答。

第二,掌握真正企业级得落地场景:你能把 RAG 的完整闭环跑起来:准备资料、切分、向量化、入库、检索TopK、组装Prompt、输出答案和引用。

第三,你能做最基本的工程验收:答案有没有引用来源?引用里有没有关键证据?模型有没有胡编?
这三点为什么对就业重要?

因为企业招"Agent工程师/AI应用工程师",最看重的不是你会不会背名词,而是你能不能做出可验证、可追溯、可交付的AI功能。企业看重得是能真正能解决问题得能力和价值。
RAG 是目前企业落地最常见的第一站,所以把这一段学扎实,你就已经具备了"能交付一个企业级AI核心模块"的底座。

说在前面的话 02 - 学习目标:学完你到底"会了什么",能掌握什么求职能力

  • 目标1:能解释清楚

    • 我能用"开卷考试"讲清 RAG:为什么需要、解决什么问题、和普通聊天有什么区别。
  • 目标2:能跑通闭环

    • 我能跑通 7 步闭环,不是只会调用模型。
  • 目标3:能输出证据

    • 我能做到"答案 + 引用片段"一起输出,让结果可复核。
  • 目标4:能做最小调优

    • 我知道 k 是翻几页、chunk_size 是便签大小、Prompt 是紧箍咒,能通过小实验看到效果变化。
  • 目标5:能迁移到真实业务

    • 题库问答只是例子,同样方法能迁移到:客服知识库、制度问答、SOP问答、产品手册助手、代码库检索问答。

说着前面得话 03:就业价值:学了这段你在职场上"能做什么事"

  • 从就业角度,这段内容带来的价值非常明确:

    • 你不再只是"会用AI聊天",而是能做出一个企业能用的功能模块:知识库问答/资料检索问答。
  • 这类能力在岗位上通常对应:

    • Agent工程师
    • AI应用工程师
    • 企业知识库/RAG工程师
    • 智能客服/智能助手解决方案工程师

面试时面试官最常问的也就是这些:

  • "你怎么避免大模型胡说?"
  • "你怎么让回答有依据?"
  • "你怎么做权限与可追溯?"
    RAG 闭环就是最标准、最常见、最好落地的答案。

说在前面得话 04:学完能写进简历的"可量化表述"(给你直接复制)

简历表述1

基于 LangChain + DeepSeek 搭建 RAG 闭环(文档切分、向量化、FAISS入库、TopK检索、Prompt组装、引用输出),实现"面试题库问答"原型。

简历表述2

实现答案引用片段展示与"资料不足不编造"约束,提升回答可追溯性与可靠性。

简历表述3

具备 RAG 基础调优能力:通过调整 chunk_size/chunk_overlap/k 与提示词模板优化召回效果与幻觉控制。

1. 回到正文

讲课稿为商业版权文件

下面只粘贴实战代码

python 复制代码
import os
from typing import List

from langchain_openai import ChatOpenAI
from langchain_community.embeddings import HuggingFaceEmbeddings
from langchain_community.vectorstores import FAISS
from langchain_text_splitters import RecursiveCharacterTextSplitter
from langchain_core.documents import Document


def build_docs() -> List[Document]:
    texts = [
        "分库分表常见的全局唯一ID方案包括:雪花算法(Snowflake)、UUID、数据库号段模式(segment)、Redis自增、Leaf等。核心权衡是:有序性、可用性、时钟回拨风险、跨机房一致性。",
        "雪花算法(Snowflake)通常由时间戳+机器ID+序列号组成,优点是大致有序且性能高;风险点是时钟回拨,需要容错与监控。",
        "号段模式(segment)通过数据库提前分配一段ID区间给业务方本地发号,优点是稳定且不依赖时钟;缺点是需要维护号段与容灾。",
        "分布式事务一致性常见思路:2PC/3PC、TCC、Saga、可靠消息最终一致性。选择取决于业务可接受的延迟与补偿复杂度。",
        "幂等指同一个请求执行一次或执行多次,最终结果一致。常见实现:唯一请求号+去重表、分布式锁、状态机/版本号、数据库唯一索引。",
        "限流常见算法:固定窗口、滑动窗口、漏桶、令牌桶。限流用于保护系统,避免突发流量压垮下游。",
        "熔断是当下游故障时快速失败,防止雪崩;常配合降级与重试策略。常见指标:错误率、超时率、RT。",
        "JVM GC 常见算法:标记-清除、标记-整理、复制算法;分代收集结合新生代/老年代特点提升效率。",
        "常见垃圾收集器:Serial、Parallel、CMS、G1、ZGC、Shenandoah。选择取决于吞吐、延迟目标与堆大小。",
        "面试中判断候选人是否真正做过分库分表,要追问:分片键怎么选、跨分片查询怎么做、扩容迁移怎么做、全局ID怎么发、事务一致性怎么处理。",
        "面试中评估并发能力可追问:线程安全、锁粒度、无锁结构、CAS、内存模型、性能瓶颈定位。",
        "面试中评估项目深度:是否能讲清权衡、边界条件、故障处理、监控指标、以及为什么这样设计而不是另一种。",
    ]
    return [Document(page_content=t, metadata={"source": "interview_kb"}) for t in texts]


def build_vectorstore(docs: List[Document]) -> FAISS:
    splitter = RecursiveCharacterTextSplitter(chunk_size=220, chunk_overlap=40)
    chunks = splitter.split_documents(docs)

    embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-MiniLM-L6-v2")
    vs = FAISS.from_documents(chunks, embeddings)
    return vs


def build_llm() -> ChatOpenAI:
    api_key = os.getenv("DEEPSEEK_API_KEY")
    if not api_key:
        raise RuntimeError("Missing env var DEEPSEEK_API_KEY")

    return ChatOpenAI(
        model="deepseek-chat",
        api_key=api_key,
        base_url="https://api.deepseek.com",
        temperature=0.2,
    )


def answer_question(vs: FAISS, llm: ChatOpenAI, question: str, k: int = 4) -> None:
    retriever = vs.as_retriever(search_kwargs={"k": k})
    retrieved = retriever.get_relevant_documents(question)

    context = "\n\n".join([f"[片段{i+1}] {d.page_content}" for i, d in enumerate(retrieved)])

    prompt = f"""你是"面试数字人题库助手"。请严格根据【参考资料】回答【问题】。
要求:
1) 必须基于资料作答;资料不足就回答"资料不足,无法确定",不要编造。
2) 回答要清晰分点。
3) 最后给出"追问建议"(面试官可以继续问什么)1-3条。

【参考资料】
{context}

【问题】
{question}
"""

    resp = llm.invoke(prompt)

    print("\n" + "=" * 90)
    print(f"问题:{question}\n")
    print("【引用片段TopK】")
    for i, d in enumerate(retrieved, 1):
        print(f"{i}. {d.page_content}")
    print("\n【DeepSeek回答】")
    print(resp.content)


def main():
    docs = build_docs()
    vs = build_vectorstore(docs)
    llm = build_llm()

    questions = [
        "分库分表如何生成全局唯一ID?分别说说Snowflake和号段模式的优缺点。",
        "什么是幂等?在支付回调或订单创建场景中怎么保证幂等?",
        "JVM GC 常见算法有哪些?G1 的目标是什么?",
    ]

    for q in questions:
        answer_question(vs, llm, q, k=4)


if __name__ == "__main__":
    main()
相关推荐
Elwin Wong1 小时前
浅析DeepSeek-OCR v1&v2
人工智能·大模型·llm·ocr·deepseek
火山引擎开发者社区1 小时前
火山引擎正式上线 102.4T 自研交换机,构建 AI 网络新底座
网络·人工智能·火山引擎
庄周迷蝴蝶1 小时前
CNN的底层实现方式
人工智能·神经网络·cnn
落雨盛夏1 小时前
深度学习|李哥考研——transformer
人工智能·深度学习·transformer
凤希AI伴侣2 小时前
凤希AI伴侣V1.3.5.0发布:从“功能堆砌”到“体验重塑”的思考
人工智能·凤希ai伴侣
catchadmin2 小时前
Laravel AI SDK 在 Laracon India 2026 首次亮相
人工智能·php·laravel
love530love2 小时前
Windows 11 配置 CUDA 版 llama.cpp 并实现系统全局调用(GGUF 模型本地快速聊天)
人工智能·windows·大模型·llama·llama.cpp·gguf·cuda 加速
一招定胜负2 小时前
从RNN到LSTM:循环神经网络的进化之路
人工智能·rnn·深度学习
阿杰学AI2 小时前
AI核心知识81——大语言模型之MaaS(简洁且通俗易懂版)
人工智能·ai·语言模型·自然语言处理·aigc·maas·模型即服务