fix: CLI 路径检查改用 is_safe_cli_path(允许绝对路径),更新文档
This commit is contained in:
@@ -4,14 +4,14 @@ This file provides guidance to Claude Code (claude.ai/code) when working with co
|
||||
|
||||
## 项目概述
|
||||
|
||||
Markdown 文档向量数据库 — 将 .md 文件分块 → 嵌入 → 存入 ChromaDB,通过 FastAPI HTTP 或 CLI 提供语义检索。
|
||||
文档向量数据库 — 将 .md/.txt/.pdf/.html/.epub 文件分块 → 嵌入 → 存入 ChromaDB,通过 FastAPI HTTP 或 CLI 提供语义检索。
|
||||
|
||||
## 常用命令
|
||||
|
||||
```bash
|
||||
```Shell
|
||||
# --- 安装与测试 ---
|
||||
uv sync # 安装依赖(lockfile 已锁定 CUDA torch)
|
||||
uv run pytest tests/ -v # 全部测试 (115+ 个)
|
||||
uv run pytest tests/ -v # 全部测试 (120 个)
|
||||
uv run pytest tests/test_api.py -v # 单个测试模块
|
||||
uv run pytest tests/ -v -k "test_search" # 按名称过滤
|
||||
|
||||
@@ -36,6 +36,7 @@ uv run python scripts/ingest_obsidian.py
|
||||
│ ├── db.py # VectorDB: 线程安全的 ChromaDB 封装
|
||||
│ ├── embedder.py # 策略模式: LocalEmbedder / OpenAIEmbedder / DashscopeEmbedder
|
||||
│ ├── ingest.py # DocumentIngestor: 按扩展名自动选择 Splitter
|
||||
│ ├── security.py # 路径遍历防护 (is_safe_path + is_path_within_workspace)
|
||||
│ ├── search.py # Searcher: 语义检索 + 源文件管理
|
||||
│ └── splitters/ # 文档分块器包
|
||||
│ ├── base.py # Splitter(Protocol) + BaseTextSplitter(ABC)
|
||||
@@ -43,6 +44,7 @@ uv run python scripts/ingest_obsidian.py
|
||||
│ ├── text.py # TextSplitter: 纯文本段落切分
|
||||
│ ├── pdf.py # PDFSplitter: pymupdf 提取文字
|
||||
│ ├── html.py # HTMLSplitter: bs4 去标签
|
||||
│ ├── epub.py # EPUBSplitter: ebooklib 提取章节
|
||||
│ └── registry.py # 扩展名 → Splitter 自动选择
|
||||
|
||||
server/ # FastAPI HTTP 层
|
||||
@@ -55,7 +57,7 @@ cli/main.py # Typer CLI,5 个命令 + --config 选项
|
||||
|
||||
**数据流**: 文件 → `get_splitter(path)` 自动选择 → `Splitter.split()` → `batch_embed()` → `ChromaDB collection.add()` → `Searcher.search()`
|
||||
|
||||
**支持的格式**: `.md` / `.txt` / `.pdf` / `.html` — 安装可选依赖: `uv sync --extra all`
|
||||
**支持的格式**: `.md` / `.txt` / `.pdf` / `.html` / `.epub` — 安装可选依赖: `uv sync --extra all`
|
||||
|
||||
**依赖方向**: `config` ← `db` ← `embedder` ← `ingest`/`search` ← `server`/`cli`
|
||||
|
||||
@@ -90,7 +92,7 @@ cli/main.py # Typer CLI,5 个命令 + --config 选项
|
||||
|
||||
- **API Key**: 环境变量 `MD_VECTOR_API_KEY` → `verify_api_key` 依赖注入到 ingest/search/delete 端点;未设置则跳过
|
||||
- **速率限制**: `RateLimiter` 中间件,默认 60s 窗口内最多 30 请求
|
||||
- **路径遍历防护**: `_is_safe_path()` 拒绝绝对路径和 `..` 穿越
|
||||
- **路径遍历防护**: `is_path_within_workspace()` 拒绝绝对路径、`..` 穿越和目录外访问
|
||||
- **错误信息**: 500 返回通用消息,详细错误记入 `logger.exception`
|
||||
|
||||
### 配置系统 (config.py)
|
||||
@@ -118,15 +120,16 @@ cli/main.py # Typer CLI,5 个命令 + --config 选项
|
||||
|
||||
## 已入库知识库
|
||||
|
||||
| 集合名 | 来源 | 文件数 | chunks | 说明 |
|
||||
|--------|------|--------|--------|------|
|
||||
| `novel_taohou` | `D:\Code\doing_exercises\exercise\Novel\我有太后罩着,你们有什么\原有章节剧情` | 220 | 670 | 小说章节(GPU bge-small-v1.5) |
|
||||
| `obsidian_blog` | `D:\Code\Obsidian` | 51 | 3,611 | 博客笔记(GPU bge-small-v1.5) |
|
||||
| `default` | 测试文件 | 2 | ~30 | test-guide.md + stdin-doc.md |
|
||||
| 集合名 | 来源 | 文件数 | chunks | 说明 |
|
||||
| ----------------- | -------------------------------------------------------------------------------- | ------ | ------ | ------------------------------ |
|
||||
| `novel_taohou` | `D:\Code\doing_exercises\exercise\Novel\我有太后罩着,你们有什么\原有章节剧情` | 220 | 670 | 小说章节(GPU bge-small-v1.5) |
|
||||
| `obsidian_blog` | `D:\Code\Obsidian` | 51 | 3,611 | 博客笔记(GPU bge-small-v1.5) |
|
||||
| `default` | 测试文件 | 2 | ~30 | test-guide.md + stdin-doc.md |
|
||||
|
||||
搜索时务必用 `-C` 指定集合,否则只会搜到 default 中的测试数据。
|
||||
|
||||
**小说搜索示例**:
|
||||
|
||||
```bash
|
||||
uv run md-vector-db search "张莽和孙太后的关系" -k 3 -C novel_taohou
|
||||
uv run md-vector-db search "抄家事件" -k 5 -C novel_taohou
|
||||
@@ -149,6 +152,7 @@ index-strategy = "unsafe-best-match" # 允许跨源查找
|
||||
**不要删除 `[tool.uv]` 配置**,否则 `uv sync` 会重新解析为 CPU 版 torch。
|
||||
|
||||
### MarkdownSplitter 边界情况
|
||||
|
||||
`_split_single_paragraph` 中,当段落分隔符(。!?等)距 chunk 起点 < overlap(100) 时,
|
||||
`start` 会回退为负数,Python `str.rfind` 的负索引会绕回文本末尾,造成死循环。
|
||||
此 bug 已被修复(`start = max(start + 1, next_start)`),但给超长段落测试时需留意类似问题。
|
||||
|
||||
Reference in New Issue
Block a user