Skip to content

highkay/stupidsimplerag

Repository files navigation

stupidsimplerag

专用、高效、节省资源的单机 RAG:重预处理,轻运行时。

入库阶段通过 LLM 把原始文档转成“富语义切片”(摘要 / 表格叙述 / 关键词),查询阶段使用 Qdrant 混合检索(Dense + Sparse)+ 可选 Rerank + 时间衰减,兼顾质量与成本。

架构与能力

  • FastAPI 无状态服务,内置 1 小时 TTLCache 查询缓存。
  • 入库 ETL:chonkie 切分 + LLM 三合一分析 + metadata 注入。
  • 检索链路:Hybrid Retrieval -> 可选 Rerank -> 内容过滤 -> 关键词过滤 -> 时间衰减。
  • 存储:单集合 Qdrant(Dense text-dense + Sparse BM42)。
  • 前端:内置 HTMX + Jinja2 控制台(仪表盘、上传、查询、文档管理)。

项目结构

/stupidsimplerag
├── app/
│   ├── __init__.py              # 自动加载 .env + 初始化日志
│   ├── main.py                  # FastAPI 路由(API + UI)
│   ├── core.py                  # Qdrant、检索引擎、Rerank、后处理器
│   ├── ingest.py                # 文档分析与切分
│   ├── models.py                # Pydantic 请求/响应模型
│   ├── openai_utils.py          # OpenAI 兼容配置与 LLM 包装
│   ├── logging_config.py        # Loguru/stdlib 日志桥接
│   ├── templates/               # Jinja2 页面与 HTMX partial
│   └── static/                  # CSS/Favicon
├── offline_ingest.py            # 离线批量入库脚本
├── reset_qdrant.py              # 危险:删除并重建集合
├── preload_models.py            # 预下载 FastEmbed 稀疏模型
├── test/                        # 集成与功能测试
├── Dockerfile
├── docker-compose.yml
└── AGENTS.md

快速启动

git clone <repo>
cd stupidsimplerag
cp .env.example .env
docker compose up -d

默认 docker-compose.yml 使用镜像 highkay/stupidsimplerag:latest

  • API: http://localhost:8005(容器内 8000)
  • Qdrant: http://localhost:6333

本地开发(不走容器):

pip install -r requirements.txt
uvicorn app.main:app --reload

HTTP API

入库

Endpoint Method 说明
/ingest POST 单文件入库(multipart/form-data
/ingest/batch POST 批量入库(files 多字段)
/ingest/text POST 直接上传文本(application/json

/ingest/ingest/batch

  • 支持 .md / .txt
  • force_update(可选):true 时先删同名文档再重建
  • scope(可选):逻辑命名空间,作为文档身份的一部分写入 metadata
  • 可选请求头 X-File-Mtime:支持 Unix 时间戳(秒/毫秒)或 ISO 时间,按 APP_TIMEZONE(或 TZ)归一为日期

/ingest/text 请求体:

{
  "content": "# 文档正文",
  "filename": "optional.md",
  "force_update": false,
  "scope": "reports/2025"
}

查询与检索

Endpoint Method 说明
/chat POST 标准检索 + 可选生成
/chat/lod POST 两阶段 LOD 检索(先选文档,再聚焦生成,支持 filename/filename_contains 过滤)

/chat 支持字段:

  • query(必填)
  • start_date / end_date
  • filename(精确匹配)
  • filename_contains(不区分大小写模糊匹配)
  • keywords_any / keywords_all
  • scope
  • skip_rerank(跳过重排)
  • skip_generation(仅返回切片,不调用生成)

/chat/chat/lod 的响应 sources[] 会返回 filename/date/score/keywords/text/scope, 其中 scope 从切片 metadata 透传;无该字段时为 null

示例:

curl -X POST http://localhost:8000/chat \
  -H "Content-Type: application/json" \
  -d '{
    "query": "英伟达最新财报表现",
    "start_date": "2025-01-01",
    "keywords_any": ["NVDA", "GPU"],
    "skip_generation": true
  }'

文档管理

Endpoint Method 说明
/documents GET 列出文档(按 filename + scope 聚合)
/documents/{filename} DELETE 删除指定文档切片;可选查询参数 scope,未传时仅删除无 scope 文档

Web 控制台

页面/接口 说明
/ Dashboard(Qdrant 状态、缓存状态、配置快照)
/ui/upload 单文件上传页面
/ui/upload/batch 批量上传页面
/ui/chat 查询页面
/ui/documents 文档列表 partial
/ui/documents/{filename} 删除文档(HTMX)

说明:UI 表单默认 accept=.md,但后端 API 实际支持 .md.txt

关键实现细节(与代码一致)

  1. 去重与幂等
  • doc_hash = sha256(content)
  • 若同一 scope 内已存在相同 doc_hash 且未 force_update,入库返回 status=skipped
  • 节点 ID 使用 md5(doc_hash + scope + chunk_idx),避免跨 scope 冲突。
  • scope 参与文档身份;同内容可在不同 scope 中并存。
  1. 检索后处理顺序
  • APIReranker(可跳过)
  • ContentFilterPostprocessor
  • KeywordFilterPostprocessor
  • TimeDecayPostprocessor
  1. Rerank 协议兼容
  • RERANK_API_URL 包含 /rerank:按 rerank endpoint 协议调用。
  • 否则按 OpenAI Chat Completions 协议调用重排模型。
  1. 缓存行为
  • /chat 结果使用 TTLCache(1h)。
  • 缓存键包含 query、日期范围、文件过滤、关键词过滤、skip 标志、scope。
  • 任一入库接口成功写入新切片后会清空查询缓存。
  • /chat/lod 当前不缓存。
  1. 时区基线
  • 应用统一使用 APP_TIMEZONE(回退 TZ,默认 Asia/Shanghai)。
  • 时间戳解析、/ingest/text 默认日期、时间衰减均按同一时区计算。
  • 依赖 tzdata 保证无系统 IANA 时区数据库环境下的行为一致性。

配置说明(.env)

核心配置

  • LLM_MODEL, OPENAI_API_KEY, OPENAI_API_BASE
  • EMBEDDING_MODEL, EMBEDDING_API_KEY, EMBEDDING_API_BASE, EMBEDDING_DIM
  • RERANK_API_URL, RERANK_API_KEY, RERANK_MODEL
  • QDRANT_HOST, QDRANT_PORT, QDRANT_URL, QDRANT_API_KEY, COLLECTION_NAME
  • APP_TIMEZONE(默认 Asia/Shanghai)、TZ(容器系统时区,建议与 APP_TIMEZONE 一致)

检索与策略

  • TOP_K_RETRIEVAL
  • TOP_N_RERANK
  • FINAL_TOP_K
  • SPARSE_TOP_K
  • TIME_DECAY_RATE

并发 / 重试 / 超时(高级)

  • LLM_CONTEXT_WINDOW, LLM_CONCURRENCY, LLM_MAX_RETRIES, LLM_RETRY_BACKOFF
  • EMBEDDING_MAX_RETRIES, EMBEDDING_RETRY_BACKOFF
  • RERANK_TIMEOUT, RERANK_MAX_RETRIES, RERANK_RETRY_BACKOFF, RERANK_RETURN_DOCUMENTS
  • INSERT_BATCH_SIZE, INGEST_INSERT_MAX_RETRIES, INGEST_INSERT_RETRY_BACKOFF
  • QUERY_MAX_RETRIES, QUERY_RETRY_BACKOFF
  • BATCH_INGEST_CONCURRENCY, BATCH_MAX_FILES
  • QDRANT_CLIENT_TIMEOUT

日志

  • APP_LOG_LEVEL(优先)
  • LOG_LEVEL

运维脚本

  1. offline_ingest.py
  • 递归导入目录下 .md/.txt 或单文件。
  • 支持 --batch-size--skip-completed--progress-file--max-retries--dry-run
  • 批量模式对超时采用指数退避重试。
  1. reset_qdrant.py
  • 删除并重建集合(危险操作)。
  • 默认会交互确认;-y 跳过确认。
  1. preload_models.py
  • 提前下载 FastEmbed 稀疏模型到 FASTEMBED_CACHE_PATH

测试

pytest -q

当前测试构成:

  • test/test_features_scope.py:Mock 测试(scope 透传、LOD 路由)。
  • test/test_features_scope.py 额外覆盖 scope 去重、文档列表与 scoped 删除行为。
  • test/test_offline_ingest.py:离线批量入库脚本的批次结果处理测试。
  • test/test_api.py:真实链路测试(依赖可用的 LLM/Embedding/Qdrant)。

提示:test/conftest.py 会把 COLLECTION_NAME 改为 pytest_integration_test,避免污染默认集合。

Docker 与 CI

  • Dockerfile 使用 python:3.13-slim,启动命令为 Gunicorn + Uvicorn worker。
  • 镜像内默认 TZ=Asia/Shanghai,并安装 tzdatadocker-compose 同步为 api/qdrant 注入 TZ
  • 镜像构建阶段会执行 preload_models.py 预热 BM42。
  • GitHub Actions(.github/workflows/docker-publish.yml)在 main 相关文件变更时自动推送镜像:
    • highkay/stupidsimplerag:latest
    • highkay/stupidsimplerag:<commit_sha>

关联文档

  • 维护者/代理协作规则与代码约束:AGENTS.md

About

简单,低开销,适合金融事件和信息的rag

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors

Languages