feat: 第三优先级完善 — CI/CD、PyPI、pre-commit、CHANGELOG、贡献指南、基准测试、ADR
CI / Test (Python 3.13) (push) Has been cancelled
CI / Test (Python 3.13) (push) Has been cancelled
This commit is contained in:
@@ -0,0 +1,48 @@
|
||||
# CI
|
||||
name: CI
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
branches: [main]
|
||||
|
||||
jobs:
|
||||
test:
|
||||
name: Test (Python ${{ matrix.python-version }})
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
python-version: ["3.13"]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
|
||||
- name: Install dependencies
|
||||
run: uv sync --extra dev --extra all
|
||||
|
||||
- name: Run lint (ruff)
|
||||
run: uv run ruff check src/ tests/
|
||||
|
||||
- name: Run type check (mypy)
|
||||
run: uv run mypy src/ --ignore-missing-imports
|
||||
|
||||
- name: Run tests with coverage
|
||||
run: |
|
||||
uv run pytest tests/ \
|
||||
--cov=src \
|
||||
--cov-report=term-missing \
|
||||
--cov-report=xml \
|
||||
-v
|
||||
|
||||
- name: Upload coverage to Codecov
|
||||
uses: codecov/codecov-action@v5
|
||||
with:
|
||||
files: ./coverage.xml
|
||||
fail_ci_if_error: false
|
||||
@@ -0,0 +1,28 @@
|
||||
# Publish to PyPI
|
||||
name: Publish to PyPI
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v*"
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
name: Build and publish
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v5
|
||||
|
||||
- name: Build package
|
||||
run: uv build
|
||||
|
||||
- name: Publish to PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages-dir: dist/
|
||||
@@ -0,0 +1,41 @@
|
||||
# Changelog
|
||||
|
||||
所有值得注意的更改都将记录在此文件中。
|
||||
|
||||
格式基于 [Keep a Changelog](https://keepachangelog.com/zh-CN/1.0.0/),
|
||||
版本号遵循 [语义化版本](https://semver.org/lang/zh-CN/)。
|
||||
|
||||
## [Unreleased]
|
||||
|
||||
### Added
|
||||
- 混合检索(BM25 + 向量联合),HybridRetriever + SearchConfig 可配置
|
||||
- 增量入库(SHA256 文件变更追踪),CLI `--incremental` / `--force` 选项
|
||||
- Cross-Encoder 结果重排序(BAAI/bge-reranker-base)
|
||||
- Web 管理界面(Vue 3 SPA,`/admin`)
|
||||
- .docx 文档支持(markitdown)
|
||||
- 数据导出功能(JSON/CSV),CLI `export` 命令
|
||||
- Docker 部署方案 + docker-compose(含 GPU profile)
|
||||
- API 审计日志、请求体大小限制、健康检查免限速
|
||||
- GitHub Actions CI 流水线 + PyPI 发布
|
||||
- Pre-commit 钩子配置(ruff + mypy)
|
||||
- 性能基准测试(嵌入 + 检索)
|
||||
|
||||
### Changed
|
||||
- Searcher 支持 hybrid/vector 检索模式切换
|
||||
- Embedder Protocol 修复为标准写法
|
||||
- PDF/EPUB Splitter 参数名统一为 `source`
|
||||
|
||||
### Fixed
|
||||
- CORS `allow_credentials` 配置修复
|
||||
- chromadb 不同版本异常类型兼容(NotFoundError)
|
||||
|
||||
## [0.1.0] - 2026-07-05
|
||||
|
||||
### Added
|
||||
- Markdown 文档解析与语义检索
|
||||
- 多 Provider 嵌入支持(local/OpenAI/DashScope)
|
||||
- 多格式文档(.md/.txt/.pdf/.html/.epub)
|
||||
- GPU 自动检测加速
|
||||
- FastAPI HTTP API + Typer CLI
|
||||
- API Key 认证和速率限制
|
||||
- 路径遍历安全防护
|
||||
@@ -0,0 +1,54 @@
|
||||
# 贡献指南
|
||||
|
||||
## 开发环境
|
||||
|
||||
```bash
|
||||
git clone git@github.com:LHY0125/md-vector-db.git
|
||||
cd md-vector-db
|
||||
uv sync --extra dev --extra all
|
||||
uv run pre-commit install
|
||||
```
|
||||
|
||||
## 开发流程
|
||||
|
||||
1. **Fork 仓库** → 创建功能分支 `feat/xxx`
|
||||
2. **写测试**(TDD): 先在 `tests/` 下写失败测试
|
||||
3. **实现功能**: 最少代码让测试通过
|
||||
4. **运行全部测试**: `uv run pytest tests/ --cov=src -v`
|
||||
5. **确保覆盖率 ≥ 80%**: `uv run pytest tests/ --cov=src --cov-fail-under=80`
|
||||
6. **Lint 检查**: `uv run ruff check src/ tests/`
|
||||
7. **类型检查**: `uv run mypy src/ --ignore-missing-imports`
|
||||
8. **提交**: 遵循约定式提交格式
|
||||
9. **创建 PR**: 描述清楚变更内容和测试结果
|
||||
|
||||
## 提交消息格式
|
||||
|
||||
```
|
||||
<类型>: <描述>
|
||||
|
||||
<可选正文>
|
||||
```
|
||||
|
||||
类型: `feat`, `fix`, `refactor`, `docs`, `test`, `chore`, `perf`, `ci`
|
||||
|
||||
## 代码风格
|
||||
|
||||
- Python 3.13+,遵循 PEP 8
|
||||
- 类型注解覆盖所有 public API
|
||||
- 中文注释
|
||||
- 小文件原则(<800 行),函数 <50 行
|
||||
|
||||
## 添加新文档格式支持
|
||||
|
||||
1. 在 `src/core/splitters/` 下实现 Splitter Protocol
|
||||
2. 在 `src/core/splitters/registry.py` 注册扩展名
|
||||
3. 在 `pyproject.toml` 添加可选依赖
|
||||
4. 在 `tests/` 下添加测试
|
||||
5. 更新 `README.md`
|
||||
|
||||
## 运行基准测试
|
||||
|
||||
```bash
|
||||
uv sync --extra bench
|
||||
uv run pytest tests/benchmarks/ -v --benchmark-only
|
||||
```
|
||||
@@ -1,5 +1,8 @@
|
||||
# md-vector-db
|
||||
|
||||
[](https://github.com/LHY0125/md-vector-db/actions/workflows/ci.yml)
|
||||
[](https://opensource.org/licenses/MIT)
|
||||
|
||||
Markdown 文档向量数据库 — 将 Markdown 文件自动分块、嵌入、存入 ChromaDB,通过语义检索快速查找相关内容。提供 **CLI 命令行工具**和 **HTTP API** 两种使用方式供其他项目集成。
|
||||
|
||||
## 功能特性
|
||||
@@ -180,14 +183,14 @@ docker exec -it md-vector-db uv run md-vector-db ingest /app/md_docs/doc.md
|
||||
|
||||
所有命令均支持 `--config/-c`(配置文件)、`--collection/-C`(集合名,默认 `default`)。
|
||||
|
||||
| 命令 | 说明 |
|
||||
| --------------------------------- | -------------------------------------------------------- |
|
||||
| 命令 | 说明 |
|
||||
| ----------------------------------- | -------------------------------------------------------- |
|
||||
| `ingest <文件路径> --incremental` | 增量入库单文件,自动跳过未变更文件 |
|
||||
| `ingest <文件路径> --force` | 强制重新入库(忽略增量检查) |
|
||||
| `ingest-dir <目录路径>` | 递归入库目录下所有支持的文档格式 |
|
||||
| `search <查询> -k <数量> --mode` | 语义检索,`--mode hybrid\|vector`,`--json` JSON 输出 |
|
||||
| `search <查询> -k <数量> --mode` | 语义检索,`--mode hybrid\|vector`,`--json` JSON 输出 |
|
||||
| `stats` | 显示 chunks 总数、源文件列表 |
|
||||
| `export -o <文件> -f <json\|csv>` | 导出 collection 数据 |
|
||||
| `export -o <文件> -f <json\|csv>` | 导出 collection 数据 |
|
||||
| `serve -p <端口>` | 启动 HTTP 服务(默认 8000) |
|
||||
|
||||
---
|
||||
@@ -327,6 +330,16 @@ index-strategy = "unsafe-best-match" # 允许跨源查找
|
||||
|
||||
---
|
||||
|
||||
---
|
||||
|
||||
## 文档
|
||||
|
||||
- [API 参考](docs/api_reference.md)
|
||||
- [架构决策记录](docs/architecture.md)
|
||||
-
|
||||
- [贡献指南](CONTRIBUTING.md)
|
||||
- [变更日志](CHANGELOG.md)
|
||||
|
||||
## License
|
||||
|
||||
MIT
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
# md-vector-db API 参考文档
|
||||
|
||||
## REST API
|
||||
|
||||
- **Base URL**: `http://localhost:8000/api/v1`
|
||||
- **认证**: `X-API-Key` Header(取决于 `MD_VECTOR_API_KEY` 环境变量)
|
||||
- **速率限制**: 60s 窗口内最多 30 请求
|
||||
|
||||
### GET /health — 健康检查
|
||||
|
||||
无需认证。
|
||||
|
||||
```json
|
||||
{
|
||||
"status": "ok",
|
||||
"checks": {
|
||||
"chromadb": {"status": "ok", "count": 1240},
|
||||
"embedder": {"status": "ok", "dimension": 512}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### GET /collections — 列出集合
|
||||
|
||||
需 API Key。返回 `{"collections": [{"name": "...", "count": N}, ...]}`。
|
||||
|
||||
### POST /search — 语义检索
|
||||
|
||||
| 字段 | 类型 | 必填 | 约束 |
|
||||
|------|------|------|------|
|
||||
| query | string | ✅ | 1-2000 字符 |
|
||||
| top_k | int | ❌ | 1-100,默认 10 |
|
||||
| collection | string | ❌ | ≤128 字符 |
|
||||
|
||||
返回 `{"results": [...], "collection": "..."}`,每条结果含 `id`, `content`, `source_file`, `section_title`, `heading_level`, `score`。
|
||||
|
||||
### POST /ingest — 入库文档
|
||||
|
||||
| 字段 | 类型 | 必填 | 约束 |
|
||||
|------|------|------|------|
|
||||
| file_path | string | 二选一 | 安全路径 |
|
||||
| content | string | 二选一 | ≤500KB |
|
||||
| file_name | string | 推荐 | 1-255 字符 |
|
||||
| collection | string | ❌ | ≤128 字符 |
|
||||
|
||||
返回 `{"status": "ok", "chunks": N, "file": "...", "collection": "..."}`。
|
||||
|
||||
### DELETE /documents/{file_name} — 删除文档
|
||||
|
||||
查询参数: `collection` (可选)。
|
||||
|
||||
| 状态码 | 含义 |
|
||||
|--------|------|
|
||||
| 200 | 删除成功 |
|
||||
| 400 | file_name 不合法 |
|
||||
| 401 | API Key 无效 |
|
||||
| 404 | 文档不存在 |
|
||||
|
||||
## CLI 命令
|
||||
|
||||
```bash
|
||||
md-vector-db ingest <文件> --incremental --force
|
||||
md-vector-db ingest-dir <目录> -C <集合>
|
||||
md-vector-db search "<查询>" -k 10 --mode hybrid --json
|
||||
md-vector-db stats -C <集合>
|
||||
md-vector-db export -o output.json -f json
|
||||
md-vector-db serve -p 8000
|
||||
```
|
||||
@@ -0,0 +1,43 @@
|
||||
# 架构决策记录 (ADR)
|
||||
|
||||
## ADR-1: 为什么选择 ChromaDB?
|
||||
|
||||
**日期**: 2026-07-05 | **状态**: 已采纳
|
||||
|
||||
**背景**: 需要一个嵌入式向量数据库来持久化文档嵌入。
|
||||
|
||||
**候选**: ChromaDB(嵌入式 SQLite)、Qdrant(独立服务)、FAISS(纯内存)、Milvus(生产级集群)
|
||||
|
||||
**决策**: ChromaDB。零运维成本远超吞吐量考量。内置 Collection 概念映射多知识库场景。
|
||||
|
||||
**代价**: 高并发下逊于 Qdrant/Milvus。未来可透明迁移(Embedder/Searcher 已隔离 ChromaDB 依赖)。
|
||||
|
||||
---
|
||||
|
||||
## ADR-2: 为什么默认 bge-small-zh-v1.5?
|
||||
|
||||
**日期**: 2026-07-05 | **状态**: 已采纳
|
||||
|
||||
**候选**: bge-small-zh-v1.5 (512维/23M)、bge-large-zh-v1.5 (1024维/324M)、text2vec-large-chinese、m3e-base
|
||||
|
||||
**决策**: bge-small-zh-v1.5。RTX 4060 上 729 chunks 嵌入仅 1.8s,日常精度足够。高精度场景可切换 large 模型或 OpenAI API。
|
||||
|
||||
---
|
||||
|
||||
## ADR-3: 为什么采用 Protocol 而非 ABC?
|
||||
|
||||
**日期**: 2026-07-05 | **状态**: 已采纳
|
||||
|
||||
**候选**: typing.Protocol(结构化子类型)、abc.ABC(名义子类型)、Callable(丢失类型信息)
|
||||
|
||||
**决策**: Protocol。外部模块无需依赖本项目源码即可实现 Splitter/Embedder,对插件化友好。
|
||||
|
||||
---
|
||||
|
||||
## ADR-4: 为什么使用 rank-bm25 而非集成搜索引擎?
|
||||
|
||||
**日期**: 2026-07-11 | **状态**: 已采纳
|
||||
|
||||
**候选**: rank-bm25(纯 Python BM25)、Elasticsearch(外部服务)、Whoosh(纯 Python 全文搜索)
|
||||
|
||||
**决策**: rank-bm25。零运维、轻量、与现有 ChromaDB 架构匹配。在向量候选上做 BM25 重打分(而非全文索引所有文档),兼顾性能和精度。
|
||||
+23
-1
@@ -1,7 +1,21 @@
|
||||
[project]
|
||||
name = "md-vector-db"
|
||||
version = "0.1.0"
|
||||
description = "Markdown 文档向量数据库,支持语义检索"
|
||||
description = "Markdown 文档向量数据库 — 语义检索、混合检索、REST API"
|
||||
readme = "README.md"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "刘航宇", email = "3364451258@qq.com"},
|
||||
]
|
||||
keywords = ["vector-database", "semantic-search", "rag", "chromadb", "markdown"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3.13",
|
||||
"Topic :: Scientific/Engineering :: Artificial Intelligence",
|
||||
"Topic :: Text Processing :: Markup",
|
||||
]
|
||||
requires-python = ">=3.13"
|
||||
dependencies = [
|
||||
"chromadb>=0.5.0",
|
||||
@@ -15,6 +29,12 @@ dependencies = [
|
||||
"rank-bm25>=0.2.2",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/LHY0125/md-vector-db"
|
||||
Documentation = "https://github.com/LHY0125/md-vector-db#readme"
|
||||
Repository = "https://github.com/LHY0125/md-vector-db"
|
||||
Issues = "https://github.com/LHY0125/md-vector-db/issues"
|
||||
|
||||
[project.scripts]
|
||||
md-vector-db = "src.cli.main:app"
|
||||
|
||||
@@ -24,6 +44,7 @@ pdf = ["pymupdf>=1.24.0"]
|
||||
html = ["beautifulsoup4>=4.12.0"]
|
||||
epub = ["ebooklib>=0.18"]
|
||||
docx = ["markitdown>=0.1.0"]
|
||||
bench = ["pytest-benchmark>=5.0"]
|
||||
all = ["md-vector-db[pdf,html,epub,docx]", "requests>=2.31.0", "openai>=1.0.0"]
|
||||
|
||||
[build-system]
|
||||
@@ -56,3 +77,4 @@ ignore_missing_imports = true
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
pythonpath = ["src"]
|
||||
norecursedirs = ["tests/benchmarks"]
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
"""版本号管理 — 更新 pyproject.toml 中的 version."""
|
||||
import re
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def bump(part: str) -> str:
|
||||
"""递增版本号.
|
||||
|
||||
Args:
|
||||
part: "major" | "minor" | "patch"
|
||||
|
||||
Returns:
|
||||
新版本号字符串
|
||||
"""
|
||||
pyproject = Path(__file__).parent.parent / "pyproject.toml"
|
||||
content = pyproject.read_text(encoding="utf-8")
|
||||
match = re.search(r'version\s*=\s*"(\d+)\.(\d+)\.(\d+)"', content)
|
||||
if not match:
|
||||
print("错误: 未找到 version 字段", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
major, minor, patch = int(match[1]), int(match[2]), int(match[3])
|
||||
if part == "major":
|
||||
major += 1
|
||||
minor = 0
|
||||
patch = 0
|
||||
elif part == "minor":
|
||||
minor += 1
|
||||
patch = 0
|
||||
elif part == "patch":
|
||||
patch += 1
|
||||
else:
|
||||
print(f"错误: 未知的版本部分 '{part}',可选: major/minor/patch", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
new_version = f"{major}.{minor}.{patch}"
|
||||
new_content = content.replace(match[0], f'version = "{new_version}"')
|
||||
pyproject.write_text(new_content, encoding="utf-8")
|
||||
print(f"版本: {match[1]}.{match[2]}.{match[3]} → {new_version}")
|
||||
return new_version
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
if len(sys.argv) != 2:
|
||||
print("用法: python scripts/bump_version.py <major|minor|patch>")
|
||||
sys.exit(1)
|
||||
bump(sys.argv[1])
|
||||
@@ -0,0 +1,41 @@
|
||||
"""基准测试共享 fixture."""
|
||||
import pytest
|
||||
|
||||
from src.core.config import ChunkConfig, EmbedConfig
|
||||
from src.core.db import VectorDB
|
||||
from src.core.embedder import create_embedder
|
||||
from src.core.ingest import DocumentIngestor
|
||||
from src.core.search import Searcher
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def benchmark_db(tmp_path_factory):
|
||||
"""模块级共享 ChromaDB 实例."""
|
||||
persist_dir = tmp_path_factory.mktemp("bench_data")
|
||||
return VectorDB(persist_dir=str(persist_dir))
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def benchmark_embedder():
|
||||
"""模块级共享 LocalEmbedder."""
|
||||
config = EmbedConfig(mode="local", local_model="BAAI/bge-small-zh-v1.5")
|
||||
return create_embedder(config)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def benchmark_searcher(benchmark_db, benchmark_embedder):
|
||||
"""预填充数据的 Searcher."""
|
||||
ingestor = DocumentIngestor(
|
||||
benchmark_db, benchmark_embedder, "bench_collection",
|
||||
chunk_config=ChunkConfig(max_size=1000, overlap=100),
|
||||
)
|
||||
for i in range(100):
|
||||
content = (
|
||||
f"# 文档{i}\n\n"
|
||||
+ "\n\n".join(
|
||||
f"第{j}段用于基准测试。关键词: Python, Rust, GPU, 向量数据库。"
|
||||
for j in range(5)
|
||||
)
|
||||
)
|
||||
ingestor.ingest_content(content, f"bench_{i}.md")
|
||||
return Searcher(benchmark_db, benchmark_embedder, "bench_collection")
|
||||
@@ -0,0 +1,23 @@
|
||||
"""嵌入性能基准测试."""
|
||||
import pytest
|
||||
|
||||
|
||||
def test_bench_embed_single(benchmark, benchmark_embedder):
|
||||
"""单文本嵌入耗时."""
|
||||
text = "这是一段测试文本,用于测量嵌入速度。"
|
||||
benchmark(benchmark_embedder.embed, [text])
|
||||
|
||||
|
||||
def test_bench_embed_batch_32(benchmark, benchmark_embedder):
|
||||
"""批量 32 文本嵌入耗时."""
|
||||
texts = [f"测试文本第{i}条,模拟真实文档内容。" for i in range(32)]
|
||||
benchmark(benchmark_embedder.embed, texts)
|
||||
|
||||
|
||||
def test_bench_embed_batch_100(benchmark, benchmark_embedder):
|
||||
"""批量 100 文本嵌入耗时(GPU 优势显著)."""
|
||||
texts = [
|
||||
f"测试文本第{i}条。Python 通用编程语言,用于数据科学和 AI。"
|
||||
for i in range(100)
|
||||
]
|
||||
benchmark(benchmark_embedder.embed, texts)
|
||||
@@ -0,0 +1,17 @@
|
||||
"""检索性能基准测试."""
|
||||
import pytest
|
||||
|
||||
|
||||
def test_bench_search_top5(benchmark, benchmark_searcher):
|
||||
"""top_k=5 检索耗时."""
|
||||
benchmark(benchmark_searcher.search, "Python 向量数据库", top_k=5)
|
||||
|
||||
|
||||
def test_bench_search_top20(benchmark, benchmark_searcher):
|
||||
"""top_k=20 检索耗时."""
|
||||
benchmark(benchmark_searcher.search, "Rust 编程语言 GPU", top_k=20)
|
||||
|
||||
|
||||
def test_bench_search_cold_start(benchmark, benchmark_searcher):
|
||||
"""冷启动检索耗时."""
|
||||
benchmark(benchmark_searcher.search, "GPU 加速 深度学习 嵌入", top_k=10)
|
||||
@@ -1206,6 +1206,9 @@ all = [
|
||||
{ name = "pymupdf" },
|
||||
{ name = "requests" },
|
||||
]
|
||||
bench = [
|
||||
{ name = "pytest-benchmark" },
|
||||
]
|
||||
dev = [
|
||||
{ name = "httpx" },
|
||||
{ name = "mypy" },
|
||||
@@ -1240,6 +1243,7 @@ requires-dist = [
|
||||
{ name = "openai", marker = "extra == 'all'", specifier = ">=1.0.0" },
|
||||
{ name = "pymupdf", marker = "extra == 'pdf'", specifier = ">=1.24.0" },
|
||||
{ name = "pytest", marker = "extra == 'dev'", specifier = ">=8.0" },
|
||||
{ name = "pytest-benchmark", marker = "extra == 'bench'", specifier = ">=5.0" },
|
||||
{ name = "pytest-cov", marker = "extra == 'dev'", specifier = ">=5.0" },
|
||||
{ name = "python-dotenv", specifier = ">=1.2.2" },
|
||||
{ name = "pyyaml", specifier = ">=6.0" },
|
||||
@@ -1250,7 +1254,7 @@ requires-dist = [
|
||||
{ name = "typer", specifier = ">=0.12.0" },
|
||||
{ name = "uvicorn", extras = ["standard"], specifier = ">=0.30.0" },
|
||||
]
|
||||
provides-extras = ["dev", "pdf", "html", "epub", "docx", "all"]
|
||||
provides-extras = ["dev", "pdf", "html", "epub", "docx", "bench", "all"]
|
||||
|
||||
[[package]]
|
||||
name = "mdurl"
|
||||
@@ -1559,7 +1563,7 @@ name = "nvidia-cudnn-cu12"
|
||||
version = "9.1.0.70"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/9f/fd/713452cd72343f682b1c7b9321e23829f00b842ceaedcda96e742ea0b0b3/nvidia_cudnn_cu12-9.1.0.70-py3-none-manylinux2014_x86_64.whl", hash = "sha256:165764f44ef8c61fcdfdfdbe769d687e06374059fbb388b6c89ecb0e28793a6f", size = 664752741, upload-time = "2024-04-22T15:24:15.253Z" },
|
||||
@@ -1570,7 +1574,7 @@ name = "nvidia-cufft-cu12"
|
||||
version = "11.2.1.3"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/27/94/3266821f65b92b3138631e9c8e7fe1fb513804ac934485a8d05776e1dd43/nvidia_cufft_cu12-11.2.1.3-py3-none-manylinux2014_x86_64.whl", hash = "sha256:f083fc24912aa410be21fa16d157fed2055dab1cc4b6934a0e03cba69eb242b9", size = 211459117, upload-time = "2024-04-03T20:57:40.402Z" },
|
||||
@@ -1589,9 +1593,9 @@ name = "nvidia-cusolver-cu12"
|
||||
version = "11.6.1.9"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-cublas-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cublas-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-cusparse-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/3a/e1/5b9089a4b2a4790dfdea8b3a006052cfecff58139d5a4e34cb1a51df8d6f/nvidia_cusolver_cu12-11.6.1.9-py3-none-manylinux2014_x86_64.whl", hash = "sha256:19e33fa442bcfd085b3086c4ebf7e8debc07cfe01e11513cc6d332fd918ac260", size = 127936057, upload-time = "2024-04-03T20:58:28.735Z" },
|
||||
@@ -1602,7 +1606,7 @@ name = "nvidia-cusparse-cu12"
|
||||
version = "12.3.1.170"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
dependencies = [
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "python_full_version >= '3.14' or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
{ name = "nvidia-nvjitlink-cu12", marker = "(python_full_version >= '3.14' and sys_platform != 'win32') or sys_platform == 'darwin' or sys_platform == 'linux'" },
|
||||
]
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/db/f7/97a9ea26ed4bbbfc2d470994b8b4f338ef663be97b8f677519ac195e113d/nvidia_cusparse_cu12-12.3.1.170-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ea4f11a2904e2a8dc4b1833cc1b5181cde564edd0d5cd33e3c168eff2d1863f1", size = 207454763, upload-time = "2024-04-03T20:58:59.995Z" },
|
||||
@@ -1942,6 +1946,15 @@ wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/19/c7/5f7c636ec43e0c545e28d1f1db71990108306f7bdcb89f069ba97e428e7f/protobuf-7.35.1-py3-none-any.whl", hash = "sha256:4bc97768d8fe4ad6743c8a19403e314511ed9f6d13205b687e52421c023ac1b9", size = 171659, upload-time = "2026-06-11T21:55:39.155Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "py-cpuinfo"
|
||||
version = "9.0.0"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/37/a8/d832f7293ebb21690860d2e01d8115e5ff6f2ae8bbdc953f0eb0fa4bd2c7/py-cpuinfo-9.0.0.tar.gz", hash = "sha256:3cdbbf3fac90dc6f118bfd64384f309edeadd902d7c8fb17f02ffa1fc3f49690", size = 104716, upload-time = "2022-10-25T20:38:06.303Z" }
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/e0/a9/023730ba63db1e494a271cb018dcd361bd2c917ba7004c3e49d5daf795a2/py_cpuinfo-9.0.0-py3-none-any.whl", hash = "sha256:859625bc251f64e21f077d099d4162689c762b5d6a4c3c97553d56241c9674d5", size = 22335, upload-time = "2022-10-25T20:38:27.636Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pybase64"
|
||||
version = "1.4.3"
|
||||
@@ -2181,6 +2194,19 @@ wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-benchmark"
|
||||
version = "5.2.3"
|
||||
source = { registry = "https://pypi.tuna.tsinghua.edu.cn/simple/" }
|
||||
dependencies = [
|
||||
{ name = "py-cpuinfo" },
|
||||
{ name = "pytest" },
|
||||
]
|
||||
sdist = { url = "https://pypi.tuna.tsinghua.edu.cn/packages/24/34/9f732b76456d64faffbef6232f1f9dbec7a7c4999ff46282fa418bd1af66/pytest_benchmark-5.2.3.tar.gz", hash = "sha256:deb7317998a23c650fd4ff76e1230066a76cb45dcece0aca5607143c619e7779", size = 341340, upload-time = "2025-11-09T18:48:43.215Z" }
|
||||
wheels = [
|
||||
{ url = "https://pypi.tuna.tsinghua.edu.cn/packages/33/29/e756e715a48959f1c0045342088d7ca9762a2f509b945f362a316e9412b7/pytest_benchmark-5.2.3-py3-none-any.whl", hash = "sha256:bc839726ad20e99aaa0d11a127445457b4219bdb9e80a1afc4b51da7f96b0803", size = 45255, upload-time = "2025-11-09T18:48:39.765Z" },
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "7.1.0"
|
||||
|
||||
Reference in New Issue
Block a user