7.5 KiB
7.5 KiB
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 — 嵌入层
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.5api模式:兼容 OpenAI/DashScope/硅基流动(OpenAI 协议)- 切换方式:修改
config.yaml中的embed.mode
4.2 ingest.py — 文档入库
分块策略(混合切分):
- 按 Markdown 标题(
#/##/###)拆分章节 - 若章节超过 1000 字符,按段落边界(
\n\n)继续拆分 - 每个 chunk 保留元数据:
source_file,section_title,heading_level,chunk_index
入库流程:
Markdown 文件 → 读取 → 提取标题结构 → 分块
→ 逐块 embed → ChromaDB collection.add()
去重: 同一文件重复入库时,先删除旧 chunks 再重新插入(以 source_file 为键)。
4.3 search.py — 检索
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 — 数据库层
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 |
健康检查 |
请求/响应示例
入库:
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" }
检索:
POST /api/v1/search
{
"query": "如何配置向量数据库",
"top_k": 10
}
→ {
"results": [
{
"content": "...匹配片段...",
"source_file": "setup-guide.md",
"section_title": "向量数据库配置",
"heading_level": 2,
"score": 0.923
}
]
}
启动方式
# 嵌入式模式(直接调用 core 模块)
python -c "from src.core.search import search; print(search('关键词'))"
# HTTP 服务模式(供其他项目调用)
uv run scripts/serve.py --port 8000
6. CLI 工具
# 入库单个文件
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. 配置设计
# 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. 依赖
[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. 自检清单
- 无 TBD/TODO 占位符
- 模块间接口定义清晰(core/server/cli 分层)
- 功能范围明确(入库、检索、CLI、HTTP API)
- 无内部矛盾(本地模型+API 双模、嵌入+服务双模)
- 已确定分块策略(混合切分:标题+段落)