cumcm-rag-mcp
# CUMCM Optimization RAG
这是一个面向全国大学生数学建模竞赛优化与决策类问题的**非官方**、可审计 RAG 工程。项目提供 Python 查询核心、受 manifest 约束的入库器、命令行工具和只读 MCP 服务;不包含竞赛题面、附件、优秀论文、扫描件、压缩包或其他未获明确公开再分发许可的材料。
本项目与案例建模仓库相互独立。案例仓库可以选择通过 MCP 调用本项目,但两者不共享源码、语料、索引或虚拟环境;案例复现也不以本项目为运行前提。
## 协作者
- [54334-bit](https://github.com/54334-bit)
- [o0enon0ok-cell](https://github.com/o0enon0ok-cell)
- yidan chen
## 当前公开数据状态
迁移前基线 manifest 有 399 条:L0 119、L1 193、L2 87。许可审计没有发现任何具备肯定公开再分发许可的记录,因此:
- `data/manifest/corpus_manifest.csv`:0 条公开原文记录,仅保留表头;
- `data/manifest/sources.csv`:399 条来源与权利元数据;
- `data/manifest/exclusions.csv`:399 条排除记录及理由;
- `data/corpus/`:不包含原语料;
- `artifacts/index/`:不包含生成索引。
这意味着仓库可以安装、校验、启动 CLI 和 MCP,但在添加并审核合法语料、构建本地索引之前不能执行真实检索。该状态是版权门禁的预期结果,不是数据丢失或程序故障。
其中 199 条迁移记录没有公开 URL,已明确标为 `source_locator_status=local_record_no_public_url`。这些记录只是本地来源台账,不能被描述为外部可独立复核的在线来源。`rag_list_sources` 会返回元数据总账并用 `available_for_index` 区分是否存在于公开 manifest;`rag_get_document` 仍严格只允许读取公开 manifest 登记的原文。
## 目录结构
```text
.
├─ src/cumcm_rag/ # 核心、入库、CLI、MCP
├─ config/ # 相对路径配置与 Codex 示例
├─ scripts/ # manifest 迁移、校验工具
├─ tests/ # 单元与 MCP stdio 集成测试
├─ data/
│ ├─ manifest/ # 公开清单、来源元数据、排除登记
│ ├─ corpus/ # 仅放已核验可再分发文本
│ └─ incoming/ # 本地待审材料;默认忽略
├─ artifacts/index/ # 可重建索引;默认忽略
├─ docs/ # 架构、治理、接入、验证与迁移说明
└─ docker/ # 容器镜像和 Compose 配置
```
## 环境与安装
要求 Python 3.11 或更高版本。推荐在项目外或项目根下自建虚拟环境;虚拟环境不会进入版本控制。
```powershell
python -m venv .venv
.\.venv\Scripts\Activate.ps1
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"
```
只运行状态、manifest 和 MCP 元数据接口不需要模型依赖。构建索引和检索时安装:
```powershell
python -m pip install -e ".[runtime]"
```
OCR/PDF 抽取工具属于本地语料准备能力,不会赋予材料再分发权:
```powershell
python -m pip install -e ".[corpus]"
```
## 最小可运行示例
源码模式:
```powershell
$env:PYTHONPATH = "$PWD\src"
python -m cumcm_rag.cli status
python -m cumcm_rag.cli health
python scripts\verify_manifest.py
```
可编辑安装后:
```powershell
cumcm-rag status
cumcm-rag sources --all --limit 5
cumcm-rag-mcp
```
普通安装或从仓库外运行时必须设置 `CUMCM_RAG_ROOT` 指向包含 `config/rag.yaml` 与 `data/manifest` 的项目/数据根目录;程序不会再把 `site-packages` 的父目录误判为项目根。
当前 `health` 会明确报告“索引缺失”,因为索引是本地生成物且公开语料白名单为空。MCP 仍可正常完成初始化、列出工具、查询状态和执行浅层健康检查。
## 添加合法语料与构建索引
只有同时满足以下条件的文本文件才能进入 `corpus_manifest.csv`:
1. `permission_status=public_redistribution_verified`;
2. `redistribution_allowed=yes`;
3. 有有效 SPDX 许可证或覆盖再分发的书面授权;
4. 来源、权利人、上游派生关系和人工复核状态完整;
5. 文件存在且 SHA-256 与登记值一致;
6. 文件位于 `data/corpus/` 内,且是允许的文本格式。
完成登记后先运行:
```powershell
python scripts\verify_manifest.py
```
再构建本地索引:
```powershell
cumcm-rag build-index
cumcm-rag health --deep
cumcm-rag search "MILP 不可行时如何诊断" --limit 5
```
索引器只读取 manifest 中 `index_default=yes` 的文件;未登记文件会使校验失败,不会被静默收录。
## MCP 与 Codex
MCP 服务暴露六个只读工具:
- `rag_search`
- `rag_get_case_context`
- `rag_get_document`
- `rag_list_sources`
- `rag_get_status`
- `rag_health`
服务入口:
```powershell
python -m cumcm_rag.mcp_server
```
示例配置见 `config/codex_config.example.toml`,详细说明见 `docs/codex-mcp.md`。示例不包含个人机器绝对路径;推荐先在目标 Python 环境中安装本项目,再让 Codex 运行模块入口。
## Docker
解析 Compose 配置:
```powershell
docker compose -f docker\compose.yaml config
```
构建并启动:
```powershell
docker compose -f docker\compose.yaml build
docker compose -f docker\compose.yaml run --rm cumcm-rag-mcp
```
容器只读挂载 `data/corpus` 和 `artifacts/index`。模型缓存在命名卷中;语料和索引不会写入镜像。
## 测试与验证
```powershell
python -m compileall -q src scripts tests
python -m pytest -q --basetemp .pytest-tmp
python scripts\verify_manifest.py
docker compose -f docker\compose.yaml config
```
完整的静态检查、MCP 验证、旧路径扫描、敏感信息扫描和环境限制见 `docs/validation.md`。
## 常见故障
- **`索引不存在或不完整`**:当前仓库不分发索引。先合法添加语料、通过 manifest 校验,再执行 `build-index`。
- **缺少 `txtai` 或 `jieba`**:安装 `.[runtime]`。浅层状态和 manifest 校验不要求它们。
- **模型无法下载**:在可联网环境预先填充模型缓存,或设置 `HF_HOME` 指向合规的本地缓存;不要提交缓存。
- **MCP 能启动但检索失败**:先调用 `rag_get_status` 和 `rag_health`。索引缺失是最常见原因。
- **Windows 临时目录拒绝访问**:给 pytest 指定项目内临时目录,如 `--basetemp .pytest-tmp`,测试后删除该目录。
- **FAISS AVX2 警告**:若随后成功回退到普通 FAISS,通常只是性能提示;仍应以真实检索结果判断功能是否正常。
## 许可、贡献与引用
原创代码和原创文档采用 Apache License 2.0。该许可证不覆盖语料元数据所指向的题面、论文、附件、网页、仓库或其他第三方材料。详见 `DATA_LICENSE.md`、`NOTICE` 和 `THIRD_PARTY_NOTICES.md`。
提交贡献前请阅读 `CONTRIBUTING.md`;安全问题按 `SECURITY.md` 私下报告;引用信息见 `CITATION.cff`。
## 已知限制
- 当前公开语料为 0,无法开箱执行语义检索;
- 旧基线中有 3 条来源记录的实际 SHA-256 与登记值不符,已保留为排除元数据,不能作为已验证证据;
- 未联网复核官方网页条款或取得第三方书面授权;
- 真实检索依赖较大的模型与 FAISS/txtai 环境,跨平台表现可能不同;
- 本项目只提供方法与检索支持,不能替代题面原文、用户数据、实际求解结果或人工版权判断。
TDQS
Scored across 6 tools
Most tools have clearly distinct roles: search, document retrieval, source listing, and case-context assembly are well separated. However, rag_get_status and rag_health overlap in purpose, both probing system/index health, which could cause occasional misselection.
All tools share the rag_ prefix and use consistent snake_case with action-oriented verbs like get, search, list, and health. The naming pattern is predictable and easy to extend.
Six tools form a tight, well-scoped surface for a RAG retrieval server: search, document access, source metadata, context assembly, and health/status checks. No tool feels redundant or unnecessary.
The retrieval side is well covered: search, document reading, source listing, case context, and health checks. Minor gaps exist around index management or ingestion, but the apparent read-only RAG purpose is largely satisfied.