


















分析日期:2026-06-04
项目来源:GitHub Trending(2026-06-02)
| 属性 | 详情 |
|---|---|
| 项目名称 | Production Agentic RAG Course(又名 Mother of AI Project - Phase 1) |
| 项目地址 | https://github.com/jamwithai/production-agentic-rag-course |
| 官网 / 博客 | https://jamwithai.substack.com/ |
| 作者 | jamwithai |
| Star / Fork | 6,419 / 1,489 |
| 创建时间 | 2025-08-06 |
| 主要语言 | Python(95%+) |
| 许可证 | MIT License |
| 当前版本 | week7.0(Week 7 Agentic RAG 已发布) |
| 项目定位 | 面向学习者的生产级 Agentic RAG 系统构建实战课程 |
Production Agentic RAG Course 是一个 面向 AI 工程师的生产级 RAG 系统实战课程。项目的核心理念是 "先掌握关键词搜索基础,再增强语义检索"——区别于直接上手向量数据库的教程,本课程遵循真实企业的技术演进路径。
项目以 arxiv 学术论文检索助手 为场景,带领学习者从零开始构建完整的 RAG 系统,历时 7 周逐步迭代:
Week 1: 基础设施(Docker + FastAPI + PostgreSQL + OpenSearch)
↓
Week 2: 数据采集管道(arXiv API + PDF 解析 + Airflow)
↓
Week 3: BM25 关键词搜索(OpenSearch 索引 + 查询 DSL)
↓
Week 4: 混合搜索(分块策略 + Embedding + RRF 融合)
↓
Week 5: 完整 RAG 对话(本地 LLM + 流式响应 + Gradio 界面)
↓
Week 6: 生产级监控与缓存(Langfuse 追踪 + Redis 缓存)
↓
Week 7: Agentic RAG(LangGraph 决策 + Telegram Bot)
核心主张:构建 RAG 系统的正确方式是先建立扎实的关键词搜索基础,再在此之上叠加 AI 语义能力,而非一开始就纯依赖向量检索。
┌─────────────────────────────────────────────────────────┐
│ Telegram Bot / Gradio │
│ (用户交互层,Week 5-7) │
└────────────────────────┬────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ FastAPI 路由层 │
│ /api/v1/ask · /api/v1/stream · /api/v1/agentic │
│ /api/v1/hybrid-search · /api/v1/ping │
└────────────────────────┬────────────────────────────────┘
▼
┌────────────────────────────────────┼─────────────────────────────────────┐
│ ▼ │
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌─────────────┐│
│ │ Langfuse │ │ Redis │ │ Agentic │ │ RAG ││
│ │ Tracing │ │ Cache │ │ RAG │ │ Pipeline ││
│ │(Week 6) │ │(Week 6) │ │(Week 7) │ │(Week 5) ││
│ └──────┬───────┘ └──────┬───────┘ └──────┬───────┘ └──────┬──────┘│
└─────────┼─────────────────┼──────────────────┼──────────────────┼───────┘
▼ ▼ ▼ ▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Service Layer(业务服务) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ OpenSearch │ │ Embeddings │ │ Ollama │ │ PDF Parser │ │
│ │(Week 3-4) │ │(Week 4) │ │(Week 5) │ │(Week 2) │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
│ │ arXiv API │ │ Metadata │ │ Indexing │ │ Cache Svc │ │
│ │(Week 2) │ │ Fetcher │ │(Week 3-4) │ │(Week 6) │ │
│ │ │ │(Week 2) │ │ │ │ │ │
│ └─────────────┘ └─────────────┘ └─────────────┘ └─────────────┘ │
└──────────────────────────────────┬──────────────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────────────────────┐
│ Data Storage(数据存储) │
│ PostgreSQL 16 ←─────── 论文元数据存储(Paper 表) │
│ OpenSearch 2.19 ←────── 倒排索引 + 向量索引(BM25 + Hybrid) │
│ Redis ←────────────── LLM 响应缓存(LRU + 精确键匹配) │
│ Langfuse Postgres ←─── 追踪数据(独立实例) │
└─────────────────────────────────────────────────────────────────────────┘
▲
┌──────────────────────────────────┴──────────────────────────────────────┐
│ Apache Airflow(Week 2) │
│ DAG: 定时抓取 arXiv 新论文 → 解析 → 入库 │
└─────────────────────────────────────────────────────────────────────────┘
| 特性 | 说明 |
|---|---|
| 7 周渐进式架构演进 | 从 Docker Compose 到 Agentic RAG,每周一个可运行的版本 |
| 周度 Tag 发布 | 每个 Week 对应一个 Git Tag(week1.0 ~ week7.0),可随时切换查看 |
| 博客 + 视频讲解 | 每周配套 Substack 深度文章,讲解设计决策与工程实践 |
| 完整测试套件 | pytest + testcontainers,所有组件都有单元/集成测试 |
| 特性 | 说明 |
|---|---|
| Docker 多阶段构建 | 基于 astral-sh/uv 的 slim 镜像,生产级 Dockerfile |
| uv 依赖管理 | 使用 astral-sh/uv 替代 pip,速度提升 10-100 倍 |
| 健康检查 | 所有容器均配置 healthcheck,自动恢复不健康服务 |
| Pydantic v2 数据模型 | 严格的类型校验,自动生成 OpenAPI 文档 |
| Ruff 代码规范 | line-length=130,统一代码风格 |
| .env 配置管理 | 环境变量驱动所有配置,遵循 12-Factor 原则 |
| 技术 | 说明 |
|---|---|
| 混合搜索(Hybrid Search) | BM25 + 向量相似度 + RRF(Reciprocal Rank Fusion)融合 |
| 智能分块 | Section-aware chunking,基于文档结构而非固定长度 |
| Jina Embeddings | Jina AI v2 嵌入模型,支持降级策略 |
| 本地 LLM(Ollama) | 完全离线可运行,支持模型热切换 |
| 流式响应 | Server-Sent Events(SSE),实时打字机效果 |
| Redis 缓存 | 精确键匹配缓存,命中后 1ms 返回,平均提速 150-400 倍 |
| Langfuse 追踪 | 端到端追踪,Token 成本、延迟、质量全可视化 |
| 特性 | 说明 |
|---|---|
| LangGraph 工作流 | 图式 Agent 编排,支持条件路由与循环决策 |
| 文档分级评估 | Agent 自动判断检索文档是否足够回答问题 |
| 查询重写(Query Rewriting) | 当检索结果不足时,Agent 自动重写查询再次检索 |
| 护栏机制(Guardrails) | 识别越界问题(如非学术领域提问),拒绝回答 |
| 推理步骤透明 | 完整展示 Agent 的思考过程,增强可解释性 |
| Telegram Bot | 移动端接入,随时随地使用 RAG 助手 |
| 特性 | 说明 |
|---|---|
| MIT 许可证 | 完全商业友好 |
| 详细 README | 超过 500 行的项目说明文档 |
| 完整 Notebook | 每个 Week 都有配套 Jupyter Notebook 教学 |
| 活跃社区 | Issue 响应迅速,PR 活跃 |
| 要求 | 最低配置 | 推荐配置 |
|---|---|---|
| 操作系统 | Linux / macOS / Windows(WSL2) | Linux / macOS(原生) |
| Python 版本 | >= 3.12 | 3.12.8(与 Dockerfile 一致) |
| Docker | Docker Desktop 4.25+ | 最新稳定版 |
| Docker Compose | v2 插件版本 | v2.20+ |
| 内存(RAM) | 8 GB | 16 GB+(运行 LLM 时需要) |
| 磁盘空间 | 20 GB | 50 GB+(Docker 镜像 + 向量索引 + LLM 模型) |
| CPU | 4 核 | 8 核+ |
| GPU(可选) | 无 | NVIDIA GPU(CUDA 12+,用于本地 LLM 加速) |
| 网络 | 需访问 GitHub、arXiv、PyPI | 稳定宽带 |
| 依赖包 | 版本范围 | 用途 |
|---|---|---|
| fastapi[standard] | >= 0.115.12 | Web 框架,自动文档 |
| uvicorn | >= 0.34.0 | ASGI 服务器,4 Worker 生产部署 |
| pydantic | >= 2.11.3 | 数据模型 + 校验 |
| sqlalchemy | >= 2.0.0 | ORM,PostgreSQL 访问 |
| psycopg2-binary | >= 2.9.10 | PostgreSQL 驱动 |
| opensearch-py | >= 3.0.0 | OpenSearch 客户端 |
| sentence-transformers | >= 5.1.0 | 本地 Embedding 模型 |
| redis | >= 6.4.0 | 缓存客户端 |
| langfuse | >= 3.0.0 | 追踪与观察性 |
| langgraph | >= 0.2.0 | Agent 工作流编排 |
| langchain | >= 0.3.0 | LLM 工具链 |
| langchain-ollama | >= 0.3.0 | Ollama 集成 |
| python-telegram-bot | >= 21.0, <22 | Telegram Bot SDK |
| gradio | >= 4.0.0 | 交互式 Web UI |
| docling | >= 2.43.0 | 科学 PDF 智能解析 |
| httpx | >= 0.28.1 | 异步 HTTP 客户端(arXiv API) |
| alembic | >= 1.13.3 | 数据库迁移工具 |
开发依赖:pytest, pytest-asyncio, testcontainers, ruff, mypy, pre-commit, notebook, jupyter
| 服务 | 容器端口 | 主机端口 | 用途 |
|---|---|---|---|
| FastAPI | 8000 | 8000 | API 服务 + /docs Swagger |
| Gradio | 7861 | 7861 | 交互式聊天界面 |
| PostgreSQL | 5432 | 5432 | 论文元数据存储 |
| OpenSearch | 9200, 9600 | 9200, 9600 | 搜索引擎(REST + 节点通信) |
| OpenSearch Dashboards | 5601 | 5601 | 搜索可视化面板 |
| Apache Airflow | 8080 | 8080 | DAG 调度与管理 |
| Ollama | 11434 | 11434 | 本地 LLM 推理服务 |
| Redis(主) | 6379 | 6379 | LLM 响应缓存 |
| Langfuse Web | 3000 | 3001 | 追踪仪表盘 |
| Langfuse Postgres | 5432 | 5433 | 追踪数据存储(独立实例) |
| Langfuse Redis | 6379 | 6380 | Langfuse 内部缓存 |
| ClickHouse | 8123, 9000 | 8123, 9000 | Langfuse 分析引擎 |
# 1. 克隆仓库
git clone https://github.com/jamwithai/production-agentic-rag-course.git
cd production-agentic-rag-course
# 2. 配置环境变量(添加 Jina/OpenAI/Langfuse API Key)
cp .env.example .env
# 编辑 .env 文件,填入以下关键配置:
# - JINA_API_KEY(用于 Embeddings)
# - LANGFUSE_SECRET_KEY / LANGFUSE_PUBLIC_KEY(用于追踪)
# - TELEGRAM_BOT_TOKEN(Week 7 可选)
# 3. 安装 Python 依赖(本地开发用)
uv sync
# 4. 启动全部服务(首次构建可能需要 5-10 分钟)
docker compose up --build -d
# 5. 健康检查(应返回 {"status": "healthy"})
curl http://localhost:8000/api/v1/health
# 6. 打开交互界面
# - API 文档: http://localhost:8000/docs
# - Gradio 聊天: http://localhost:7861
# - Langfuse: http://localhost:3001
# - Airflow: http://localhost:8080
# 7. 克隆特定周的代码(如 Week 7)
git checkout week7.0
| 服务 | 用途 | 是否必填 |
|---|---|---|
| Jina AI API | 生产级 Embeddings 生成 | 推荐(Week 4+ 需要) |
| Langfuse Cloud / Self-host | RAG 管道追踪与成本分析 | 推荐(Week 6+ 需要) |
| Ollama 本地模型 | llama3 / qwen2.5 等模型 | 可选(可换为 OpenAI API) |
| Telegram Bot Token | 移动端 Agent 接入 | 可选(Week 7 需要) |
production-agentic-rag-course/
├── src/ # 源代码主目录
│ ├── main.py # FastAPI 应用入口(~4.5KB)
│ ├── config.py # 全局配置(Pydantic Settings,~6KB)
│ ├── database.py # SQLAlchemy 会话管理
│ ├── dependencies.py # FastAPI 依赖注入(~4KB)
│ ├── exceptions.py # 自定义异常与错误处理
│ ├── middlewares.py # 请求/响应中间件
│ ├── gradio_app.py # Gradio 交互式界面(~9.5KB)
│ │
│ ├── models/ # 数据模型
│ │ ├── __init__.py
│ │ └── paper.py # Paper ORM 模型(SQLAlchemy)
│ │
│ ├── schemas/ # Pydantic 请求/响应 Schema
│ │ └── (请求 DTO、响应 DTO 定义)
│ │
│ ├── repositories/ # 数据访问层(Repository Pattern)
│ │ └── (封装 DB 操作,解耦业务逻辑与存储)
│ │
│ ├── routers/ # API 路由层(FastAPI APIRouter)
│ │ ├── __init__.py
│ │ ├── ping.py # 健康检查端点(~2.8KB)
│ │ ├── search.py # BM25 关键词搜索(Week 3)
│ │ ├── hybrid_search.py # 混合搜索(BM25 + 向量,~3KB)
│ │ ├── ask.py # 普通 RAG 问答(标准 + 流式,~11.6KB)
│ │ └── agentic_ask.py # Agentic RAG 问答(~3.6KB)
│ │
│ └── services/ # 业务服务层(核心逻辑)
│ ├── metadata_fetcher.py # arXiv 元数据抓取(~18.5KB,Week 2 核心)
│ │
│ ├── arxiv/ # arXiv API 封装
│ │ └── (论文检索、分类、增量同步)
│ │
│ ├── pdf_parser/ # PDF 解析(Docling 驱动,Week 2)
│ │ └── (结构化提取:标题、摘要、章节、参考文献)
│ │
│ ├── opensearch/ # 搜索引擎服务(Week 3-4)
│ │ ├── __init__.py
│ │ ├── client.py # OpenSearch 客户端封装
│ │ ├── indexer.py # 文档索引导入
│ │ └── searcher.py # BM25 + Hybrid 查询逻辑
│ │
│ ├── embeddings/ # Embedding 服务(Week 4)
│ │ ├── __init__.py
│ │ ├── jina_client.py # Jina AI API 客户端
│ │ └── fallback.py # 降级策略(sentence-transformers 本地)
│ │
│ ├── indexing/ # 索引管道
│ │ ├── __init__.py
│ │ ├── text_chunker.py # Section-aware 智能分块
│ │ └── pipeline.py # 从 PDF → 分块 → 索引的全流程
│ │
│ ├── ollama/ # 本地 LLM 服务(Week 5)
│ │ ├── __init__.py
│ │ ├── client.py # Ollama REST 客户端
│ │ ├── rag_engine.py # RAG Prompt 组装与 LLM 调用
│ │ └── prompts/ # Prompt 模板(纯文本文件)
│ │ └── rag_system.txt # 学术论文问答系统 Prompt
│ │
│ ├── cache/ # Redis 缓存服务(Week 6)
│ │ ├── __init__.py
│ │ └── cache_service.py # 精确键匹配 + TTL 管理
│ │
│ ├── langfuse/ # Langfuse 追踪集成(Week 6)
│ │ ├── __init__.py
│ │ └── tracer.py # 装饰器模式,自动追踪调用
│ │
│ ├── agents/ # Agentic RAG(Week 7,核心亮点模块)
│ │ ├── __init__.py
│ │ ├── agentic_rag.py # LangGraph 工作流主文件(~18.2KB)
│ │ ├── state.py # Agent 状态定义(TypedDict)
│ │ ├── models.py # Agent 消息模型(~3.8KB)
│ │ ├── tools.py # Agent 可用工具(检索、评分等,~3KB)
│ │ ├── prompts.py # Agent Prompt 模板(~5.5KB)
│ │ ├── config.py # Agent 配置参数
│ │ ├── context.py # 上下文管理(~1.5KB)
│ │ ├── factory.py # Agent 工厂函数(~1.5KB)
│ │ └── nodes/ # LangGraph 节点(每个函数一个节点)
│ │ ├── __init__.py
│ │ ├── retrieve.py # 检索节点
│ │ ├── evaluate.py # 文档评估节点
│ │ ├── rewrite.py # 查询重写节点
│ │ ├── generate.py # 生成回答节点
│ │ └── guardrails.py # 护栏节点
│ │
│ └── telegram/ # Telegram Bot(Week 7)
│ ├── __init__.py
│ └── bot.py # python-telegram-bot 封装
│
├── airflow/ # Airflow 配置与 DAG(Week 2)
│ ├── Dockerfile # Airflow 自定义镜像
│ ├── dags/ # DAG 定义
│ │ └── arxiv_ingestion_dag.py # 每日 arXiv 论文抓取 DAG
│ └── plugins/ # 自定义 Airflow 插件
│
├── notebooks/ # 教学 Notebook(每周一份)
│ ├── week1/
│ │ └── week1_setup.ipynb # 基础设施搭建教程
│ ├── week2/
│ │ └── week2_arxiv_integration.ipynb # 数据管道教程
│ ├── week3/
│ │ └── week3_opensearch.ipynb # BM25 搜索教程
│ ├── week4/
│ │ └── week4_hybrid_search.ipynb # 混合搜索教程
│ ├── week5/
│ │ └── week5_complete_rag_system.ipynb # 完整 RAG 教程
│ └── (week6, week7 notebooks...)
│
├── tests/ # 测试套件
│ ├── unit/ # 单元测试
│ ├── integration/ # 集成测试(testcontainers)
│ └── conftest.py # pytest 配置与 Fixtures
│
├── static/ # 架构图与演示 GIF
│ ├── mother_of_ai_project_rag_architecture.gif
│ ├── week1_infra_setup.png
│ ├── week2_data_ingestion_flow.png
│ ├── week3_opensearch_flow.png
│ ├── week4_hybrid_opensearch.png
│ ├── week5_complete_rag.png
│ ├── week7_telegram_and_agentic_ai.png
│ └── langgraph-mermaid.png
│
├── Dockerfile # FastAPI 服务镜像(~40 行)
├── compose.yml # 全栈 Docker Compose(~300 行,10+ 服务)
├── pyproject.toml # 项目配置与依赖(uv + PEP 621)
├── uv.lock # 锁定的依赖版本树(由 uv 生成)
├── .env.example # 环境变量示例
├── .pre-commit-config.yaml # pre-commit 钩子(ruff、mypy)
├── Makefile # 常用命令(up、down、logs、test)
├── gradio_launcher.py # Gradio 启动脚本
└── README.md # 主文档(~500 行)
┌─────────────────────────────────────────────────────────┐
│ Presentation Layer(表示层) │
│ src/routers/*.py + src/gradio_app.py │
│ 职责:HTTP 路由解析、参数校验、响应格式化、SSE 流式 │
└──────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ Service Layer(业务层) │
│ src/services/* │
│ 职责:业务逻辑编排、工具调用协调、Agent 决策循环 │
└──────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ Repository Layer(持久层) │
│ src/repositories/ + src/models/ │
│ 职责:数据访问抽象,屏蔽 PostgreSQL / OpenSearch 差异 │
└──────────────────────────┬──────────────────────────────┘
▼
┌─────────────────────────────────────────────────────────┐
│ Infrastructure Layer(基础设施层) │
│ src/config.py + src/database.py + Docker 服务 │
│ 职责:外部服务连接、配置加载、连接池管理 │
└─────────────────────────────────────────────────────────┘
设计亮点:
src/dependencies.py)获得数据库会话和服务实例src/dependencies.py 定义了全局依赖:
# 核心依赖(简化示意)
def get_db_session() -> Session:
"""提供线程安全的 PostgreSQL 会话"""
session = SessionLocal()
try:
yield session
finally:
session.close()
def get_opensearch_client() -> OpenSearch:
"""获取 OpenSearch 客户端"""
return OpenSearch(config.OPENSEARCH_HOST, ...)
def get_rag_service() -> RAGService:
"""组合依赖,生成 RAG 服务实例"""
return RAGService(
search_client=get_opensearch_client(),
llm_client=get_ollama_client(),
cache=get_redis_cache(),
tracer=get_langfuse_tracer(),
)
src/config.py 使用 Pydantic v2 的 BaseSettings,支持:
.env 文件自动读取src/services/agents/factory.py 提供统一的 Agent 创建入口:
def create_agentic_rag_agent(
llm_provider: str = "ollama",
model_name: str = "llama3",
search_tool: Callable = None,
**kwargs
) -> LangGraphAgent:
"""统一的 Agent 工厂函数。
不同 LLM 提供商在这里被封装为统一接口。
"""
┌─────────────────────┐
│ 用户输入 Query │
└──────────┬──────────┘
▼
┌─────────────────────┐
│ Guardrail N │
│ (护栏检测) │
│ - 是否越界? │
│ - 需要搜索? │
└──────┬──────┬───────┘
│ │
越界/闲聊 │ │ 需要检索
▼ ▼
┌─────────┐ ┌───────────────┐
│ 直接拒绝 │ │ Retrieve N │
└─────────┘ │ (文档检索) │
└──────┬──────────┘
▼
┌─────────────────────┐
│ Evaluate Docs N │
│ (文档相关性评分) │
│ - 计算相似度 │
│ - 判断是否足够回答 │
└──────┬──────┬───────┘
│ │
足够了 │ │ 不足
▼ ▼
┌─────────┐ ┌───────────────┐
│ Generate │ │ Rewrite Query │
│(生成回答)│ │(查询重写) │
└────┬────┘ └──────┬────────┘
│ │
│ 返回 Loop │
└────────────────┘
│
▼
┌────────────────────────┐
│ Langfuse Trace + │
│ Redis Cache 写入 │
└───────────┬────────────┘
▼
┌────────────────────────┐
│ 流式响应给用户 │
└────────────────────────┘
工作流说明:
src/services/agents/nodes/guardrails.py):先判断用户意图,拦截闲聊或越界问题retrieve.py):调用混合搜索 API 获取 Top-K 文档evaluate.py):使用 LLM 或向量相似度评估文档与问题的匹配度rewrite.py):若评估不通过,根据已有文档提示重写查询再次检索generate.py):基于足够上下文,通过结构化 Prompt 生成最终答案# 1. 创建 FastAPI 应用实例
app = FastAPI(title="arXiv RAG API", version="0.1.0")
# 2. 注册中间件(CORS、请求日志、Langfuse 追踪)
app.add_middleware(CORSMiddleware, allow_origins=["*"], ...)
# 3. 注册全局异常处理器(统一错误响应格式)
app.add_exception_handler(HeadlineException, custom_exception_handler)
# 4. 挂载路由(每个 Router 对应一个业务模块)
app.include_router(ping.router, prefix="/api/v1", tags=["Health"])
app.include_router(search.router, prefix="/api/v1", tags=["Search"])
app.include_router(hybrid_search.router, prefix="/api/v1", tags=["Hybrid Search"])
app.include_router(ask.router, prefix="/api/v1", tags=["RAG"])
app.include_router(agentic_ask.router, prefix="/api/v1", tags=["Agentic RAG"])
# 5. 启动事件:预热模型、初始化索引
@app.on_event("startup")
async def startup_event():
await opensearch_client.ensure_index_exists()
logger.info("All services initialized")
# POST /api/v1/ask(标准 JSON 响应)
async def ask_question(
request: AskRequest,
rag_service: RAGService = Depends(get_rag_service),
) -> AskResponse:
"""给定问题,检索相关文档并用 LLM 生成回答。"""
# Step 1. 混合搜索(关键词 BM25 + 向量 + RRF 融合)
search_results = await rag_service.search(
query=request.query,
top_k=request.top_k,
hybrid=request.use_hybrid_search,
)
# Step 2. 缓存检查(Week 6)
cached = await rag_service.check_cache(request.query)
if cached and not request.force_refresh:
return AskResponse(answer=cached, sources=[], cached=True)
# Step 3. 构造 RAG Prompt(系统 Prompt + 文档上下文 + 用户问题)
context_prompt = rag_service.build_context(search_results)
full_prompt = SYSTEM_PROMPT + "\n" + context_prompt + "\nQuestion: " + request.query
# Step 4. 调用 LLM 生成
answer = await rag_service.llm.generate(full_prompt, temperature=request.temperature)
# Step 5. 写入缓存 + 上报追踪
await rag_service.write_cache(request.query, answer, ttl=3600)
rag_service.trace(request.query, answer, search_results) # Langfuse
return AskResponse(answer=answer, sources=search_results, cached=False)
# POST /api/v1/stream(SSE 流式响应)
async def ask_question_stream(request: AskRequest, ...):
"""与 /ask 逻辑相同,但响应为 Server-Sent Events 流式输出。"""
async for token in rag_service.llm.generate_stream(full_prompt):
yield f"data: {token}\n\n"
yield "data: [DONE]\n\n"
class AgenticRAGEngine:
"""基于 LangGraph 的 Agentic RAG 引擎。"""
def __init__(self, llm, search_tool, config):
self.llm = llm # LLM 客户端(Ollama/OpenAI)
self.search_tool = search_tool # 可调用的搜索函数
self.config = config # Agent 配置(重试次数、温度等)
# 构建 LangGraph 状态图
self.graph = self._build_graph()
def _build_graph(self) -> StateGraph:
"""构建图结构,定义节点与条件边。"""
graph = StateGraph(AgentState)
# 注册节点(每个节点是一个函数)
graph.add_node("guardrail", guardrail_node)
graph.add_node("retrieve", retrieve_node)
graph.add_node("evaluate", evaluate_node)
graph.add_node("rewrite", rewrite_node)
graph.add_node("generate", generate_node)
# 设置入口
graph.set_entry_point("guardrail")
# 定义条件边(核心决策逻辑)
graph.add_conditional_edges(
"guardrail",
self._should_continue, # 返回 "retrieve" 或 "reject"
{"retrieve": "retrieve", "reject": END},
)
graph.add_edge("retrieve", "evaluate")
graph.add_conditional_edges(
"evaluate",
self._sufficient_context, # 返回 "generate" 或 "rewrite"
{"generate": "generate", "rewrite": "rewrite"},
)
graph.add_edge("rewrite", "retrieve") # 重写后回到检索(循环)
graph.add_edge("generate", END)
return graph.compile()
def answer(self, query: str) -> AgentResponse:
"""执行完整 Agent 流程。"""
initial_state = AgentState(
query=query,
documents=[],
iteration_count=0,
max_iterations=self.config.max_retries,
)
final_state = self.graph.invoke(initial_state)
return AgentResponse(
answer=final_state["answer"],
sources=final_state["documents"],
reasoning=final_state["reasoning_trace"],
iterations=final_state["iteration_count"],
)
# src/config.py(简化版)
class Settings(BaseSettings):
"""统一配置入口,自动从环境变量加载。"""
# API 服务
API_HOST: str = "0.0.0.0"
API_PORT: int = 8000
# PostgreSQL
POSTGRES_DATABASE_URL: str = (
"postgresql+psycopg2://rag_user:rag_password@postgres:5432/rag_db"
)
# OpenSearch
OPENSEARCH_HOST: str = "http://opensearch:9200"
OPENSEARCH_INDEX: str = "arxiv_papers"
OPENSEARCH_BM25_K1: float = 1.2 # BM25 核心参数
OPENSEARCH_BM25_B: float = 0.75
# Redis
REDIS_HOST: str = "redis"
REDIS_PORT: int = 6379
REDIS_CACHE_TTL: int = 3600
# LLM(Ollama)
OLLAMA_HOST: str = "http://ollama:11434"
OLLAMA_MODEL: str = "llama3"
OLLAMA_TEMPERATURE: float = 0.2
# Embeddings
JINA_API_KEY: str | None = None
EMBEDDING_MODEL: str = "jina-embeddings-v2-base-en"
EMBEDDING_DIM: int = 768
# Langfuse 追踪
LANGFUSE_HOST: str = "http://langfuse-web:3000"
LANGFUSE_PUBLIC_KEY: str | None = None
LANGFUSE_SECRET_KEY: str | None = None
# Agent 配置
AGENT_MAX_RETRIES: int = 3
AGENT_RELEVANCE_THRESHOLD: float = 0.7
class Config:
env_file = ".env"
extra = "ignore"
settings = Settings()
services:
# 主 API 服务(FastAPI)
api:
build: .
container_name: rag-api
ports:
- "8000:8000"
depends_on:
postgres:
condition: service_healthy
opensearch:
condition: service_healthy
redis:
condition: service_healthy
healthcheck:
test: ["CMD-SHELL", "curl -f http://localhost:8000/api/v1/health"]
interval: 30s
timeout: 10s
retries: 3
env_file:
- .env
# 搜索引擎(核心存储组件)
opensearch:
image: opensearchproject/opensearch:2.19.0
environment:
- discovery.type=single-node
- OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m
- DISABLE_SECURITY_PLUGIN=true
ports:
- "9200:9200"
- "9600:9600"
volumes:
- opensearch_data:/usr/share/opensearch/data
# 缓存层(Week 6 引入)
redis:
image: redis:7-alpine
command: redis-server --appendonly yes --maxmemory 256mb --maxmemory-policy allkeys-lru
ports:
- "6379:6379"
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 3s
retries: 3
# 本地 LLM(Week 5 引入)
ollama:
image: ollama/ollama:0.11.2
ports:
- "11434:11434"
volumes:
- ollama_data:/root/.ollama
# 数据管道(Week 2 引入)
airflow:
build: ./airflow
volumes:
- ./airflow/dags:/opt/airflow/dags
- ./src:/opt/airflow/src
environment:
- PYTHONPATH=/opt/airflow/src
# 可观测性(Week 6 引入,独立命名空间)
langfuse-web:
image: langfuse/langfuse:3
depends_on:
langfuse-postgres:
condition: service_healthy
clickhouse:
condition: service_healthy
ports:
- "3001:3000"
environment:
- DATABASE_URL=postgresql://langfuse:xxx@langfuse-postgres:5432/langfuse
- CLICKHOUSE_URL=http://clickhouse:8123
volumes:
postgres_data:
opensearch_data:
ollama_data:
airflow_logs:
redis_data:
clickhouse_data:
langfuse_v3_postgres_data:
langfuse_v3_minio_data:
networks:
rag-network:
driver: bridge
| 模块 | 主文件数 | 估计总行数 | 核心文件(Size) |
|---|---|---|---|
| API 路由层 | 5+ | ~1,500 | ask.py (11.6KB), hybrid_search.py (3KB), agentic_ask.py (3.6KB) |
| Service 业务层 | 30+ | ~6,000 | agentic_rag.py (18.2KB), metadata_fetcher.py (18.5KB) |
| Agent 节点 | 5+ | ~1,000 | tools.py (3KB), state.py (2.5KB), prompts.py (5.5KB) |
| 配置与依赖 | 4 | ~500 | config.py (6KB), dependencies.py (4.2KB) |
| Gradio UI | 1 | ~300 | gradio_app.py (9.5KB) |
| Airflow DAG | 1+ | ~500 | arxiv_ingestion_dag.py |
| Docker/编排 | 3 | ~400 | Dockerfile, compose.yml, Makefile |
| Notebooks | 7+ | 大量 Markdown | week1~week7 教学 Notebook |
| 测试 | 20+ | ~3,000 | unit/, integration/ |
| 总计 | ~80+ | ~13,000+ | Python 为主,注释完整 |
| 场景 | 适配理由 | 如何使用 |
|---|---|---|
| AI 工程学习 | 7 周渐进式架构,从零到生产,每一步都有代码和笔记 | Fork 仓库,按 Week 顺序学习 |
| 企业知识库搭建 | 已有完整的文档摄取 → 索引 → 检索 → 问答链路 | 替换 arXiv 抓取为企业文档抓取 |
| 科研论文助手 | 原生支持 arXiv,可直接用于团队文献检索 | 配置领域关键词过滤器 |
| 内部 Agent 平台 | LangGraph 架构可直接扩展为多 Agent 系统 | 在 services/agents/ 新增节点与工具 |
| RAG 性能基准测试 | 内置 Langfuse 追踪,可量化不同分块/检索策略的效果 | 使用 tests/evals 自定义评估集 |
| 教学与培训 | Notebook + 博客 + 可运行代码三件套 | 用于企业内训或高校课程 |
原版 arXiv RAG
│
┌─────────────┼─────────────┐
▼ ▼ ▼
替换数据源 替换LLM 替换前端
(企业文档/维基/ (OpenAI/ (Web App/
内部 Confluence Anthropic Slack/Discord
/ PDF 共享盘) / DeepSeek) Bot 等)
具体改造路径:
src/services/arxiv/ 下的抓取逻辑 → 对接 Confluence API / SharePoint / Notion / OSS 文档src/services/indexing/text_chunker.py → 针对特定文档格式(法律条文/代码库/小说)定制分块src/services/ollama/ 或新增 OpenAI/Anthropic/DeepSeek 客户端(langchain 已有统一抽象)src/services/agents/nodes/ 新增自定义节点(例如 "代码执行"、"网络搜索")src/gradio_app.py,用 Next.js / Vue 对接 /api/v1/stream 接口| 维度 | 评分 | 说明 |
|---|---|---|
| 教学价值 | ★★★★★ | 7 周渐进式架构演进,非常适合学习生产级 RAG 的构建思路 |
| 工程质量 | ★★★★☆ | Docker 多阶段构建、uv 依赖、健康检查、中间件、配置管理都很规范 |
| 功能完整度 | ★★★★☆ | 覆盖数据管道 → 搜索 → RAG → Agent → 可观测性全链路 |
| 代码可读性 | ★★★★☆ | 分层清晰,函数命名直观,注释与 docstring 完整 |
| 可扩展性 | ★★★★☆ | 模块化设计,替换任意组件都只需修改对应目录 |
| 可运行性 | ★★★★☆ | docker compose up 即可跑通(若不配置 API Key 则走降级路径) |
| 创新点 | ★★★☆☆ | Agentic RAG 流程设计较扎实,LangGraph 使用规范 |
关键优点具体展开:
"先基础后增强"的方法论正确 — 很多教程直接上向量库,忽略 BM25 的重要性。本课程 Week 3 先教 BM25,Week 4 才引入向量混合搜索,符合真实工程实践。
完整的生产工程实践 — 不同于 notebook 里的 demo,这个项目包含了:Docker Compose 多服务编排、健康检查、数据库迁移、异步 API、流式响应、缓存、追踪、测试(testcontainers)、pre-commit 等一整套工程化要素。
可切换的依赖策略 — Embedding、LLM、缓存都有降级路径(Jina → sentence-transformers 本地,Ollama → OpenAI API),不会因为缺少某个 API Key 就跑不起来。
LangGraph 的教科书级使用 — Agentic RAG 的图结构(Guardrail → Retrieve → Evaluate → Rewrite ↔ Generate)展示了 LangGraph 真正的价值:可循环、可条件分支的决策流,而不是简单的 LinearChain。
文档与素材极其丰富 — 每周一篇 Substack 深度文章 + 一套 Notebook + 一套完整代码,对自学者非常友好。
| 问题 | 严重度 | 说明与建议 |
|---|---|---|
| Windows 原生支持不足 | 中 | compose 中部分路径映射(如 Airflow 的 user: "50000:0")在 Windows 上需要注释掉,建议在 README 中补充 Windows 部署说明 |
| 本地推理对硬件要求高 | 中 | 使用 Ollama 跑 llama3 7B 需要 8GB+ 内存,且速度较慢。建议在 README 中更明确标注 "无 GPU 机器建议使用 OpenAI API / Anthropic Claude 作为替代" |
| 缺少生产部署文档 | 中 | 本地 Docker Compose 运行没问题,但缺少 K8s Helm Chart / 生产部署指南,SSL/TLS、反向代理、WAF 配置需要自行摸索 |
| 多租户与权限缺失 | 中 | 当前为单租户设计(用户共享同一 PostgreSQL),要用于企业内部需要自行增加用户表、权限中间件 |
| 中文语料适配有限 | 中 | 默认 Embedding 模型(Jina v2 Base English)对中文效果一般,Prompt 模板也是英文的。建议增加:Jina 中文模型 / bge-m3 中文模型支持,中文系统 Prompt |
| 评分阈值硬编码 | 低 | Agentic RAG 中的相关性阈值(0.7)在 config 里定义不错,但不同主题的论文可能需要不同阈值,可考虑按领域配置 |
| RRF 融合权重固定 | 低 | 混合搜索使用固定的 RRF 权重,建议开放为可配置项,并增加权重搜索(如 "0.3 BM25 + 0.7 向量" vs "0.7 BM25 + 0.3 向量")的 A/B 测试 |
| 缺少向量化预热 | 低 | 首次 Embedding 调用较慢(模型加载开销),建议在 startup 事件中预热一次空向量化 |
| Telegram Bot 仅提供文本交互 | 低 | Week 7 的 Telegram Bot 只实现了文本问答,未实现 "流式输出"、"文档引用展开" 等高级功能 |
| 测试覆盖主要集中在单元测试 | 低 | 端到端测试(真的跑通 "抓取 → 索引 → 检索 → 回答")较少,建议补充一条 golden dataset 的 e2e smoke test |
| 维度 | 本项目 | LangChain 官方 RAG 模板 | LlamaIndex Starter | 纯 LangGraph Agent 教程 |
|---|---|---|---|---|
| 教学深度 | 7 周,渐进式 | 单篇教程 | 单篇教程 | 单篇教程 |
| 工程完备度 | Docker + 多服务 + 测试 | 单文件 demo | 单文件 demo | 单文件 demo |
| 包含数据管道 | ✅ Airflow DAG | ❌ | ❌ | ❌ |
| 包含关键词搜索 | ✅ OpenSearch BM25 | ❌(直接向量) | ❌(直接向量) | ❌(直接向量) |
| 可观测性 | ✅ Langfuse | ❌ | ❌ | 可选 |
| 缓存层 | ✅ Redis | ❌ | ❌ | ❌ |
| Agentic RAG | ✅ LangGraph 完整流程 | ❌ | ❌ | ✅ |
| 本地运行 | ✅ Docker Compose | ✅ | ✅ | ✅ |
| 代码量(LOC) | ~13,000+ | ~500 | ~300 | ~800 |
| 适合人群 | 中高级工程师,希望系统学习 | 初学者,希望快速跑通 | 初学者 | 已有基础,希望学习 LangGraph |
Production Agentic RAG Course 是目前 GitHub 上最完整的 "从 0 到生产级" Agentic RAG 教学项目之一。 它的核心价值在于:
学习建议:
src/routers/ask.py 和 src/services/agents/agentic_rag.py,再按需要深入其他模块与前几期分析的项目(opentalking / MoneyPrinterTurbo / train-llm-from-scratch / project-nomad / Headroom)的定位对比:
| 项目 | 定位 | 与本项目关系 |
|---|---|---|
| Headroom | LLM 上下文压缩中间件 | 可作为本项目的 Prompt 压缩层(压缩 10-30KB 文档到 2-3KB) |
| opentalking | 端到端语音对话系统 | 可替换本项目的 Gradio / Telegram 前端,实现语音交互 |
| MoneyPrinterTurbo | 图文视频自动化生成 | 应用层产品,可复用本项目的 Agent 框架做内容策划 |
| train-llm-from-scratch | 模型训练 | 可用于训练本项目的领域特定 Embedding 或 Reranker 模型 |
| project-nomad | 通用 Agent 框架 | 可作为本项目 Week 7 Agent 的替代/扩展方案 |
可以看到,本项目(Production Agentic RAG Course)更像一个 "脚手架+教学" 混合项目,它不是最快、最准、最强大的 RAG 系统,但它是你从"看懂 RAG"到"写出生产级 RAG"的最佳入门路径。
参考链接
- 项目主页:https://github.com/jamwithai/production-agentic-rag-course
- 作者博客:https://jamwithai.substack.com/
- Week 7 Agentic RAG 文章:https://jamwithai.substack.com/p/agentic-rag-with-langgraph-and-telegram
- LangGraph 官方文档:https://langchain-ai.github.io/langgraph/
- OpenSearch BM25 参考:https://opensearch.org/docs/latest/query-dsl/full-text/bm25/
- Jina Embeddings:https://jina.ai/embeddings/
- RRF(Reciprocal Rank Fusion)算法说明:https://plg.uwaterloo.ca/~gvcormac/cormacksigir09-rrf.pdf
此内容由惯性聚合(RSS阅读器)自动聚合整理,仅供阅读参考。 原文来自 — 版权归原作者所有。