Commit Graph

81 Commits

Author SHA1 Message Date
Serendipity 9784f5f436 feat: API 安全加固 — 请求体大小限制、审计日志、健康检查免限速 2026-07-11 19:47:14 +08:00
Serendipity ba814c7a70 feat: CLI 添加 --incremental/--force/--mode 选项 2026-07-11 19:45:50 +08:00
Serendipity 82924ff5f3 feat: 添加 Cross-Encoder Reranker + 集成到 Searcher 2026-07-11 19:44:56 +08:00
Serendipity 1d58a55a73 feat: Searcher 集成 HybridRetriever + SearchConfig 配置 2026-07-11 19:43:49 +08:00
Serendipity cb470e516b feat: 添加 HybridRetriever — BM25+向量混合检索 2026-07-11 19:42:20 +08:00
Serendipity 7b3c7d5323 feat: DocumentIngestor 支持增量入库(FileTracker) 2026-07-11 19:41:21 +08:00
Serendipity 3e2c61402a feat: 添加 FileTracker — 基于 SHA256 的文件变更追踪 2026-07-11 19:39:12 +08:00
Serendipity 78ad21d311 chore: 添加 rank-bm25 依赖(混合检索用) 2026-07-11 19:38:33 +08:00
Serendipity f7801b45a7 fix: CLI 路径检查改用 is_safe_cli_path(允许绝对路径),更新文档 2026-07-10 15:45:22 +08:00
Serendipity ec3898ecb7 fix: auth 测试改用 monkeypatch.setattr,MarkdownSplitter 跳过代码块内标题识别 2026-07-10 15:30:58 +08:00
Serendipity 20eec96e92 fix: splitters/__init__.py 导出 HTMLSplitter 2026-07-10 15:29:21 +08:00
Serendipity f8ec682474 test: 提取 MarkdownSplitter 边界测试到独立文件 2026-07-10 15:29:10 +08:00
Serendipity 9dd1efeec9 fix: ingest_obsidian 移除硬编码回退路径,改为明确错误提示 2026-07-10 15:29:00 +08:00
Serendipity e99c090152 fix: 速率限制器配置从环境变量读取而非硬编码 2026-07-10 15:28:30 +08:00
Serendipity 76ae81c772 test: test_config 用 monkeypatch 替代 importlib.reload 2026-07-10 15:28:22 +08:00
Serendipity 788f610d3f test: 修复 EPUB 缺失依赖测试设计问题 2026-07-10 15:28:13 +08:00
Serendipity 2e95f68864 fix: list_collections 异常向上传播而非静默吞掉 2026-07-10 15:28:03 +08:00
Serendipity 3308636086 refactor: 去重删除逻辑统一到 VectorDB.delete_by_source 2026-07-10 15:27:52 +08:00
Serendipity ebfae1f60c fix: EXPECTED_API_KEY 改为惰性求值防加载顺序问题 2026-07-10 15:27:38 +08:00
Serendipity 29bdfcfb18 fix: 替换过时的 X-XSS-Protection 为 Content-Security-Policy 2026-07-10 15:27:27 +08:00
Serendipity 276a1401f4 fix: content 模式默认 file_name 改用 UUID 防并发覆盖 2026-07-10 15:27:19 +08:00
Serendipity b0319f366a test: 补充 Searcher list_sources/delete_by_source/get_collection_info 测试
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:25:54 +08:00
Serendipity 925499b05b test: 补充 ingest_file 和 ingest_directory 的测试覆盖
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:25:50 +08:00
Serendipity e0190e8d2d test: 添加 verify_api_key 和 RateLimiter 完整单元测试
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:25:47 +08:00
Serendipity a368e640c1 test: 添加 CLI 模块基础测试 (ingest/search/stats/json)
Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:25:43 +08:00
Serendipity fc010cda06 fix: CLI serve 使用 load_config 避免主进程双重加载嵌入模型
- 用 load_config(config) 替代 get_state().config
- 避免 CLI 主进程加载嵌入模型后 uvicorn 子进程再次加载
- 移除对 get_state 的隐式依赖(已有 DEFAULT_CONFIG_PATH 导入)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:23:19 +08:00
Serendipity b97cff8857 fix: chunk 配置通过 DocumentIngestor 传递,不再被硬编码覆盖
- DocumentIngestor 新增 chunk_config 参数,类型 ChunkConfig
- ingest_file 使用 self.chunk_config.max_size/overlap 代替硬编码 1000/100
- deps.py get_ingestor 传入 config.chunk 配置对象

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 15:23:14 +08:00
Serendipity 6a5be5f3e7 fix: ingest_obsidian 初始化添加异常处理和友好错误信息 2026-07-10 15:21:29 +08:00
Serendipity 8445af7be0 fix: HF_ENDPOINT 环境变量操作添加线程锁防竞态 2026-07-10 15:19:43 +08:00
Serendipity 298f13721c fix: 统一 CLI/API 路径安全检查为 is_path_within_workspace 2026-07-10 15:19:17 +08:00
Serendipity 1eb6f44ef4 fix: delete_document 的 collection 参数添加正则校验 2026-07-10 15:18:56 +08:00
Serendipity 0a4a4c766c fix: search_documents 端点添加异常处理防止 traceback 泄露 2026-07-10 15:18:46 +08:00
Serendipity 284a4b9e09 fix: 修复 CORS allow_credentials 与 allow_origins=* 冲突 2026-07-10 15:18:39 +08:00
Serendipity 3b8b585f31 feat: 添加 EPUBSplitter — ebooklib 提取章节文字后分块
- 新增 splitters/epub.py: ebooklib 读取 EPUB → BeautifulSoup 去标签 → TextSplitter 分块
- epub 作为可选依赖: uv sync --extra epub
- registry 新增 .epub 映射, ingest_file 处理 EPUB 二进制文件
- 测试: 3 个 EPUBSplitter 测试 (含空 EPUB/Protocol 合规)

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-10 14:32:41 +08:00
Serendipity eda080bc05 docs: 更新文档记录多格式支持特性 2026-07-10 14:27:11 +08:00
Serendipity b8afc9043d test: 添加 PDFSplitter 和 HTMLSplitter 测试 2026-07-10 14:25:40 +08:00
Serendipity 9db0c15dee test: 添加 Splitter 注册表和 TextSplitter 测试 2026-07-10 14:23:34 +08:00
Serendipity 30716f10dc feat: 添加 HTMLSplitter — bs4 去标签后分块 2026-07-10 14:22:28 +08:00
Serendipity 69fb8cac9f feat: 添加 PDFSplitter — pymupdf 提取文字后分块 2026-07-10 14:20:53 +08:00
Serendipity cde4ae7ddc feat: ingest.py 使用 registry 自动选择 Splitter,ingest_directory 支持多格式 2026-07-10 14:19:03 +08:00
Serendipity 13d63ba6ff feat: 添加 TextSplitter 和 registry 自动选择机制 2026-07-10 14:17:17 +08:00
Serendipity 4dc51dccd2 refactor: 将 MarkdownSplitter 移入 splitters 包,ingest.py 保留兼容 import 2026-07-10 14:15:59 +08:00
Serendipity 30c4d65cf0 feat: 创建 splitters 包骨架 — Splitter Protocol + BaseTextSplitter 基类 2026-07-10 14:12:38 +08:00
Serendipity 11b6171e21 docs(test-guide): 重写为完整的项目使用与测试文档
替换原有的通用向量数据库入门内容,新增项目简介、核心概念、快速上手流程、CLI与HTTP API使用方法、配置说明、嵌入提供商选择、安全配置、架构概览、GPU加速、测试命令和常见问题等完整文档内容,适配作为项目的使用指南与测试手册。
2026-07-07 15:04:45 +08:00
Serendipity 405303e82c fix: 修复 44 个代码审查问题 (CRITICAL/HIGH/MEDIUM/LOW)
Batch 1 — CRITICAL (1):
- 提取 is_safe_path() 到 src/core/security.py 公共模块
- CLI 和 ingest_obsidian.py 统一添加路径遍历防护

Batch 2 — HIGH (13) + 架构重构:
- CLI 复用 deps.py AppState, 消除 30 行重复代码
- AppState/get_state 添加线程安全锁
- serve 命令传递 --config 到 uvicorn (H1)
- OpenAIEmbedder 懒创建+复用 HTTP 客户端 (H2)
- DashscopeEmbedder import 移到模块顶部 (H3)
- 路径检查改用 os.path.commonpath (H4)
- embedder.embed() 返回值长度检查 (H5)
- 健康检查不泄露内部错误详情 (H7)
- /api/v1/collections 添加 API Key 认证 (H8)
- API Key 使用 hmac.compare_digest 恒定时间比较 (H9)
- 添加 CORS 中间件 (H10)
- ServerConfig 支持 SSL 配置 (H11)
- HF_ENDPOINT 修改添加详细注释 (H12)

Batch 3 — MEDIUM (20) + Splitter Protocol:
- 定义 Splitter(Protocol) 接口, DocumentIngestor 接受可选 splitter
- DashScope 响应添加结构验证 (M2)
- ingest_obsidian.py 支持 CLI 参数和 OBSIDIAN_DIRS 环境变量 (M6)
- scripts/serve.py 添加废弃警告 (M7)
- content 限制 500KB, collection 正则限制字符集 (M12-M14)
- 默认监听地址 127.0.0.1 (M16)
- 添加安全响应头中间件 (M17)
- verify_api_key 认证失败记录日志 (M19)

Batch 4 — LOW (10):
- CLI emoji 清理为纯文本标记 (L5)
- logging.basicConfig 移到 FastAPI lifespan (L1)
- VectorDB 添加 write_guard() 上下文管理器 (L3)
- IngestRequest file_path/content 互斥校验 (L10)
- ingest_obsidian.py 注释修正 (L6)

测试: 46 → 70 (+24)
- tests/test_security.py: 11 个路径安全测试
- tests/test_deps.py: 11 个依赖注入测试

Co-Authored-By: Claude <noreply@anthropic.com>
2026-07-06 16:56:38 +08:00
Serendipity 832201186d fix: 修复 11 个代码架构审计问题
H1: AppConfig 自定义 __init__ 改用 from_dict() 类方法
H2: list_collections_with_stats 改为从 ChromaDB 直接查询
H3: RateLimiter 过期 key 自动清理, 防止内存泄漏
M1: delete_by_source 区分 ValueError 与真实异常, 记日志
M2: VectorDB 新增 list_collections() 封装方法
M3: _remove_by_source 异常记日志, 不再静默吞掉
M4: CLI 集合回退支持 MD_VECTOR_DB_COLLECTION 环境变量
L1: DEFAULT_CONFIG_PATH 自动从项目根目录解析
L2: ingest 命令内重复 import 移至模块顶部
L3: 新增死循环回归测试 + 密集分隔符分块测试
L4: 统一 logger 名称为 md-vector-db
删除旧版审计文档

测试: 48 passed
2026-07-06 13:16:26 +08:00
Serendipity 7e77c31e16 docs: 更新 README/CLAUDE 文档 + 配置 uv CUDA 兼容
- README: 补充 GPU 加速章节、多集合、CLI 新选项 (-C/--json)
- CLAUDE: 修正 uv run 可用说明、补充 [tool.uv] 配置文档
- pyproject.toml: 添加 [tool.uv] 配置, 通过 find-links + unsafe-best-match
  让 uv 从本地 CUDA wheel 解析 torch, 不再覆盖 GPU 环境
- uv.lock: 更新 lockfile, Windows 平台锁定 torch 2.6.0+cu124
2026-07-06 12:44:06 +08:00
Serendipity eebdef739c fix: 修复 MarkdownSplitter 死循环 + 添加 GPU 自动检测
- ingest.py: _split_single_paragraph 中分隔符距 start 小于 overlap 时
  start 会回退为负数,Python rfind 负索引导致无限循环
  修复: start = max(start + 1, next_start) 确保始终前进
- embedder.py: LocalEmbedder 自动检测 CUDA,优先使用 GPU
- ingest_obsidian.py: MAX_SIZE 调整为 200KB 适配 GPU 嵌入
- 清理临时日志文件
2026-07-06 00:04:04 +08:00
Serendipity d141baf964 fix: use path hash prefix for source_file names to prevent same-name collisions; add size filter to ingest script 2026-07-05 04:46:47 +08:00
Serendipity d3cb88525c feat: multi-file, stdin, and glob support for ingest; fix stderr UTF-8 2026-07-05 02:14:17 +08:00