Skip to content

修复长文本 embedding 超限,并固定请求分片策略 - #27

Merged
loveRhythm1990 merged 3 commits into
mainfrom
fix/embedding-token-chunks
Oct 30, 2026
Merged

loveRhythm1990 merged 3 commits into
mainfrom
fix/embedding-token-chunks

Conversation

@loveRhythm1990

@loveRhythm1990 loveRhythm1990 commented Oct 30, 2026 •

Copy link
Copy Markdown
Contributor

现有 Add 仅按 32 KiB UTF-8 字节数分片,不能保证符合 embedding 模型的 token 上限。合成复现中,29,763 字节的文本被 BGE-M3 计为 18,333 token,超过 8,192 上限,embedding 返回 400;重复提交不能恢复。本次为新请求同时执行字节和 token 限制,完整保留原文,并补齐证据归因与回滚兼容保护。

实现

  • 新请求每片默认最多 7,680 token,保留 32,768 字节上限;ADAPTER_EMBEDDING_TOKEN_BUDGET 可配置为 128–8,192。默认值和合法范围集中定义;计数包含角色、时间前缀和特殊 token。
  • 使用固定 revision、SHA-256 校验的真实 BGE-M3 tokenizer。按原始 Unicode 切片,不解码重建、不截断或概括正文。普通 Search 查询不变。
  • tokenizer 在初始化/构建时准备,运行时不下载;缺失或校验失败则启动失败。Docker 下载层独立于其他源码,CI 缓存并重新校验资源。
  • 首次写入意图与分片策略在同一 SQLite 事务中保存。后续重试使用持久化策略,配置调整只影响新请求;每片仍为三次持久化提交。完成请求校验指纹后直接返回。
  • message_parts、write_bodies、SourceManifest 必须显式传入策略或预算,消除默认规则不一致。
  • 增加同样认证保护的只读 POST /diagnostics/render-policy:提交原 Add body,校验指纹后仅返回已记录策略,不返回正文。评测逐请求查询,包括已完成的续跑请求,并生成包含逐消息策略的 v2 manifest。缺失或未知策略明确失败,不静默计成未召回。
  • 只有已知旧版服务缺少策略接口时,才能显式使用 --legacy-byte-rendering,且仅允许 HTTP 404 回退;检测到 v2 或其他错误仍拒绝。该选择纳入 resume contract。
  • v2 写入采用旧版不认识的 idempotent_tokens_v2 journal 协议,阻止旧版把已存分片误当作字节分片跳过。SQLite INSERT/UPDATE 触发器同时阻止旧版向 v2 请求的尚未写入位置登记 v1 意图。

验证

  • 全套测试 654 passed;最后格式版本/常量调整后,相关 83 项再次通过。Ruff、actionlint、diff 检查通过。
  • 混合 v1 与自定义 4,096-token 策略的实际本地 adapter/runner 合成集成测试:证据召回 100%、unmapped=0;manifest/reader 元数据匹配,续跑不重复 Add。
  • 策略接口覆盖鉴权、payload 指纹、已完成请求、预算变更后重启、缺失/无效策略和显式旧服务兼容。
  • 用真实旧 main(77a0270)代码进行回滚复现:修复前应写 3 片但仅存 1 片时,旧版错误返回成功并标记完成;修复后旧版在调用后端前返回 503、请求保持未完成,换回新版可补齐全部 3 片且原文完整。另覆盖已有位置和未写位置的数据库保护。
  • linux/amd64 镜像构建通过;断网、只读文件系统、512 MiB 限制下启动、分片、策略接口鉴权及缺失策略检查通过;再次修改应用源码构建时确认 tokenizer 下载层命中缓存。
  • 首次提交已完成实际 embedding 合成验证:18,333-token 旧文本返回 400;新分片为 7,676 / 7,663 / 3,028 token,均返回 200;本地新版 adapter 对接 Memoria 的 Add、重放和 Search 通过,无重复、原文完整。
  • 按 OCR delegate 规则完成本次 12/12 个可审文件自审(100%,无跳过),额外检查测试与 README。所有复现仅使用合成内容。

升级边界

旧 journal 请求保留 v1 字节分片规则,不会自动恢复旧的超限失败请求。 不清空 journal、不重新解释既有位置、不修改 request_id 绕过;这类请求需另行评估重放/迁移。

保留 journal schema/触发器,停止旧进程后升级。存在未完成 v2 请求时回滚旧二进制会明确失败;应恢复兼容新版继续,而非删除保护。切换 embedding 模型/tokenizer 仍须新增兼容策略。旧版 benchmark 检查点缺少分片策略契约,新 runner 会拒绝续跑;应保留旧结果,使用匹配 runner 或新建本地测试。

tokenizer 反复计数与额外 journal 读取的性能优化、Memoria 后端能力协商属于后续项;本次不改变已持久化的 v2 分片算法。

基于最新 main(77a0270)准备;合并后需要新镜像。尚未合并或更新任何环境。

Copy link
Copy Markdown
Contributor Author

已追加 commit 4a6b85c,处理本轮 review:

  1. 策略查询改为复用 call_adapter:最多 6 次请求尝试,保留已有退避、Retry-After、传输异常处理及脱敏 retry_audit。通过捕获最终 HTTPStatusError 保留显式旧版兼容的 404 回退,不增加额外探测请求;404/403 等不可重试错误不会重试。
  2. 补充回归:408/429/503/传输异常后恢复、重试正文/鉴权一致性、Retry-After、逐次审计和脱敏;持续 503 严格止于 6 次,保留完成 Add 检查点,恢复后 resume 只查询策略并继续 Search,不重发已成功 Add。旧版 404 兼容仍仅在显式开启时生效。
  3. 回滚文档补齐。第 2 条 review 中“大概率 500”不符合当前旧 main 的行为:用 77a0270 的真实 Journal 代码验证,触发器产生 IntegrityError 后,被旧版已有 sqlite3.Error 捕获转换为 HTTP 503 Idempotency journal unavailable;原始 cause 为 Unsupported rendering protocol,未写位置仍未落盘。提示不够明确属实,README 已说明应核对版本并恢复兼容二进制,保留 journal 和触发器。

验证:全套 659 passed;Ruff、diff 检查通过;完成修改范围代码自审。未合并或部署。

@loveRhythm1990
loveRhythm1990 merged commit 904b35e into main Oct 30, 2026
1 check passed
@loveRhythm1990
loveRhythm1990 deleted the fix/embedding-token-chunks branch October 30, 2026 15:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant