chore: T-P-1 工作区收敛——并行会话成果与历史未入库文件整理入库
- 入库历史遗漏源码/测试:router_system 9 模块(agent/executors/inference/knowledge/ memory/planner/skills/trace)、tests 11 个测试文件、config/knowledge 领域知识 - 入库根目录方案文档(v2/v3/可行性×2)、references 文献(arxiv 14-18/cnki_open/ 参考文献清单)、research 论文素材(routerarena/paper/中文文献 PDF) - 前端构建产物刷新(新 hash);webapp 误写文档删除 - gitignore 增补:deepseek-harness、research/_refs、.mimosa/.zcode、网关日志/pid、 临时调试脚本、tests/e2e/node_modules、AI代理功能开发/prefix - 基线确认:318 passed
This commit is contained in:
@@ -0,0 +1,302 @@
|
||||
# 实施方案:校园 AI 代理层与缓存层(T-P0…T-P8 逐任务执行版)
|
||||
|
||||
> 编写日期:2026-09-05 状态:**执行版**(设计依据见《方案_校园AI代理层.md》;两者冲突时以本文为准)
|
||||
> 预期读者:负责实现的 AI Agent。实现前必读:第 1 节锁定决策、第 9 节测试纪律。
|
||||
> 总工期估算:约 13 个工作日;里程碑 M1(计费代理)→ M2(缓存栈)→ M3(管理面+验收)。
|
||||
|
||||
---
|
||||
|
||||
## 0. 范围与非目标
|
||||
|
||||
**范围**:现有 FastAPI app 内新增代理面(`/proxy/v1/*`)+学生 key 鉴权计费+两级缓存(精确→n-gram 语义)
|
||||
+管理端点与前端页+压测报告。
|
||||
|
||||
**MVP 非目标**(做了算超纲,除非另有指示):多上游 key 轮换/前缀亲和、embedding 向量检索
|
||||
(预留 embedder 接口,M3 可选)、空闲时段自动调度(仅实现 `is_offpeak(ts)` 判定)、流式中途
|
||||
failover、内容审核、多币种。
|
||||
|
||||
**不改动**:`router_system/`(只允许 import `router_system.cache`);现有 `/chat`、`/agent`、
|
||||
`/review` 行为与全部既有测试。
|
||||
|
||||
---
|
||||
|
||||
## 1. 锁定决策(实现中不得擅改)
|
||||
|
||||
- **D-P1 货币**:账本一律**毫元整数**(1 元 = 1000 毫元),禁止浮点;展示层格式化。
|
||||
- **D-P2 桶来源**:请求头 `X-Campus-Bucket`(缺省 `default`);`model→bucket` 可在配置映射。
|
||||
- **D-P3 上游条目**:复用 `config/model_pool.json`,条目新增可选字段
|
||||
`"provider": "deepseek|openai|anthropic"`(usage 归一化用)与 `"in_hit_price"`(可选,缺省 = in_miss×1/30)。
|
||||
- **D-P4 failover**:仅在上游**首 token 返回前**允许切换;流中失败 = `aborted`,按已收 usage 计费
|
||||
(无 usage 按字符估算),**不写缓存**。
|
||||
- **D-P5 缓存准入**:只缓存 `finish_reason=="stop"` 的**完整单轮**响应;错误/超时/断连/多轮一律不缓存。
|
||||
- **D-P6 依赖纪律**:M1/M2 **零新第三方依赖**(语义缓存用 stdlib 倒排 n-gram);embedding + numpy
|
||||
属 M3 可选项,启用须登记 requirements.txt 并说明理由。
|
||||
- **D-P7 开关**:`proxy.enabled == false` 时不注册任何 `/proxy` 路由,行为与现状逐字节一致。
|
||||
- **D-P8 凭据**:上游主 key 只从 env / `config/settings.json`(已 gitignore)读取,代码/测试零字面量。
|
||||
- **D-P9 进程模型**:**uvicorn 单进程(workers=1)是正确性前提**——singleflight、令牌桶、内存 LRU
|
||||
均为进程内状态,多 worker 会静默失效(限流失效/重复打上游)。扩容路径只有性能预算触发的
|
||||
数据面手术(方案 §3.5),不存在"加 worker"这个选项。
|
||||
- **D-P10 DB 访问纪律**:sqlite3 是同步库,**所有 DB 调用必须经 `asyncio.to_thread`**(写路径可进一步
|
||||
收敛为单写线程+队列);连接 `check_same_thread=False` + `threading.Lock` 串行化写。
|
||||
热路径读(key→学生上下文)走进程内缓存:哈希→(student_id,status,caps) 的 LRU,TTL 30s,写后失效。
|
||||
违反此条,T-P8 的 P99 ≤50ms 会被同步 DB 卡死。
|
||||
- **D-P11 计费两阶段(防并发超扣)**:预扣用**原子 UPDATE**:
|
||||
`UPDATE students SET balance_milli=balance_milli-? WHERE id=? AND balance_milli>=?`(rowcount=0 即 402),
|
||||
est = in_miss 价×字符估算 + out 价×min(max_tokens,4096)(宁可高估);settle 按真实 usage 回补
|
||||
est−actual 差额;void 全额退。不用 holds 表,一条 SQL 解决竞态。
|
||||
|
||||
---
|
||||
|
||||
## 2. 文件清单
|
||||
|
||||
**新建**:
|
||||
```
|
||||
gateway/proxy/
|
||||
├── __init__.py # build_proxy_router(settings, pool) -> APIRouter;唯一组装点
|
||||
├── config.py # ProxyConfig:从 settings 读取 + 校验 + 默认值
|
||||
├── errors.py # ProxyAuthError(401)/QuotaError(429)/BalanceError(402)/UpstreamError(502)
|
||||
├── auth.py # key 签发/校验/注销 + 令牌桶 + 日限额
|
||||
├── ledger.py # DDL 初始化 + students/keys CRUD + hold/settle/void + 日志写入
|
||||
├── pricing.py # PriceTable + is_offpeak(ts) + compute(usage, model, ts) -> CostBreakdown
|
||||
├── normalizer.py # bucket 解析 + 规范化哈希 + PrefixShaper(整形后请求体)
|
||||
├── semcache.py # 精确 L1 + n-gram 倒排 L2 + TTL/版本失效 + singleflight
|
||||
├── upstream.py # httpx 流式派发 + usage 三家归一化 + 首 token 前 failover
|
||||
└── routes.py # /proxy/v1/chat/completions、/proxy/v1/models、/proxy/admin/*
|
||||
scripts/bench_proxy.py # E-P1/E-P2 数据管道:200 条校园模拟请求 → 命中率/毛利报告
|
||||
webapp/src/views/ProxyView.vue
|
||||
tests/test_proxy_{auth,ledger,pricing,normalizer,semcache,upstream,routes}.py
|
||||
```
|
||||
|
||||
**修改**:`gateway/api.py`(`app.include_router`,受 `proxy.enabled` 门控,≤5 行);
|
||||
`webapp/src/App.vue`(NAV 加"代理"项);`config/model_pool.json`(条目加 provider/in_hit_price);
|
||||
`任务拆解与执行计划.md`、`AGENTS.md`(登记)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据模型(SQLite DDL,库文件 `data/proxy.sqlite3`,WAL 模式)
|
||||
|
||||
```sql
|
||||
CREATE TABLE students(
|
||||
id INTEGER PRIMARY KEY, name TEXT NOT NULL, class TEXT DEFAULT '',
|
||||
status TEXT NOT NULL DEFAULT 'active', -- active|suspended
|
||||
balance_milli INTEGER NOT NULL DEFAULT 0,
|
||||
daily_cap_milli INTEGER NOT NULL DEFAULT 5000,
|
||||
spent_today_milli INTEGER NOT NULL DEFAULT 0, spent_date TEXT DEFAULT '');
|
||||
|
||||
CREATE TABLE proxy_keys(
|
||||
id INTEGER PRIMARY KEY, key_hash TEXT UNIQUE NOT NULL, key_prefix TEXT NOT NULL,
|
||||
student_id INTEGER NOT NULL REFERENCES students(id),
|
||||
created_ts INTEGER NOT NULL, revoked INTEGER NOT NULL DEFAULT 0,
|
||||
rpm_cap INTEGER NOT NULL DEFAULT 10, day_cap_req INTEGER NOT NULL DEFAULT 200,
|
||||
req_today INTEGER NOT NULL DEFAULT 0, req_date TEXT DEFAULT '');
|
||||
|
||||
CREATE TABLE usage_ledger(
|
||||
request_id TEXT PRIMARY KEY, ts INTEGER NOT NULL, key_id INTEGER NOT NULL,
|
||||
model TEXT NOT NULL, bucket TEXT NOT NULL DEFAULT 'default',
|
||||
in_miss_tok INTEGER NOT NULL DEFAULT 0, in_hit_tok INTEGER NOT NULL DEFAULT 0,
|
||||
out_tok INTEGER NOT NULL DEFAULT 0, gateway_cached INTEGER NOT NULL DEFAULT 0,
|
||||
upstream_cost_milli INTEGER NOT NULL DEFAULT 0, charged_milli INTEGER NOT NULL DEFAULT 0,
|
||||
margin_milli INTEGER NOT NULL DEFAULT 0, ttfb_ms INTEGER, total_ms INTEGER,
|
||||
status TEXT NOT NULL); -- ok|cached|error|aborted|insufficient
|
||||
|
||||
CREATE TABLE semcache(
|
||||
cache_key TEXT PRIMARY KEY, -- bucket + '|' + sha256(norm_q)
|
||||
bucket TEXT NOT NULL, q_norm TEXT NOT NULL, answer TEXT NOT NULL, model TEXT NOT NULL,
|
||||
created_ts INTEGER NOT NULL, ttl_ts INTEGER NOT NULL,
|
||||
doc_version INTEGER NOT NULL DEFAULT 1, hits INTEGER NOT NULL DEFAULT 0);
|
||||
CREATE INDEX idx_semcache_bucket ON semcache(bucket, ttl_ts);
|
||||
CREATE INDEX idx_ledger_ts ON usage_ledger(ts); -- stats 按时间范围聚合用
|
||||
```
|
||||
|
||||
前缀资料文件(`doc_prefix_file` 指向的 txt)不入库不入 git(内容属课程方),gitignore 加
|
||||
`AI代理功能开发/prefix/`。
|
||||
|
||||
---
|
||||
|
||||
## 4. 配置 schema(settings.json 的 `proxy` 段)
|
||||
|
||||
```jsonc
|
||||
"proxy": {
|
||||
"enabled": true,
|
||||
"admin_key": "",
|
||||
"buckets": {
|
||||
"default": {"system_template": "你是校园学习助手。", "doc_prefix_file": null,
|
||||
"doc_version": 1, "ttl_hours": 72},
|
||||
"course_python": {"system_template": "你是 Python 课程助教。",
|
||||
"doc_prefix_file": "AI代理功能开发/prefix/python24.txt",
|
||||
"doc_version": 1, "ttl_hours": 168}
|
||||
},
|
||||
"pricing": { // 上游成本价:元/1M tokens;示例为 Flash 档高峰价,以官网价目为准
|
||||
"deepseek-chat": {"in_miss": 3.0, "in_hit": 0.1, "out": 9.0},
|
||||
"peak_window": {"start": "08:30", "end": "23:59"}, // 窗口外按 off-peak 系数 0.5
|
||||
"offpeak_factor": 0.5,
|
||||
"sale_discount": {"in": 0.5, "out": 0.5} // 学生售价折扣
|
||||
},
|
||||
"limits": {"rpm_per_key": 10, "day_req_cap": 200, "concurrent_per_key": 2,
|
||||
"max_body_chars": 60000},
|
||||
"semcache": {"enabled": true, "sim_threshold": 0.92, "max_entries": 300000,
|
||||
"promote_frequency": 5}
|
||||
}
|
||||
```
|
||||
|
||||
峰值/空闲窗口与官方"高峰时段"定义对齐,上线前按官网核对一次。
|
||||
|
||||
---
|
||||
|
||||
## 5. API 契约
|
||||
|
||||
### 5.1 学生面(OpenAI 兼容)
|
||||
- `POST /proxy/v1/chat/completions`,`Authorization: Bearer sk-campus-…`,
|
||||
body = OpenAI chat 格式 + 可选头 `X-Campus-Bucket`。**计量不依赖客户端行为**:
|
||||
代理向上游始终注入 `stream_options: {"include_usage": true}`,客户端未要求 usage 时
|
||||
过滤该 chunk 不下发。响应与客户端请求同构:stream=true 收 SSE,stream=false 收 JSON;
|
||||
**缓存命中也按此回放**(SSE 合成,见 §6)。
|
||||
- `GET /proxy/v1/models` → 池内允许的模型名列表。
|
||||
|
||||
### 5.2 管理面(X-Admin-Key 鉴权,见本节末)
|
||||
| 端点 | 说明 |
|
||||
|---|---|
|
||||
| `POST /proxy/admin/students` | 建学生 {name, class, balance_yuan, caps} |
|
||||
| `POST /proxy/admin/students/{id}/topup` | {amount_yuan} 充值 |
|
||||
| `POST /proxy/admin/keys` | {student_id, rpm_cap?, day_cap_req?} → **明文 key 只返回一次** |
|
||||
| `POST /proxy/admin/keys/{id}/revoke` | 注销 |
|
||||
| `GET /proxy/admin/stats` | {requests, h_g, h_p, revenue, cost, margin, by_bucket} |
|
||||
| `GET /proxy/admin/ledger?student_id=&limit=&offset=` | 流水分页 |
|
||||
|
||||
**管理面鉴权**:请求头 `X-Admin-Key` 与 `settings.proxy.admin_key` 比对
|
||||
(`hmac.compare_digest`,防时序侧信道);未配置 admin_key 时仅放行 loopback 来源。
|
||||
**stats 口径**:h_g = cached/requests;h_p = Σin_hit/(Σin_hit+Σin_miss);revenue=Σcharged、
|
||||
cost=Σupstream_cost、margin=Σmargin;支持 `?since=<ts>` 走 idx_ledger_ts。
|
||||
归档:usage_ledger 超 180 天的行由 T-P8 顺带清理(年度 650 万行会拖慢聚合)。
|
||||
|
||||
### 5.3 错误码
|
||||
401 无效/注销 key;403 学生 suspended;402 余额或日上限不足;429 限流;
|
||||
502 上游失败(首 token 前 failover 均失败);body 超 `max_body_chars` → 413。
|
||||
|
||||
---
|
||||
|
||||
## 6. 模块接口签名(实现按此,不改名)
|
||||
|
||||
```python
|
||||
# auth.py
|
||||
def issue_key(ledger, student_id, rpm_cap=None, day_cap_req=None) -> str # 明文仅此一次
|
||||
def authenticate(authorization: str, ledger, limits, now) -> AuthContext # raises ProxyAuth/Quota
|
||||
class RateLimiter: allow(key_id, rpm_cap) -> bool
|
||||
|
||||
# ledger.py
|
||||
class Ledger:
|
||||
def init_db(cls, path) -> Ledger
|
||||
def upsert_student / topup / set_status(...)
|
||||
def check_and_count(key_id, student_id, now) -> None # 日限额双检
|
||||
def try_hold(student_id, est_milli) -> bool # 原子预扣(D-P11),False=402
|
||||
def settle(request_id, actual_milli, ...) -> None # 结算 + 回补 est-actual 差额
|
||||
def void(request_id) -> None # 全额退(上游失败)
|
||||
def record(UsageRow) -> None # 幂等:request_id 主键
|
||||
|
||||
# pricing.py
|
||||
def is_offpeak(ts, window) -> bool
|
||||
def compute(usage: Usage, model: str, ts: int, cfg) -> CostBreakdown
|
||||
# CostBreakdown: upstream_cost_milli, charged_milli, margin_milli(全整数毫元)
|
||||
|
||||
# normalizer.py
|
||||
def resolve_bucket(body, headers, cfg) -> BucketCfg
|
||||
def canonical_hash(bucket, doc_version, body) -> str # 稳定序列化→sha256
|
||||
def shape(body, bucket_cfg) -> dict # 整形后上游请求体
|
||||
|
||||
# semcache.py
|
||||
class SemanticCache:
|
||||
def lookup(bucket, doc_version, norm_hash, norm_text, now) -> Hit|None
|
||||
def put(bucket, doc_version, norm_hash, norm_text, answer, model, now) -> None
|
||||
def stats() -> {entries, hits, h_g}
|
||||
|
||||
# upstream.py —— 模块级 httpx.AsyncClient 单例(keepalive;limits.max_connections=100),
|
||||
# 超时 connect=10s / read=120s(流式整段)/ write=10s / pool=30s;始终注入 include_usage(§5.1)。
|
||||
async def stream(body, entry, usage_sink) -> AsyncIterator[bytes]
|
||||
def normalize_usage(provider, usage_dict) -> Usage # 三家字段→统一 Usage
|
||||
```
|
||||
|
||||
**规范化规则(normalizer,决定缓存命中率的代码,测试最重)**:
|
||||
1. messages 序列化:role 与 content 交替拼接为 `role\u0001content\u0002`;
|
||||
2. 剔除易变字段:`temperature/frequency_penalty/seed/request_id/时间戳类内容行`;
|
||||
3. 系统模板与资料前缀**不参与** L1 哈希(桶+doc_version 已表达),只参与上游整形;
|
||||
4. 整形后消息顺序固定:`[canonical_system] → [doc_prefix] → [原 messages]`;
|
||||
5. 多轮判定:`len(messages) > 2`(system 之外 >1 条)→ `cacheable=False`。
|
||||
|
||||
**语义相似度精确定义(semcache L2,误命中=返回错答案,此节测试最重)**:
|
||||
- q_norm 取**字符 2-gram + 3-gram 集合**(中文天然适配,无需分词);
|
||||
- 倒排索引驻内存(gram→cache_key 列表),**启动时由 semcache 表 q_norm 重建**;
|
||||
- 候选门限:共享 gram ≥3 才计分(避免全量比对);分数 = 加权 Jaccard(3-gram 权 2、2-gram 权 1);
|
||||
- ≥ sim_threshold(0.92) 判命中;**L2 语义命中累计 promote_frequency(5) 次后晋升为 L1 精确条目**
|
||||
(复用 v1 cache.py 的提升模式——考试周变体收敛后自动加速)。
|
||||
|
||||
**SSE 合成回放(缓存命中的流式客户端兼容)**:命中时按请求 stream 字段同构返回——
|
||||
stream=true 则用缓存内容合成 SSE(复用缓存 id/format,content 按 ~20 字符分块 +
|
||||
finish_reason=stop + `data: [DONE]`),stream=false 返回标准 JSON。
|
||||
**禁止**对 stream=true 客户端直返 JSON(OpenAI SDK 会解析失败)。
|
||||
|
||||
---
|
||||
|
||||
## 7. 请求处理时序(routes.py 主流程)
|
||||
|
||||
```
|
||||
auth(热路径缓存) → 限流/日额 → body 校验(413) → bucket/规范化 → L1 精确查 → L2 n-gram 查
|
||||
├命中: settle(cached, cost=0, charged=按售价) → SSE/JSON 同构回放(§6)
|
||||
└未命中: singleflight 登记 → try_hold(est 原子预扣,不足 402) → shape(body) → upstream.stream
|
||||
→ tee: 逐块转发客户端 + 累积(含被过滤的 usage chunk)
|
||||
→ 结束: usage 归一化 → compute → settle(actual,回补差额) → (stop 且单轮)semcache.put
|
||||
→ 异常: void 退预扣 / aborted 按已收 usage 记账;均不缓存;singleflight 广播同一结果
|
||||
```
|
||||
|
||||
singleflight:`dict[norm_hash → asyncio.Future]`,**上限 256 条**(超出旁路不合并,防考试周
|
||||
变体洪峰撑爆内存);第二个到达者 await 同一 Future;等待方 60s 超时自行降级直连。
|
||||
|
||||
---
|
||||
|
||||
## 8. 测试计划
|
||||
|
||||
| 文件 | 必测用例 |
|
||||
|---|---|
|
||||
| test_proxy_auth | 签发→鉴权通过;错 key 401;注销 401;rpm 429;日请求上限 429 |
|
||||
| test_proxy_ledger | hold/settle/void 全链条(预扣-结算-回补一致);request_id 幂等;日限额跨日重置(注入日期);**并发 N 路同时预扣,余额不足者精确拒绝、不超扣** |
|
||||
| test_proxy_pricing | 峰谷边界(假时钟 ±1 分钟);毫元取整不漂移(≥10 组黄金用例);margin = charged − cost |
|
||||
| test_proxy_normalizer | 同语义输入同哈希;易变字段剔除;整形顺序固定;doc_version+1 后旧缓存不可见;多轮 cacheable=False |
|
||||
| test_proxy_semcache | 精确命中;n-gram 阈值上命中/下未中;TTL 过期(假时钟);失败不缓存;entries 上限 LRU |
|
||||
| test_proxy_upstream | 三家 usage 形状归一;SSE 透传逐字节一致;首 token 前 failover;流中失败=aborted;**usage 注入且客户端未要求时被过滤** |
|
||||
| test_proxy_routes | 端到端:缓存命中账目(cost=0,charged>0,cached=1);未命中全程;402/429/413;singleflight 两并发一次上游(计数 Mock);**stream=true 命中回放为合法 SSE**;**L2 命中 5 次后 L1 直接命中** |
|
||||
|
||||
**隔离清单**:每测试独立 `tmp_path/proxy.sqlite3`;假时钟注入(禁 sleep);MockTransport 假上游;
|
||||
不动 `config/settings.json` 真实文件(沿用 v4 事故后的备份/恢复模式)。
|
||||
|
||||
---
|
||||
|
||||
## 9. WBS:T-P0…T-P8(依赖顺序执行,每任务一 commit `feat(proxy): T-Pn 描述`)
|
||||
|
||||
| # | 任务 | 产出/步骤 | 验收(可执行命令级) | 估时 |
|
||||
|---|---|---|---|---|
|
||||
| T-P0 | 骨架 | gateway/proxy/ 六文件空实现 + DDL + 挂路由(enabled 门控) | `pytest tests -q` 全绿(318→新增骨架测试);开关关闭时 `/proxy/*` 404 | 0.5d |
|
||||
| T-P1 | 鉴权+账本 | auth.py + ledger.py(原子预扣 try_hold/settle/void + 热路径缓存)+ 管理端点 | test_proxy_auth/ledger 全绿;并发预扣不超扣;curl 用签发 key 过 401 | 2d |
|
||||
| T-P2 | 上游客户端 | upstream.py:AsyncClient 单例/超时/流式派发 + usage 注入与过滤 + 三家归一化 + failover | test_proxy_upstream 全绿;curl 流式可见逐块输出 | 2d |
|
||||
| T-P3 | 计价+结算 | pricing.py + 账本结算接线 | test_proxy_pricing 全绿(≥10 黄金用例) | 1d |
|
||||
| T-P4 | 路由端到端 | routes.py 主时序(不含缓存分支) | OpenAI SDK 指 `/proxy/v1` 对话成功;账本三值一致;402/429/413 正确 | 1.5d |
|
||||
| T-P5 | 规范化+桶 | normalizer.py + 配置桶 | test_proxy_normalizer 全绿 | 1d |
|
||||
| T-P6 | 语义缓存 | semcache.py(含倒排索引重建/晋升/LRU)+ SSE 合成回放 + singleflight + 接线 + `scripts/warm_prefix.py`(桶前缀预热,max_tokens=1) | test_proxy_semcache 全绿;两并发同请求上游仅 1 次;stream=true 命中回放合法 SSE | 2.5d |
|
||||
| T-P7 | 管理面+前端 | stats/ledger 端点 + ProxyView.vue(三卡片) | 看板真实数据渲染;`npm run build` 产物更新 | 2d |
|
||||
| T-P8 | 压测+预算 | scripts/bench_proxy.py:200 条(重复≥50%)+200 并发;**`--live` 模式**(真实 key 50 条子集测真实 h_p,mock 模式 h_p 为可配置常数仅供联调);顺带 ledger >180d 归档清理 | P99 附加延迟≤50ms;内存≤1GB;账目零不一致;报告入 `AI代理功能开发/bench/` | 1.5d |
|
||||
|
||||
依赖链:T-P0 → T-P1 → T-P2 → T-P3 → T-P4 → (T-P5 → T-P6) → T-P7 → T-P8。
|
||||
**总验收 = M1(T-P0..4) + M2(T-P5..6) + M3(T-P7..8)**:E-P1 报告显示 h_g+h_p ≥ 50% 且统一 5 折毛利为正
|
||||
(**h_p 须以 `--live` 实测为准**——mock 上游给不出真实的 prompt_cache_hit_tokens)。
|
||||
|
||||
---
|
||||
|
||||
## 10. 风险与回滚
|
||||
|
||||
| 风险 | 对策 |
|
||||
|---|---|
|
||||
| n-gram 语义误命中(相似≠可答) | 阈值 0.92 起步 + 桶隔离 + TTL;E-P3 抽检正确率,误答率高先调阈值再考虑 M3 embedding |
|
||||
| 单进程瓶颈 | 性能预算压测(T-P8)触发才议数据面手术(见方案 §3.5) |
|
||||
| 上游调价 | 价格表纯配置热改;model_pool 多供应商条目 |
|
||||
| 账目漂移 | 毫元整数(D-P1)+ request_id 幂等 + T-P8 账目零不一致验收 |
|
||||
| 测试污染真实配置 | 隔离清单 + settings 备份/恢复模式(v4 事故先例) |
|
||||
| 误改多 worker 部署 | D-P9 写入部署文档与 serve.py 启动参数校验(workers>1 时拒绝启动并提示) |
|
||||
| 同步 DB 卡事件循环 | D-P10 强制 to_thread + 代码评审清单项;T-P8 压测显式测 DB 路径 P99 |
|
||||
Reference in New Issue
Block a user