fix(memory): embedding 批上限与超时同源 —— 不再「客户端先放弃、服务端继续算」
M9(EMBRECALL)。故障机制(M6 + 本次复测):客户端 5s 单次超时先放弃,服务端仍在 算那一批 ⇒ 本机 llama.cpp 被自己顶住 ⇒ 后续每个请求(含写向量索引的单条请求) 排队到自己的超时 ⇒ 召回全线降级。 - embedding/budget.go(新):把「一次请求的耗时上界 ≤ 单次超时的一半」写成不变式, 批上限(条数 4 / 字符 480)与 5s 超时由**同一个不等式**解出;实测依据与复跑命令 写进注释(空闲态摊销曲线 1→0.19s / 8→1.1s / 12→1.3s / 64→8.5s,约 50ms 固定 + 2.7~3.9ms/字符,n≥32 起有数倍放大 ⇒ 余量取一半)。 - embedding/api.go:Embed 按同一对上限**自己切片**(不变式与调用方无关);冷启动 首次调用单独给 warmupTimeout,拿到第一个成功响应后立刻回常态超时。 - memory/tidy_config.go:tidyEmbedBatch = embedding.DefaultBatchLimit(同源), 并加编译期断言 —— 调回 64 会直接编译失败(constant -60 overflows uint)。 - memory/tidy.go | tidy_recall.go | tidy_dryrun.go:recall_mode 改报**实际发生** 的来源(""=本轮没候选可比 / embedding / lexical / mixed),新增 recall_degraded_partitions;试算轮 RecallMode 同口径(M6 medium finding)。 - 测试:embedding 侧用「实测曲线 + 会睡够时间的假客户端」钉住两态 (批内 < 超时 ⇒ 不降级;旧配对 64 条 ⇒ 必然超时),并断言 abandoned == 0; memory 侧钉住降级/健康/没候选三态与试算轮的如实上报。 不改 preinsert*、不改 .env、不动判定规则与任何阈值。
This commit is contained in:
1 parent
68ba85389b
commit
59672720bd
9 files changed
+836
-45
No files matched your search
@@ -222,6 +222,10 @@ const reviewBudgetRef = 20 * time.Second
|
||||
// 审查总预算:否则一次卡死的 embedding 连接就能吃光整条审查的预算,排在后面的
|
||||
// T1 灰区判定连执行机会都没有(2026-10-07 实测故障形态)。同时验证该超时确实
|
||||
// 打在了发出去的请求上。
|
||||
//
|
||||
// ⚠️ 冷启动那一次走的是 warmupTimeout(见 budget.go),因此这里**以稳态请求**
|
||||
// (第二次及以后)为准;冷启动那一路由 budget_test.go 的
|
||||
// TestAPIEmbedder_WarmupFirstCallBudget 单独钉。
|
||||
func TestDefaultRequestTimeout(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -256,8 +260,12 @@ func TestDefaultRequestTimeout(t *testing.T) {
|
||||
config.EmbeddingConfig{APIURL: "http://127.0.0.1:11434/v1/embeddings"},
|
||||
WithRoundTripper(rt),
|
||||
)
|
||||
if _, err := emb.Embed(context.Background(), []string{"hi"}); err != nil {
|
||||
t.Fatalf("Embed() error: %v", err)
|
||||
// 第一次是冷启动调用(warmupTimeout),结果由它自己的测试断言;这里连发两次,
|
||||
// 只看稳态那一次打出去的 deadline。
|
||||
for i := 0; i < 2; i++ {
|
||||
if _, err := emb.Embed(context.Background(), []string{"hi"}); err != nil {
|
||||
t.Fatalf("第 %d 次 Embed() error: %v", i+1, err)
|
||||
}
|
||||
}
|
||||
if slack <= 0 || slack > DefaultRequestTimeout {
|
||||
t.Fatalf("请求 deadline 余量 = %s, want (0, %s]", slack, DefaultRequestTimeout)
|
||||
|
||||
Reference in new issue
Block a user