【Bug已解决】ChatGPT Android Remote creates usable but hidden threads with `model_provider=openai` ins...

发布时间:2026/7/18 17:57:37
【Bug已解决】ChatGPT Android Remote creates usable but hidden threads with `model_provider=openai` ins... 【Bug已解决】ChatGPT Android Remote creates usable but hidden threads withmodel_provideropenaiinstead of host config provider 解决方案原始报错线索ChatGPT Android Remote creates usable but hidden threads withmodel_provideropenaiinstead of host config providerAndroid 远程端在创建线程时错误地用了默认的model_provideropenai而不是宿主host配置里指定的 provider导致创建了「能用但看不见」的隐藏线程。一、现象长什么样用户在本机host配置了「用我自建的模型提供方 Provider-X」。然后通过 Android 远程端发起一个新对话线程线程能用但在本机宿主界面里看不到——它是「隐藏」的排查发现这个线程的model_provider是openai客户端硬编码默认值而不是宿主配置里的Provider-X因为 provider 不同线程被存到了另一套命名空间/账户下宿主视图自然不显示用户困惑明明在「我的配置」下建的怎么跑到了别处。 根因是远端客户端没继承宿主配置自作主张用了自己的默认值。二、背景配置作用域与继承配置通常有多层层级示例优先级全局默认model_provideropenai最低宿主配置host用户在桌面端设的Provider-X中本次请求显式参数调用时传的providerY最高正确解析应是显式参数 宿主配置 全局默认。远端客户端创建线程时应当拿到「宿主配置」这一层作为基础而不是退回到「全局默认」。三、为什么用错 provider根因3.1 远端不读取宿主上下文Android 远程端发起请求时没把「当前 host 的 config」带过去或宿主没下发给它于是它用了自己包里的默认openai。3.2 默认值优先级盖过宿主配置解析逻辑写成「有默认值就用默认值」宿主配置反被当成「可选项」没生效——优先级反转。3.3 创建与查询不在同一作用域线程创建时用了 provider A 的命名空间宿主查询时用 provider B 的命名空间两边对不上 → 隐藏。3.4 缺少「来源可追溯」创建出的线程没记录「它是用哪个 provider 创建的」事后无法审计为何隐藏。四、最小可运行复现默认值覆盖宿主配置下面演示「默认值优先级高于宿主配置」如何选错 providerdef resolve_provider_bad(explicit, host_config, defaultopenai): # 错误default 优先级最高 - 永远用 openai if default: return default if host_config: return host_config if explicit: return explicit return default if __name__ __main__: chosen resolve_provider_bad( explicitNone, host_configProvider-X, # 宿主配置指定了 X defaultopenai, ) print(错误解析得到:, chosen) # openai —— 覆盖了宿主配置默认值被当成最高优先级宿主的Provider-X被无视。五、解决方案一正确的优先级链显式 宿主 默认解析顺序必须「显式最高、默认最低」def resolve_provider(explicit, host_config, defaultopenai): 优先级显式参数 宿主配置 全局默认。 if explicit is not None: return explicit if host_config is not None: return host_config return default if __name__ __main__: print(resolve_provider(None, Provider-X)) # Provider-X ✅ 宿主配置生效 print(resolve_provider(Provider-Y, Provider-X)) # Provider-Y ✅ 显式覆盖把「默认」放到最低优先级宿主配置自然生效解决 3.2。六、解决方案二远端必须继承宿主上下文远端客户端创建资源前先从宿主拉取「有效配置快照」用快照作为基础def build_thread_request(remote_input, host_config_snapshot): 远端发起创建线程以宿主配置快照为基础仅允许显式覆盖。 base { model_provider: host_config_snapshot.get(model_provider), # 来自宿主 scope: host_config_snapshot.get(scope), # 同命名空间 } # 远端传来的显式参数可覆盖但默认不覆盖宿主 for k, v in (remote_input or {}).items(): if v is not None: base[k] v return base if __name__ __main__: host {model_provider: Provider-X, scope: host-ns} req build_thread_request({}, host) # 远端没传 - 用宿主 print(创建线程用:, req) # model_providerProvider-X, scopehost-ns远端以宿主快照为基线程自然落在宿主可见的命名空间不再隐藏解决 3.1/3.3。七、解决方案三记录「创建来源」便于审计每条创建的线程都带上「用了哪个 provider、来自哪层配置」事后可查为何隐藏import time def create_thread(req, resolved_provider, source_layer): thread { id: fth_{int(time.time())}, model_provider: resolved_provider, provider_source: source_layer, # explicit / host / default visible_to_host: resolved_provider req.get(expected_host_provider), } return thread if __name__ __main__: req {expected_host_provider: Provider-X} t create_thread(req, Provider-X, host) print(t) # visible_to_hostTrue来源清楚 t2 create_thread(req, openai, default) print(t2) # visible_to_hostFalse立刻能看出错配provider_source让「是否隐藏」可立即判定审计/排查一目了然。八、跨端一致性要点单一配置服务宿主与远端都从同一配置服务解析避免各自维护默认下发而非各猜宿主在远程会话建立时把有效配置下发远端不自己编默认值作用域绑定线程的可见性由其scope/provider决定创建时必须和查询时同源变更同步宿主改了 provider进行中的远程会话应收到更新。九、排查清单「远程端用错 provider 创建隐藏线程」按下面排查优先级链对吗是否显式 宿主 默认第五节远端是否继承宿主配置还是用自己的默认值第六节创建与查询同作用域吗provider/scope 是否一致是否记录创建来源provider_source可追溯吗第七节默认值是否硬编码在客户端应来自配置服务而非写死宿主改配置后远程会话同步了吗隐藏线程能否被检索到可见性是否可判定第七节visible_to_host日志是否打印实际解析到的 provider。十、小结「远程客户端用错 provider 创建隐藏线程」的根因是配置解析优先级反转 远端不继承宿主上下文导致用客户端默认值而非宿主配置线程落到错误命名空间而隐藏。通用修复正确优先级显式 宿主 默认默认永远最低第五节继承宿主快照远端以宿主下发的配置快照为基础仅显式参数可覆盖第六节记录来源每条资源带provider_source可见性可立即判定跨端一致单一配置服务 下发 变更同步第八节呼应第 104/112 篇。 一句话远端替用户创建资源时绝不能用「自己的默认值」冒充「用户的配置」配置必须沿「显式 → 宿主 → 默认」的链解析且创建与查询必须同源。把配置来源钉死就不会再出现「能用却看不见」的幽灵线程——这与第 104 篇偏好持久化、第 105 篇数据源聚合、第 112 篇跨设备同步共同指向「分布式环境下的配置必须单一真相源且可追溯」。