# 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] 已确定分块策略(混合切分:标题+段落)