mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
内核不再硬编码对外 wire。writeChatCompletion / pumpStream 里的 OpenAI 帧拼装抽到 Serializer 接口,适配器可声明钩子完全接管。 优先级契约(用户明确要求:冲突时兜底直接让步): 适配器声明 serialize_* -> 适配器完全接管 未声明 -> 兜底 openAISerializer 「让步」的含义:适配器接管后内核绝不往其输出补任何 OpenAI 字段。混合体 (半个 Anthropic + 半个 OpenAI)比任何一个单独结果都更难排查——客户端无法 解析,而排查时会指向错误的层。 接口把「流如何结束」也纳入:OpenAI 需 usage 帧 + [DONE],Anthropic 用 message_stop,Gemini 用空 candidates 帧。DoneMarker 让适配器声明自己的 终止标记,避免擅自给严格客户端加 [DONE]。 新增能力: - VM.HasFn(name, fn):不占 worker 探测适配器是否声明某函数 - VM.AdapterRevision(name):适配器源码每次替换 +1(接着旧值递增) 修掉两个开发中引入的真实缺陷: 1. 锁序倒置自死锁:LoadAdapterSource 里在已持有 v.mu.Lock() 时嵌套 v.mu.RLock() 取 revision,RWMutex 不可重入 -> 整个测试套件静默挂起。 症状是不报错也不超时,只是永不返回;靠 go test -timeout 的 goroutine 栈定位。 2. 缓存键漏掉 VM 维度:serializerCache 原按适配器名做键,导致同进程内两个 VM 共享判定,适配器重写后新钩子永不生效且不报错。键改为 (VM, revision, adapter),回归测试 TestSerializerCacheIsPerVM。 测试三件套: - 功能:适配器接管 / 兜底(无适配器)/ 钩子失败退回兜底 / 缓存随改写失效 - 压力:TestSerializerForConcurrent(16 worker × 40 次) - 回归:golden 字节级未漂移,Phase 0 安全网生效 验证:go test -tags luajit ./... 全绿(gateway 200s / lua 56s)。