chore: scaffold md-vector-db project structure
This commit is contained in:
@@ -0,0 +1,6 @@
|
||||
__pycache__/
|
||||
*.pyc
|
||||
data/
|
||||
.env
|
||||
*.egg-info/
|
||||
.pytest_cache/
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
chroma:
|
||||
persist_dir: ./data
|
||||
collection_name: markdown_docs
|
||||
|
||||
embed:
|
||||
mode: local # local | api
|
||||
local_model: BAAI/bge-small-zh-v1.5
|
||||
api_base: "" # api 模式下填写
|
||||
api_key: "" # api 模式下填写
|
||||
|
||||
chunk:
|
||||
max_size: 1000 # 分块最大字符数
|
||||
overlap: 100 # 相邻块重叠字符数
|
||||
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8000
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,268 @@
|
||||
# md-vector-db 设计文档
|
||||
|
||||
**日期**: 2026-07-05
|
||||
**作者**: 刘航宇
|
||||
**状态**: 已确认
|
||||
|
||||
## 1. 项目概述
|
||||
|
||||
构建一个 Markdown 文档向量数据库,支持文档入库、嵌入、检索,并通过 HTTP API 供其他项目调用。
|
||||
|
||||
### 核心目标
|
||||
|
||||
- 支持 ~1000 篇 Markdown 文档的存储与检索
|
||||
- 混合嵌入方案:默认本地模型,可切换到 API
|
||||
- HTTP API 对外暴露检索能力
|
||||
- CLI 命令行管理工具
|
||||
|
||||
## 2. 技术栈
|
||||
|
||||
| 层 | 选型 | 理由 |
|
||||
| --------- | -------------------------------------- | -------------------------------- |
|
||||
| 语言 | Python 3.13 | 向量库生态最成熟 |
|
||||
| 向量库 | ChromaDB | 嵌入式运行,也支持 HTTP 服务模式 |
|
||||
| 嵌入模型 | `BAAI/bge-small-zh-v1.5`(本地默认) | 中文优化,仅 100MB |
|
||||
| 嵌入 API | OpenAI 兼容协议 | 可切到 DashScope/硅基流动/OpenAI |
|
||||
| HTTP 框架 | FastAPI + uvicorn | 轻量高性能 |
|
||||
| 包管理 | uv | 用户标准工具链 |
|
||||
|
||||
## 3. 目录结构
|
||||
|
||||
```
|
||||
md-vector-db/
|
||||
├── pyproject.toml
|
||||
├── config.yaml # 用户配置文件
|
||||
├── src/
|
||||
│ ├── core/
|
||||
│ │ ├── __init__.py
|
||||
│ │ ├── db.py # ChromaDB 初始化与配置
|
||||
│ │ ├── embedder.py # 嵌入模型抽象(本地/API)
|
||||
│ │ ├── ingest.py # Markdown 解析→分块→入库
|
||||
│ │ └── search.py # 检索接口
|
||||
│ ├── server/
|
||||
│ │ ├── __init__.py
|
||||
│ │ └── app.py # FastAPI 路由
|
||||
│ └── cli/
|
||||
│ ├── __init__.py
|
||||
│ └── main.py # 命令行入口
|
||||
├── data/ # ChromaDB 持久化目录
|
||||
├── md_docs/ # 待入库的 Markdown 源文件
|
||||
├── scripts/
|
||||
│ └── serve.py # 启动 HTTP 服务
|
||||
└── tests/
|
||||
├── test_embedder.py
|
||||
├── test_ingest.py
|
||||
├── test_search.py
|
||||
└── test_api.py
|
||||
```
|
||||
|
||||
## 4. 核心模块设计
|
||||
|
||||
### 4.1 embedder.py — 嵌入层
|
||||
|
||||
```python
|
||||
class Embedder:
|
||||
def __init__(self, config: EmbedConfig):
|
||||
if config.mode == "local":
|
||||
self.model = SentenceTransformer(config.local_model)
|
||||
elif config.mode == "api":
|
||||
self.client = OpenAI(base_url=config.api_base, api_key=config.api_key)
|
||||
|
||||
def embed(self, texts: list[str]) -> list[list[float]]:
|
||||
"""返回嵌入向量列表"""
|
||||
|
||||
@property
|
||||
def dimension(self) -> int:
|
||||
"""返回向量维度"""
|
||||
```
|
||||
|
||||
- `local` 模式:首次运行自动下载 `BAAI/bge-small-zh-v1.5`
|
||||
- `api` 模式:兼容 OpenAI/DashScope/硅基流动(OpenAI 协议)
|
||||
- 切换方式:修改 `config.yaml` 中的 `embed.mode`
|
||||
|
||||
### 4.2 ingest.py — 文档入库
|
||||
|
||||
**分块策略(混合切分):**
|
||||
|
||||
1. 按 Markdown 标题(`#`/`##`/`###`)拆分章节
|
||||
2. 若章节超过 1000 字符,按段落边界(`\n\n`)继续拆分
|
||||
3. 每个 chunk 保留元数据:`source_file`, `section_title`, `heading_level`, `chunk_index`
|
||||
|
||||
**入库流程:**
|
||||
|
||||
```
|
||||
Markdown 文件 → 读取 → 提取标题结构 → 分块
|
||||
→ 逐块 embed → ChromaDB collection.add()
|
||||
```
|
||||
|
||||
**去重:** 同一文件重复入库时,先删除旧 chunks 再重新插入(以 `source_file` 为键)。
|
||||
|
||||
### 4.3 search.py — 检索
|
||||
|
||||
```python
|
||||
def search(query: str, top_k: int = 10, filters: dict | None = None) -> list[SearchResult]:
|
||||
"""
|
||||
- query 嵌入 → ChromaDB 相似度搜索
|
||||
- 支持按 source_file、heading_level 过滤
|
||||
- 返回: [(content, source_file, section_title, score), ...]
|
||||
"""
|
||||
```
|
||||
|
||||
### 4.4 db.py — 数据库层
|
||||
|
||||
```python
|
||||
class VectorDB:
|
||||
def __init__(self, persist_dir: str = "./data"):
|
||||
self.client = chromadb.PersistentClient(path=persist_dir)
|
||||
|
||||
def get_or_create_collection(self, name: str) -> Collection:
|
||||
...
|
||||
```
|
||||
|
||||
- ChromaDB 数据持久化到 `data/` 目录
|
||||
- 默认 collection 名称:`markdown_docs`
|
||||
|
||||
## 5. HTTP API
|
||||
|
||||
### 端点设计
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
| ---------- | --------------------------------- | ------------------------------------- |
|
||||
| `POST` | `/api/v1/ingest` | 入库 Markdown(传文件路径或原始内容) |
|
||||
| `POST` | `/api/v1/search` | 语义检索 |
|
||||
| `GET` | `/api/v1/collections` | 列出所有文档集合 |
|
||||
| `DELETE` | `/api/v1/documents/{file_name}` | 删除指定文件的文档 |
|
||||
| `GET` | `/api/v1/health` | 健康检查 |
|
||||
|
||||
### 请求/响应示例
|
||||
|
||||
**入库:**
|
||||
|
||||
```json
|
||||
POST /api/v1/ingest
|
||||
{
|
||||
"file_path": "D:/docs/my-note.md"
|
||||
}
|
||||
// 或
|
||||
{
|
||||
"content": "# 标题\n正文内容...",
|
||||
"file_name": "my-note.md"
|
||||
}
|
||||
→ { "status": "ok", "chunks": 12, "file": "my-note.md" }
|
||||
```
|
||||
|
||||
**检索:**
|
||||
|
||||
```json
|
||||
POST /api/v1/search
|
||||
{
|
||||
"query": "如何配置向量数据库",
|
||||
"top_k": 10
|
||||
}
|
||||
→ {
|
||||
"results": [
|
||||
{
|
||||
"content": "...匹配片段...",
|
||||
"source_file": "setup-guide.md",
|
||||
"section_title": "向量数据库配置",
|
||||
"heading_level": 2,
|
||||
"score": 0.923
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
### 启动方式
|
||||
|
||||
```bash
|
||||
# 嵌入式模式(直接调用 core 模块)
|
||||
python -c "from src.core.search import search; print(search('关键词'))"
|
||||
|
||||
# HTTP 服务模式(供其他项目调用)
|
||||
uv run scripts/serve.py --port 8000
|
||||
```
|
||||
|
||||
## 6. CLI 工具
|
||||
|
||||
```bash
|
||||
# 入库单个文件
|
||||
uv run src/cli/main.py ingest path/to/file.md
|
||||
|
||||
# 入库整个目录
|
||||
uv run src/cli/main.py ingest-dir ./md_docs/
|
||||
|
||||
# 命令行搜索
|
||||
uv run src/cli/main.py search "关键词" --top-k 10
|
||||
|
||||
# 启动服务
|
||||
uv run src/cli/main.py serve --port 8000
|
||||
|
||||
# 查看统计
|
||||
uv run src/cli/main.py stats
|
||||
```
|
||||
|
||||
## 7. 配置设计
|
||||
|
||||
```yaml
|
||||
# config.yaml
|
||||
chroma:
|
||||
persist_dir: ./data
|
||||
collection_name: markdown_docs
|
||||
|
||||
embed:
|
||||
mode: local # local | api
|
||||
local_model: BAAI/bge-small-zh-v1.5
|
||||
api_base: "" # api 模式下填写
|
||||
api_key: "" # api 模式下填写
|
||||
|
||||
chunk:
|
||||
max_size: 1000 # 分块最大字符数
|
||||
overlap: 100 # 相邻块重叠字符数
|
||||
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8000
|
||||
```
|
||||
|
||||
## 8. 依赖
|
||||
|
||||
```toml
|
||||
[project]
|
||||
name = "md-vector-db"
|
||||
version = "0.1.0"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"chromadb>=0.5.0",
|
||||
"sentence-transformers>=3.0.0",
|
||||
"fastapi>=0.115.0",
|
||||
"uvicorn[standard]>=0.30.0",
|
||||
"pyyaml>=6.0",
|
||||
"markdown-it-py>=3.0.0",
|
||||
"typer>=0.12.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0",
|
||||
"httpx>=0.27.0",
|
||||
]
|
||||
```
|
||||
|
||||
## 9. 测试计划
|
||||
|
||||
| 测试 | 覆盖 |
|
||||
| -------------------- | ------------------------------- |
|
||||
| `test_embedder.py` | 本地/API 模式嵌入,维度验证 |
|
||||
| `test_ingest.py` | Markdown 解析、分块、入库、去重 |
|
||||
| `test_search.py` | 检索、元数据过滤 |
|
||||
| `test_api.py` | FastAPI 端点集成测试 |
|
||||
|
||||
目标覆盖率:80%+
|
||||
|
||||
## 10. 自检清单
|
||||
|
||||
- [X] 无 TBD/TODO 占位符
|
||||
- [X] 模块间接口定义清晰(core/server/cli 分层)
|
||||
- [X] 功能范围明确(入库、检索、CLI、HTTP API)
|
||||
- [X] 无内部矛盾(本地模型+API 双模、嵌入+服务双模)
|
||||
- [X] 已确定分块策略(混合切分:标题+段落)
|
||||
@@ -0,0 +1,31 @@
|
||||
[project]
|
||||
name = "md-vector-db"
|
||||
version = "0.1.0"
|
||||
description = "Markdown 文档向量数据库,支持语义检索"
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"chromadb>=0.5.0",
|
||||
"sentence-transformers>=3.0.0",
|
||||
"fastapi>=0.115.0",
|
||||
"uvicorn[standard]>=0.30.0",
|
||||
"pyyaml>=6.0",
|
||||
"markdown-it-py>=3.0.0",
|
||||
"typer>=0.12.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pytest>=8.0",
|
||||
"httpx>=0.27.0",
|
||||
]
|
||||
|
||||
[build-system]
|
||||
requires = ["hatchling"]
|
||||
build-backend = "hatchling.build"
|
||||
|
||||
[tool.hatch.build.targets.wheel]
|
||||
packages = ["src/"]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
pythonpath = ["src"]
|
||||
Reference in New Issue
Block a user