# langchain-study
**Repository Path**: mkee/langchain-study
## Basic Information
- **Project Name**: langchain-study
- **Description**: LangChain + LangGraph 开发本地知识库
- **Primary Language**: Unknown
- **License**: MulanPSL-2.0
- **Default Branch**: master
- **Homepage**: None
- **GVP Project**: No
## Statistics
- **Stars**: 0
- **Forks**: 1
- **Created**: 2026-03-03
- **Last Updated**: 2026-07-18
## Categories & Tags
**Categories**: Uncategorized
**Tags**: None
## README
# LangChain RAG 系统
基于 LangGraph + LangChain 集成阿里云通义千问(Qwen)的检索增强生成(RAG)系统,向量数据库采用 Chroma。
## 功能特性
- **文档管理**:创建/加载本地知识库,添加、查看、删除文档
- **智能检索**:混合检索(稠密向量 + BM25 稀疏检索),重排序优化
- **RAG 问答**:基于检索结果生成回答(RAG 链),多轮检索反思机制
- **纯检索**:无需 LLM,仅返回检索结果
- **上下文压缩**:过滤低相关文档,压缩过长内容
- **RAG 评估**:忠实度、答案相关性、上下文召回率三维评估
- **短期记忆**:对话窗口管理,超出窗口自动摘要压缩
- **长期记忆**:自动提取用户偏好和实体信息,持久化存储
- **本地调试**:工作流执行追踪器,可视化节点执行过程
## 系统架构
```mermaid
flowchart TB
subgraph User["用户层"]
UI[Web 页面]
Q[查询输入]
end
subgraph Memory["记忆系统"]
STM[短期记忆
对话窗口管理]
LTM[长期记忆
偏好/实体提取]
MEM_STORE[(记忆存储)]
end
subgraph Retrieval["检索层"]
DR[稠密检索
Chroma 向量]
SR[稀疏检索
BM25]
HR[混合检索
加权融合]
RR[重排序
Cross-encoder]
CC[上下文压缩]
end
subgraph Workflow["RAG 工作流 (LangGraph)"]
RET[检索文档]
FMT[格式化文档]
RFL[反思]
DEC{should_continue}
GEN[生成答案]
end
subgraph Eval["评估层"]
EVAL[RAG 评估
忠实度/相关性/召回率]
end
subgraph Storage["数据层"]
CHROMA[(Chroma
向量数据库)]
MEM_STORE2[(长期记忆
向量存储)]
PROMPTS[(提示词模板
prompts.yaml)]
end
Q --> UI
UI -->|用户问题| STM
UI -->|用户问题| LTM
STM -->|对话历史上下文| RET
LTM -->|偏好/实体上下文| RET
RET -->|查询| HR
DR --> CHROMA
HR --> DR
HR --> SR
HR -->|融合结果| RR
RR -->|重排序结果| CC
CC -->|压缩后文档| RET
RET --> FMT
FMT --> RFL
RFL --> DEC
DEC -->|继续检索| RET
DEC -->|生成答案| GEN
GEN --> EVAL
EVAL -->|评估结果| UI
GEN -->|回答| UI
GEN -->|提取信息| LTM
LTM --> MEM_STORE2
PROMPTS --> RFL
PROMPTS --> GEN
PROMPTS --> EVAL
```
### 查询流程
```mermaid
sequenceDiagram
participant U as 用户
participant UI as Web 页面
participant M as 记忆系统
participant R as 检索层
participant W as RAG 工作流
participant E as 评估层
participant S as 存储层
U->>UI: 输入问题
UI->>M: 获取记忆上下文
M-->>UI: 返回短期/长期记忆
UI->>R: 执行混合检索
R->>S: 稠密检索 + BM25
S-->>R: 返回文档
R->>R: 重排序
R->>R: 上下文压缩
R-->>UI: 返回相关文档
UI->>W: 启动 RAG 工作流
W->>W: 检索 → 格式化 → 反思
alt 需要继续检索
W->>R: 改进查询再检索
else 生成答案
W->>W: 生成最终回答
W->>E: 自动评估
E-->>UI: 评估结果
W-->>UI: 返回回答
UI->>M: 存储对话记忆
UI->>M: 提取长期记忆
end
UI-->>U: 显示结果
```
## 技术栈
- **LLM**: 阿里云通义千问 (Qwen)
- **工作流引擎**: LangGraph
- **向量数据库**: Chroma
- **框架**: LangChain, FastAPI
- **前端**: HTML + Jinja2 模板
- **检索增强**: rank_bm25 (稀疏检索), sentence-transformers (重排序)
## 环境配置
### 1. 安装依赖
```bash
pip install -r requirements.txt
```
### 2. 配置 API 密钥
**推荐方式:使用 .env 文件**(更安全,不会提交到 Git)
1. 复制环境变量模板
```bash
copy env_template.txt .env
```
2. 编辑 `.env` 文件,填入真实的 API 密钥:
```
DASHSCOPE_API_KEY=your-api-key-here
```
获取 API 密钥:https://dashscope.console.aliyun.com/
### 3. 启动服务
```bash
python main.py
```
或使用 uvicorn:
```bash
uvicorn app:app --host 0.0.0.0 --port 8000 --reload
```
服务启动后访问:http://localhost:8000
## 项目结构
```
.
├── app.py # FastAPI 应用入口
├── config.py # 配置文件
├── main.py # 服务启动入口
├── core/ # 核心模块
│ ├── __init__.py
│ ├── clients.py # LLM、Embedding、向量库客户端
│ └── prompt_manager.py # 提示词管理器
├── services/ # 业务服务
│ ├── __init__.py
│ ├── rag_service.py # RAG 工作流服务(LangGraph)
│ ├── document_service.py # 文档管理服务
│ ├── retrieval.py # 检索后处理模块(混合检索、重排序、压缩)
│ ├── evaluator.py # RAG 评估模块(忠实度、相关性、召回率)
│ ├── memory.py # 短期记忆模块(对话窗口、摘要压缩)
│ ├── long_term_memory.py # 长期记忆模块(偏好、实体提取与存储)
│ ├── debug_tracer.py # 本地调试追踪器
│ └── debug_run.py # 调试运行脚本
├── api/ # API 路由
│ ├── __init__.py
│ └── routes.py
├── templates/ # HTML 模板
│ ├── index.html
│ ├── document_detail.html
│ └── prompts/
│ └── prompts.yaml # 提示词模板配置
├── .env # 环境变量(API 密钥)
├── env_template.txt # 环境变量模板
├── requirements.txt # 依赖列表
└── .gitignore # Git 忽略配置
```
## 配置说明
在 `.env` 文件中可以配置以下选项:
| 配置项 | 说明 | 默认值 |
|--------|------|--------|
| `DASHSCOPE_API_KEY` | 阿里云通义千问 API 密钥 | - |
| `CHUNK_SIZE` | 文档分块大小 | 1000 |
| `CHUNK_OVERLAP` | 文档分块重叠大小 | 200 |
| `DEFAULT_RETRIEVAL_K` | 默认检索数量 | 4 |
| `VECTORSTORE_PATH` | 向量数据库存储路径 | chroma_db |
| `HOST` | 服务器地址 | 0.0.0.0 |
| `PORT` | 服务器端口 | 8000 |
| `DEBUG` | 开发模式(禁用字节码缓存) | true |
| `HYBRID_RETRIEVAL_ENABLED` | 开启混合检索 | true |
| `HYBRID_DENSE_WEIGHT` | 稠密检索权重 | 0.5 |
| `RERANK_ENABLED` | 开启重排序 | true |
| `COMPRESS_ENABLED` | 开启上下文压缩 | true |
| `EVAL_ENABLED` | 开启 RAG 评估 | true |
| `MEMORY_ENABLED` | 开启短期记忆 | true |
| `MEMORY_MAX_TURNS` | 短期记忆最大轮数 | 5 |
| `LONG_TERM_MEMORY_ENABLED` | 开启长期记忆 | true |
## 使用指南
### 1. 添加文档
在页面 "添加文档到知识库" 部分:
- 输入文档内容
- 输入分类标签
- 点击 "添加文档"
### 2. 查询知识库
在页面 "知识库查询" 部分:
- 输入查询问题
- 选择查询方式:
- **RAG 链**: 基于检索结果生成回答(使用 LangGraph 工作流)
- **纯检索链**: 仅返回检索结果
- 点击 "查询"
查询结果下方会显示:
- **RAG 评估**:忠实度、答案相关性、上下文召回率三指标评分
- **工作流日志**:各节点执行过程和耗时
- **对话历史**:最近多轮对话记录(超出窗口自动压缩)
- **长期记忆**:自动提取的用户偏好和实体信息
### 3. 验证知识库
在页面 "验证知识库" 部分:
- 点击 "验证知识库状态",查看知识库中的文档数量
- 查看文档列表,包含每个文档的预览、分类和 ID
- 点击 "查看详情" 按钮,查看文档的完整内容
- 点击 "删除" 按钮,删除指定文档
### 4. 本地调试(可选)
项目提供了本地调试追踪器,用于查看 LangGraph 工作流的执行过程:
```python
from services.rag_service import get_rag_graph
from services.debug_tracer import LocalDebugTracer
# 创建调试追踪器
tracer = LocalDebugTracer(
verbose=True, # 显示详细输入输出
log_file="debug.log", # 保存日志到文件
show_llm_inputs=True, # 显示 LLM 输入
show_llm_outputs=True # 显示 LLM 输出
)
# 获取带调试追踪器的工作流
graph = get_rag_graph(tracer)
# 执行工作流
result = graph.invoke({
"question": "你的问题",
"documents": [],
"context": "",
"answer": "",
"retrieval_count": 0,
"max_retrievals": 2
})
# 打印执行摘要
tracer.print_summary()
```
或使用快捷脚本:
```bash
python -m services.debug_run
```
调试输出示例:
```
15:32:10.123 [INFO] [START] 开始执行节点: 检索文档
15:32:10.456 [INFO] [DONE] 节点完成: 检索文档 (耗时: 0.335s)
...
==================================================
📊 执行摘要
==================================================
执行节点数: 4
总耗时: 2.456s
各节点耗时:
- 检索文档: 0.335s
- 格式化文档: 0.012s
- 反思: 1.234s
- 生成答案: 0.875s
==================================================
```
## RAG 工作流说明
项目使用 LangGraph 构建 RAG 工作流,流程如下:
```
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 检索文档 │───▶│ 格式化文档 │───▶│ 反思 │
└─────────────┘ └─────────────┘ └─────────────┘
▲ │
│ ┌─────────────┐ │
└───────────┤ should_continue ├◀──────┘
└─────────────┘
│
┌────┴────┐
▼ ▼
"生成答案" "反思"
│ │
▼ ▼
┌─────────────┐
│ 生成答案 │
└─────────────┘
```
- **检索文档**: 从向量数据库检索相关文档(支持混合检索)
- **格式化文档**: 将检索到的文档格式化为上下文(支持压缩)
- **反思**: 反思检索结果,决定是否需要继续检索
- **should_continue**: 条件判断,控制工作流走向
- **生成答案**: 基于最终上下文生成回答(注入记忆上下文)
### 多轮检索机制
1. 第一轮:检索 → 格式化 → 反思 → 判断
2. 反思后如果认为需要更多文档 → 回到检索
3. 否则 → 生成答案
通过 LLM 分析检索结果,如果认为检索不够充分,会自动改进搜索关键词进行新一轮检索。
## 检索后处理
### 混合检索(稠密 + 稀疏)
融合 Chroma 稠密向量检索和 BM25 稀疏检索结果,通过加权组合提升检索质量。
### 重排序
使用 Cross-encoder 模型对检索结果进行重排序,提升与查询相关文档的排序位置。
### 上下文压缩
过滤低相关度文档,截断过长内容,减少 LLM 输入噪声。
## RAG 评估
使用 LLM-as-judge 方式,自动评估三项指标:
- **忠实度 (Faithfulness)**: 回答是否基于检索上下文,有无幻觉
- **答案相关性 (Answer Relevancy)**: 回答是否切题
- **上下文召回率 (Context Recall)**: 上下文是否覆盖了问题所需信息
评估结果以 0-10 分展示在页面,绿色/橙色/红色区分高/中/低分。
## 记忆系统
### 短期记忆(对话窗口管理)
- 维护最近 N 轮对话(默认 5 轮)
- 超出窗口时自动调用 LLM 压缩为摘要
- 新查询自动注入历史对话上下文
### 长期记忆(偏好、实体提取)
- 每次对话后自动提取用户偏好和关键实体
- 使用独立的 Chroma 向量库持久化存储
- 新查询时检索相关记忆并注入上下文
- 自动去重,避免重复存储
## 提示词模板
提示词模板保存在 `templates/prompts/prompts.yaml` 文件中:
| 模板名 | 用途 |
|--------|------|
| `rag` | RAG 回答生成 |
| `reflect` | 反思检索结果 |
| `eval_faithfulness` | 忠实度评估 |
| `eval_relevancy` | 答案相关性评估 |
| `eval_context_recall` | 上下文召回率评估 |
可以在不修改代码的情况下调整提示词内容。
## 注意事项
- `.env` 文件包含敏感 API 密钥,已加入 `.gitignore`,请勿提交到 Git
- 向量数据库存储在 `chroma_db` 目录(可通过配置修改)
- 长期记忆存储在 `memory_store` 目录(可通过配置修改)
- 确保 API 密钥有足够的调用额度
- 文档会被自动分块存储,每个分块大小为 1000 字符(可通过配置修改)
- 开发模式下禁用 Python 字节码缓存(`__pycache__`),方便调试