Restore the contracts the split dropped and correct the record
A split moves code; it does not get to rewrite what the code promises. The first pass collapsed three multi-line docstrings into one-liners and the line counts in the checklist were measured before that happened. - store_search.py: search_atoms keeps its filter-shape rule and the as_holder sharing rule, FtsPage keeps why the cursor is an offset - bench/run.py: the module docstring says what the five arms are again - CHECKLIST: 116/341/83 lines, 11 call sites over 7 methods, and the migration ladder now cites 181/186/248/250 instead of the parent's lines Repo-wide multi-line docstrings are back to 114, the parent's count.
This commit is contained in:
1 parent
9cb46c18d3
commit
28959c51c6
3 files changed
+24
-7
No files matched your search
+3
-3
@@ -321,7 +321,7 @@
|
||||
- [x] **p1-6** 代码卫生
|
||||
- [x] p1-6.1 每个文件 ≤500 行
|
||||
- 验收命令 `python -m bench.filesize_check` → `OK: no tracked source file exceeds 500 lines`。这个脚本是本轮加的:500 行规则之前只靠记忆执行
|
||||
- `evals.py` 2413 行在 p0-6 已拆成 `proofs/*`(最大 430)。本轮拆的:`db.py` 503→396(BM25 检索搬进 `store_search.py` 105)、`bench/run.py` 609→351(`query_set.py` 80 + `report.py` 211)、`benchmarks.py` 619→424(`benchmark_scoring.py` 262)、`training.py` 1630→94(`training_{common,encode,metrics,datasets,lora,retrieval}.py` = 108/177/307/387/408/358,`TrainingService` 留成薄壳喂 `cli.py` 的 10 个调用点)、`schemas.py` 534→469(p1-5 拆出 `status_schemas.py` 74)
|
||||
- `evals.py` 2413 行在 p0-6 已拆成 `proofs/*`(最大 430)。本轮拆的:`db.py` 503→396(BM25 检索搬进 `store_search.py` 116)、`bench/run.py` 609→341(`query_set.py` 83 + `report.py` 211)、`benchmarks.py` 619→424(`benchmark_scoring.py` 262)、`training.py` 1630→94(`training_{common,encode,metrics,datasets,lora,retrieval}.py` = 108/177/307/387/408/358,`TrainingService` 留成薄壳喂 `cli.py` 的 11 个调用点、7 个方法)、`schemas.py` 534→469(p1-5 拆出 `status_schemas.py` 74)
|
||||
- 「拆分不改行为」的证据:脚本把每个搬走函数的**函数体去缩进后与 HEAD 逐字节比对**——training 侧 53 个、benchmarks 侧 21 个,**全部相同,0 处不同,0 个缺失**。方法转函数只重写 def 头,`self.settings`→`settings` 这类替换是正文里唯一的改动
|
||||
- 新增 `backend/tests/test_training_split.py`(6 条):CPU 能跑的纯函数逐个测;最后一条用 `inspect.signature` 断言薄壳参数表 = 模块函数参数表去掉注入的两个参数——这条就是抓 `self` 泄漏那类 bug 的
|
||||
- [x] p1-6.2 删 dead code 与未调用函数
|
||||
@@ -329,10 +329,10 @@
|
||||
- 两个为什么是死的:`memory.py` 靠读每颗卡带自己的 `sources.json` 回答归属(导出的卡带可以不在库里);`set_mounts(database, [], stamp)` 换集合本来就能清空挂载表
|
||||
- 顺手删 `backend/build/`(712KB 的 `python -m build` 残留,gitignore 内,0 个跟踪文件)——它让 grep 撒谎
|
||||
- [x] p1-6.3 删 v1/v2/v3 废弃端口
|
||||
- 量完的结论是**没有可删的**,不是没做:每个 `v1/v2/v3` 都承重——磁盘格式标签(`ely-eye-memory-capsule-v1` `proofs/checks_cartridge.py:128`、`ely-eye-{text,visual}-vectors-v1`、`ely-eye-kivi-replay-v1` `cartridge_assets.py:100,127,158`)、迁移阶梯(`migrations.py:185,190,243`)、矛盾语料 fixture 名(`proofs/contradictions.py:114-135`)、第三方名字(MiniLM-L12-v2、ScreenSpot-v2、LongBench v2)、OpenAI 兼容的 `/v1` URL、缓存键里的 `compiler-v2` salt。没有废弃端口、别名或双代码路径
|
||||
- 量完的结论是**没有可删的**,不是没做:每个 `v1/v2/v3` 都承重——磁盘格式标签(`ely-eye-memory-capsule-v1` `proofs/checks_cartridge.py:128`、`ely-eye-{text,visual}-vectors-v1`、`ely-eye-kivi-replay-v1` `cartridge_assets.py:100,127,158`)、迁移阶梯(`migrations.py:181,186,248,250`)、矛盾语料 fixture 名(`proofs/contradictions.py:114-135`)、第三方名字(MiniLM-L12-v2、ScreenSpot-v2、LongBench v2)、OpenAI 兼容的 `/v1` URL、缓存键里的 `compiler-v2` salt。没有废弃端口、别名或双代码路径
|
||||
- [x] p1-6.4 注释压到 ≤1 行
|
||||
- 口径:`tokenize` 找连续 `#` 行块。全仓 **39 块 / 86 行 → 0 块**,每块压成一行,压的时候留承重那句,实测数字与错误原文不删(`Unable to allocate 582. MiB for an array with shape (5632, 9024, 3)`、`288,266 rows for 165,973 atoms`、`[^[^\W\s]` 在 3.14 会吃掉 CJK)
|
||||
- docstring 不动(全仓多行 docstring 114 条,与父提交同数):docstring 是模块与函数的契约,不是注释;p1-4 review 用的口径也是「新增多行 docstring 数不得增加」
|
||||
- docstring 不动(全仓多行 docstring 114 条,与父提交同数):docstring 是模块与函数的契约,不是注释;p1-4 review 用的口径也是「新增多行 docstring 数不得增加」。第一轮 review 抓到搬家途中塌了 3 条——`store_search.py` 的 `search_atoms`(那条「每个过滤条件都是同一条字面 SQL 里的 `? IS NULL OR` 谓词」规则和 `as_holder` 的共享规则)和 `FtsPage`、`bench/run.py` 的模块 docstring——已按原文补回,行数仍全部在 500 以内
|
||||
- 门禁:`pytest -q` **269 passed**;`ruff check backend/src/ely_eye backend/tests bench` All checks passed;mypy 冷缓存 **24 errors / 9 files**(基线 24/6,training.py 那 6 条随拆分落到 4 个新文件,净新增 0);`pyright` 查 46 个改动文件 → **4 errors**,与 HEAD 单个 `training.py` 在包副本里量到的 4 条同源(qwen_vl_utils 元组返回、两处 `save_pretrained(Path)`、`bitsandbytes` 未解析);go build/vet/test + gofmt 干净;`npm run build` + eslint 干净
|
||||
|
||||
---
|
||||
|
||||
@@ -12,14 +12,15 @@ from .text_index import fts_expression, fts_terms, rare_terms
|
||||
|
||||
@dataclass(frozen=True)
|
||||
class FtsPage:
|
||||
"""A page of (atom_id, score) plus whether more matches exist."""
|
||||
"""One page of BM25 hits plus whether the corpus holds more: the cursor is an offset, and a
|
||||
ranking this small re-reads rather than keeps a server-side position."""
|
||||
|
||||
rows: list[tuple[str, float]]
|
||||
has_more: bool
|
||||
|
||||
|
||||
def search_fts(database: Database, query: str, limit: int) -> list[tuple[str, float]]:
|
||||
"""Best BM25 matches over the whole corpus, no filters."""
|
||||
"""Best BM25 matches over the whole corpus, no filters: the ranking the product needs most days."""
|
||||
return search_atoms(database, query, limit=limit).rows
|
||||
|
||||
|
||||
@@ -39,7 +40,16 @@ def search_atoms(
|
||||
cartridge_ids: list[str] | None = None,
|
||||
as_holder: str | None = None,
|
||||
) -> FtsPage:
|
||||
"""BM25 over the FTS index joined to memories that are open right now and readable by the asker."""
|
||||
"""BM25 over the FTS index joined to memories that are open right now and readable by the asker.
|
||||
|
||||
Every filter is a `? IS NULL OR` predicate in one literal statement: the ranking never
|
||||
depends on string-built SQL, and the planner sees one shape. A memory with no event time
|
||||
cannot answer a time filter, so it drops out when one is asked for.
|
||||
|
||||
`as_holder` applies the sharing rule: a memory is readable by its owner, by anyone named
|
||||
in its visible_to list, by everyone when it is public, and by anyone when nobody owns it.
|
||||
A memory with no holder cannot be private to a holder that does not exist. Without an
|
||||
asker the query runs over the whole library, which is what an operator debugging wants."""
|
||||
with database.connect() as connection:
|
||||
expression = fts_expression(rare_terms(connection, fts_terms(query)))
|
||||
rows = connection.execute(
|
||||
|
||||
+8
-1
@@ -1,4 +1,11 @@
|
||||
"""Run the retrieval ablation over the frozen corpus and write the report: python -m bench.run [--arms bm25_only] [--limit 200] [--no-live]."""
|
||||
"""Run the retrieval ablation over the frozen corpus and write the baseline report.
|
||||
|
||||
Five arms, one database: sparse only, dense only, graph only, the product's weighted
|
||||
fusion, and fusion plus a cross-encoder reranker. Every number in the report is either
|
||||
measured or explicitly marked as chance.
|
||||
|
||||
Run: python -m bench.run [--arms bm25_only] [--limit 200] [--no-live] [--out bench/reports]
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
|
||||
Reference in new issue
Block a user