Repository navigation
Conversation
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- rust-ci.yml 拆成 4 个并行 job:
· lint — cargo fmt + 版本一致性 + 文档链接(ubuntu 单次)
· clippy-test — clippy -D warnings + cargo test,矩阵
ubuntu-latest / windows-latest / macos-latest
Linux 条件安装 apt WebKit/GTK 依赖
· ui-build — pnpm install + build(ubuntu 单次)
· security — EmbarkStudios/cargo-deny-action check advisories bans sources
+ pnpm audit --audit-level high(ubuntu 单次)
- 新增 deny.toml:yanked=deny;多版本=warn;仅 crates.io 来源
暂不检查 licenses 以避免白名单初期噪声
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
「当前状态」拆成三档: - ✅ 已验证可用:v2 基准数字、多格式摄入、安全层、CI 矩阵等实测项 - 🚧 已实现但仍在优化:gating 误拒、图谱可视化、跨语言 - 📐 设计中/待实现:LLM-judge、限流、OpenAPI、keychain、OCR、50k 压测 同步更新: - 第5节 CJK 部分:删「50条」旧目标,换成 v2 困难基准实测数字 (top-3 0.925 · MRR 0.839 · 拒答 0.881 · citation 1.000) - memori-parser 模块描述:补 PPTX/XLSX/.doc/.ppt/.xls 新格式 - 中英文 README 同步 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
S1 — API key 接 OS keychain(Windows Credential Manager / macOS Keychain /
Linux Secret Service via zbus):
· 新增 keychain.rs:save_api_key / load_api_key / delete_api_key
· 哨兵值 "__keychain__":JSON 只存哨兵,明文不落盘
· settings_io::load_app_settings 透明替换哨兵为 keychain 实际密钥
· set_model_settings 保存前写 keychain;写失败降级明文+warn
· 兼容旧配置:首次保存自动迁移到 keychain
S5 — audit.rs 所有 IO 失败路径从 warn! 升级为 error!:
· 日志前缀 "audit event dropped:" 便于日志聚合定位
· 覆盖:路径解析/目录创建/序列化/文件打开/写入 共 5 处
依赖:keyring v3.6.3(纯 Rust,zbus 后端,无 dbus 编译期系统依赖)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
memori-server 路由层三项工程硬化,因均在 routes/mod.rs 串联中间件与路由、 彼此交织,合并为一个可独立编译的提交。 ## S2/E6 按 IP 接口限流(middleware.rs RateLimiter) - 固定 60s 窗口、按客户端 IP 计数;登录/admin 走严格桶(默认 20/min), 其余走普通桶(默认 600/min),超限返回 429 + Retry-After。 - 阈值经 env 可调:MEMORI_RATE_LIMIT_ENABLED / _PER_MIN / MEMORI_AUTH_RATE_LIMIT_PER_MIN。 - 判定逻辑抽成纯函数 RateLimiter::check,条目超 4096 时惰性清理过期窗口防膨胀; 锁中毒时保守放行而非全拒。4 个单测覆盖到限、跨窗重置、桶/IP 隔离、敏感路径归类。 - main.rs 改用 into_make_service_with_connect_info 以向中间件透传 ConnectInfo<SocketAddr>; 限流器随 ServerState 注入(state.rs)。 ## G2 request-id / trace 可观测性(middleware.rs request_id_trace_middleware) - 透传或生成 x-request-id(校验非空/≤200/ASCII),以其建立 http_request tracing span 包裹后续处理,使检索链路日志可按请求聚合;响应回写同名头部便于端到端关联。 ## G1/E5 OpenAPI 3.1 契约(routes/openapi.rs) - 表驱动:ROUTES 登记表为唯一事实源,生成 OpenAPI 3.1 文档,GET /api/openapi.json 暴露。 - 覆盖全部 33 个 REST 路由方法,含 tag/summary/operationId/security/请求响应 schema; 关键 DTO 给出精简 schema,复杂响应体(如 AskResponseStructured)标注为通用 object, 避免为生成文档而给核心 crate 引入 utoipa 依赖。 - 3 个单测:每路由有对应条目、规格结构有效、路由表条数与 build_router 一致(漂移自检)。 ## 中间件挂载顺序(routes/mod.rs,由外到内) CORS → request-id/trace → 限流 → handler。CORS 预检 OPTIONS 在最外层短路,不触发限流。 运行时验证:429 触发正常(敏感桶 3 上限:400×3→429×3);x-request-id 生成与 客户端透传均正确;/api/openapi.json 返回 openapi=3.1.0、30 路径/33 方法。 全量经 cargo fmt --check + clippy --workspace -D warnings + memori-server 全部单测(21 通过)。 deploy/env 示例补充限流相关变量说明。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
新增 memori-core/examples/perf_scale.rs:为 P1「单 Mutex<Connection> 串行化所有
读写」的改造决策提供 P50/P95/P99 量化证据,并填补 P2「50k 规模从未压测」的空白。
## 设计
- 语料全程内存合成 + 确定性离线 embedding(dim 256),不依赖 llama-server,CI 可复跑。
- 关闭 rerank(MEMORI_RERANK_ENABLED=0),隔离出存储/检索本身的延迟——正是单连接锁
影响的部分;避免本机若恰好在跑 :18004 时外部往返污染测量。
- 复用真实索引/检索栈:begin_full_rebuild → replace_document_index → load_from_db →
retrieve_structured_with_embedding(无 LLM)。合成文档不落盘,仅作路径前缀。
- 两阶段测量:
1. 顺序:单请求 P50/P95/P99 + 各阶段(doc_recall/doc_dense/chunk_lexical/
chunk_dense/merge)耗时分布。
2. 并发:固定并发度(信号量有界)同时打,测每请求延迟与吞吐。
## 本机基线(1000 文档 / 101,000 chunks,见 docs/qa/PERF_SCALE_50K.md)
- 顺序 P50/P95/P99 = 251.4 / 330.0 / 365.1 ms(~4 qps)
- 并发 8 P50/P95/P99 = 1573.7 / 2193.5 / 2488.0 ms(~5 qps)
- 顺序阶段 P50:doc_recall 185ms(主导)/ doc_dense 30 / chunk_lexical 59 /
chunk_dense 59 / merge 1ms。
## 判定:P1 改造收益明确
争用系数 = 并发 P50 / 顺序 P50 = 6.26×(并发度 8),而吞吐仅 1.28×——增加并发几乎
不增吞吐、只堆积排队延迟,正是单连接锁把并发读串行化的特征。P1 的 WAL 只读连接池 +
单写改造(store.rs:169 / lib.rs:527)由此有据;改造后用同 harness 同参复跑,目标
争用系数 < 2×。
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
补 D2「检索质量无 CI 阈值门,指标静默退步无人拦」:新增可在 CI 复跑的离线确定性 回归 + 阈值门,拦住排序/gating 代码路径的悄悄退步。 ## --assert-thresholds 门控(retrieval_regression.rs) - 新增标志:跑完后读阈值 JSON(指标名→最小可接受值),逐项比对 summary, 任一未达标打印明细并退出码 1;未知指标名视为配置错误报错。 - 仅新增 CLI 解析 + 比对函数,不触碰任何检索算法路径。 ## 自带 fixture 语料(docs/qa/ci_fixtures/) - 为何自带:v1/v2 语料未入库(CI 取不到)且含 pdf/docx 二进制不适合 CI。 - generate_ci_fixtures.py 产出 12 篇纯文本 md(各埋唯一 needle 关键事实)+ retrieval_regression_ci.json(14 case:12 答 + 2 拒)。全确定性、可复现。 - 门控对象是排序/gating 代码不退步,非真实语义质量(后者由 live 基线负责)。 ## 阈值与 CI job - retrieval_regression_ci_thresholds.json:doc/chunk recall≥0.90、citation=1.0、 reject≥0.75(设在观测值 0.917/1.0/0.786 下方留余量,catch 真实退步而不 flaky)。 - rust-ci.yml 新增 retrieval-gate job(ubuntu、无需模型、offline_deterministic)。 验证:正常通过(exit 0,全指标达标);阈值不达标正确失败(exit 1,打印未达标项)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
CI 的 cargo clippy/test 原本不带 --all-targets,漏检测试代码,导致测试模块的 clippy 违规与 example 单测 bit-rot 长期无人拦。本次升级为 --all-targets 并修掉 暴露出的既有问题: - memori-parser/lib.rs、memori-core/model_config.rs:test 模块后还有 items (clippy::items_after_test_module)→ 将 #[cfg(test)] mod tests 移到文件末尾。 - memori-core/tests.rs:3 处 let mut evidence = vec![...] 仅本地排序用 → 改数组 (clippy::useless_vec)。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
审计 P1:单 std::sync::Mutex<Connection> 串行化所有读+写,50k 压测实测并发 8 争用系数 6.26×(吞吐仅 1.28×)。本次改造: - 写连接开 journal_mode=WAL + busy_timeout=5s + synchronous=NORMAL,读写不互斥。 - 新增 N 路只读连接池(默认 4,MEMORI_DB_READ_POOL_SIZE 可调,0 关闭回退写连接), 检索热路径(search.rs 7 个 SELECT)经 lock_read_conn 轮询取连接并发读;写仍走 单 write_conn 串行(SQLite 单写者模型,保证写一致性)。WAL 下读到最后已提交事务, 索引提交后检索可见,满足一致性(22 个 storage 测试含读写往返全过)。 同参 50k 复跑(见 docs/qa/PERF_SCALE_50K.md): - 争用系数 6.26× → 1.72×(达标 <2×) - 并发 8 P50 1573.7 → 286.6ms(−82%)、P95 2193.5 → 434.8ms(−80%) - 并发吞吐 4.9 → 26.7 qps(5.4×);顺序 P50 251 → 167ms(−33%);建索引 ~2× 快。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
补齐审计 E6/E5 仅有纯函数单测、缺端到端覆盖的缺口。新增 http_tests.rs:经真实 build_router 走完整中间件链(tower oneshot),验证: - /api/health 返回 200 且带生成的 x-request-id;客户端传入 x-request-id 被透传。 - /api/openapi.json 返回有效 OpenAPI 3.1 文档(含 /api/ask 路径)。 - 敏感路径限流:阈值 2 时第 3 个请求返回 429;关闭限流时永不 429。 RateLimiter::new 放开为 pub(crate) 供测试构造;新增 tower dev-dependency(util)。 全 26 个 server 测试通过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
审计 S6:open_source_location / read_file_preview 不校验目标是否在监听目录内, 可 reveal / 读取 watch_root 范围外任意存在文件。新增 ensure_within_watch_root: canonical 化目标与 watch_root,要求目标在子树内(纯函数 path_is_within,按路径 分量匹配,兄弟目录 vault-secret 不会误配 vault),否则拒绝。read_file_content 经 read_file_preview 一并覆盖。本地信任场景的 defense-in-depth。附 2 个边界单测。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
审计 Q3「评测盲区」:harness 此前只用 top-k 命中当代理,从不判分实际答案文本, "答得对不对"无客观分。本次补闭环: - 新增 answer_judge.rs:judge_answer_correctness(question, expected_points, answer) 用 chat 模型对照期望关键事实判 correct/partial/incorrect(强制 JSON 输出 + 噪声 容错解析 + 关键词回退),分值 1/0.5/0。逻辑内聚于 core,server 评测亦可复用。 - retrieval_regression harness 加 --judge:live 模式下对应答类案例调 ask_structured 生成真实答案再判分,summary 增 answer_judged_count / answer_correct_rate; --assert-thresholds 支持 answer_correct_rate 指标(可纳入门控)。 - 顺修 example 测试既有 bit-rot(缺 top_documents 字段,因 CI 旧 test 未含 example)。 judge 解析逻辑 4 单测 + harness example 7 单测全过。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 「本轮已修」表补 8 行(S2/G2、G1、P2、D2、P1、S6、Q3、工程硬化),各带 commit。 - 修复上一批 S2/G2/G1/P2/D2 汇总行被误插进「A. 安全」5 列详细表导致的列数错位 (MD056):汇总行(3 列:项/处置/commit)统一归入文首「本轮已修」表,A. 安全 恢复为基线说明 + 原始 5 列清单。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
dense 检索(search_similar_scoped)原对每个缓存向量每次都重算 norm_b(开方)。 本次给 CachedVector 预存 L2 模(加载/写入时算一次),扫描改用 cosine_with_norms: 与 cosine_similarity 数学等价(同 dot、同 sqrt(Σx²) 乘积、同除法),结果 bit-identical, 仅把常量模移出热循环。 50k perf 复跑:doc_dense 23→19ms、chunk_dense ~43→39ms、顺序 P50 167→157ms; offline 确定性 CI 门仍 PASSED(结果不变)。属精确常量级加速;大规模真正的 O(n)→O(log n) (HNSW/ANN)留作后续规模档工作。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- env 示例:标注限流器为进程内(多副本需网关级共享限流如 Redis);新增 MEMORI_DB_READ_POOL_SIZE 说明。 - TUTORIAL:单 GPU 上 chat(14B)+embed+rerank 可能超显存,llama.cpp 会把模型溢出到 CPU 致 embedding/索引慢约 10×;建议错峰、限 -ngl 或分卡。本轮压测即遇此现象。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
审计 F2:UI 6 处 markdownRemarkPlugins/markdownRehypePlugins 用 any[](ResultStage 另有 unknown[])削弱类型安全。新增 types.ts MarkdownPlugins(从 react-markdown props 派生 PluggableList,pnpm 下不直接依赖 unified),AnswerPanel/EvidencePanel/CitationPanel/ ResultStage/app-helpers 常量统一用之。tsc --noEmit 通过,src 已无 any。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- 新增「现状重新评判(2026-06-13)」章节:✅已做(逐项带 commit)/❌未做(按卡点分类)两表 + 推进顺序 - Phase 9 E1–E8 勾选并标 commit;E9–E11 标明卡点(产品决策/协同设计/大重构) - 补审计速赢批(F1/C1/C2/S1/S5/S6/Q3/F2/P4-lite)落地说明 - 删文末误粘的残缺测试代码片段;顺修 markdown lint(表格分隔行/标题空行) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
面向接手同学:项目简介、如何运行、可直接粘贴给 AI 的提示词。 核心规则:所有开发只在 collab 分支,禁止改动 main/dev。 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
- ask_handler 完成/失败分别落 info/warn 事件,默认日志级别即可见, 事件显式携带 request_id 与各阶段耗时(doc_recall/chunk_dense/merge/answer) - 中间件把 request-id 注入 RequestId 扩展,审计 metadata 增加 request_id 字段 - 新增 extensions 注入端到端测试(http_tests)
- memori-parser: 行结束事件里嵌套 if 折叠为 match guard(行为等价) - memori-core: format! 参数去掉多余引用(行为等价) - 修复后 workspace clippy -D warnings 全绿
- AppSettings 新增 index_filter 字段(此前 serde 静默丢弃该配置) - replace_engine 在 set_indexing_config 后应用筛选配置 - 新增 2 个反序列化单测固定解析行为
- build_openai_url:endpoint 已显式带 /v1(无尾斜杠)时不再追加, 修复拼成 /v1/v1 导致 404 的问题;新增幂等单测 - 回归 harness 探活:单次 10s 超时改为 3 次重试(每次 20s + 5s 间隔), 本地模型冷载(实测 12s+)不再被误判为服务不可用
- 报告入库:retrieval_regression_v2_judge_report.json(106 应答题全部判分) - answer_correct_rate 0.401(受限配置下限:1.5B 作答 + 无 rerank) - RETRIEVAL_BASELINE_V2.md 新增作答层基线章节,含环境、数字与解读
- GET /api/docs:Swagger UI 页面,数据源 /api/openapi.json - CSS/JS 静态资源构建期内置(include_str!/include_bytes!),离线可用, 符合本地优先原则,不引入 utoipa 依赖 - 新增端到端测试:页面 HTML、静态资源 content-type 与非空校验
- ocr.rs:tesseract 外部进程封装(30s 超时强杀、PSM 4 单列排版、 路径探测 OnceLock 缓存、临时文件原子序号防并发冲突) - 扫描 PDF:无文本层回退提取 XObject 图片 OCR,支持 DCTDecode 直写 与 [ASCII85Decode FlateDecode] 链式解码(含 ASCII85/Hex 解码器) - docx 内嵌图片(word/media)OCR 追加,20MB 大小上限 - 独立图片文件(png/jpg/jpeg)进白名单直接 OCR - 找不到 tesseract 时全链路静默降级,既有行为不变 - settings.json 新增 ocr_tesseract_path,server/desktop 启动时注入 环境变量(显式 env 优先);ocr_smoke 调试工具自动读 settings - v2 套件图片/扫描 4 题:文档召回 0/4 → 4/4
- perf_scale.rs: --start-doc 断点续跑参数(50k 压测期间遗留未提交) - perf_scale.rs: --max-contention-factor 断言,超标非零退出(供 CI 门槛,目标小于 2x) - 新增 .github/workflows/perf-scale.yml:手动触发 + 每周日 02:34 UTC 全量 50k,报告 JSON 上传 artifact - README/PERF_SCALE_50K.md:同步 50k 验证结论与 CI 复跑说明
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
本 PR 将项目完整代码从 collab 合并到 main,用于初始化 / 承载主分支代码,实现“作答层 LLM-judge 评测闭环(当前只有检索层指标,无客观答案质量分)”“OpenAPI / Swagger spec(memori-server)”“OCR(图片/扫描件目前不可检索)”“50k 规模压测(P50/P95,大规模并发性能尚未验证)”功能