【开源】切 provider 避免丢会话:Codex-Threadripper(Codex实用小工具系列第一弹)

本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社...
【开源】切 provider 避免丢会话:Codex-Threadripper(Codex实用小工具系列第一弹)
【开源】切 provider 避免丢会话:Codex-Threadripper(Codex实用小工具系列第一弹)
本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容:
  • 我的帖子已经打上 开源推广 标签:
  • 我的开源项目完整开源,无未开源部分:
  • 我的开源项目已链接认可 LINUX DO 社区:
  • 我帖子内的项目介绍,AI生成、润色内容部分已截图发出:
  • 以上选择我承诺是永久有效的,接受社区和佬友监督:

以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出


前言 (点击了解更多详细信息)

这是什么

github.com

GitHub - Wangnov/codex-threadripper: Keep Codex thread history aligned to one provider...

Keep Codex thread history aligned to one provider bucket.

这是 Codex 线程撕裂者,专门用于撕裂线程之间的隔阂(中二病爆发)。解决在$CODEX_HOME/config.toml 里使用 model_provider 来切换不同 API 供应商后,却发现 Codex APP 里以前在别的 Provider 下的会话不见了,CLI 里的 codex resume 也找不到会话了的问题。

切 Provider 的方法如下:

model_provider = "test" # 在这里修改来切换

[model_provider.test]
name = "test"
wire_api = "responses"
base_url = "https://a.me/v1"
experimental_bearer_token = "sk-xxx"

[model_provider.test1]
name = "test1"
wire_api = "responses"
base_url = "https://a.me/v1"
experimental_bearer_token = "sk-xxx"

以下为 AI 写的 README 截图:

README截图

效果如何

使用前:

76f09b2f1d678d470a9b76b3c256fcc1

使用后:

760908f4d8a05981fe2d5fd96d46a913

可以看到,撕裂之后,所有的在各种不同 Provider 下的会话都能在 APP 里看到了。

如何安装

Homebrew

brew tap wangnov/tap
brew install codex-threadripper

npm

npm i -g codex-threadripper

cargo-binstall

cargo binstall codex-threadripper

cargo install

cargo install codex-threadripper

直接在 Release 里下载二进制

GitHub

Release v0.1.8 · Wangnov/codex-threadripper

Install codex-threadripper 0.1.8 Install prebuilt binaries via shell script curl --proto '=https' --tlsv1.2 -LsSf https://github.com/Wangnov/codex-threadripper/releases/download/v0.1.8/codex-thread...

如何运行

这里就直接复制 README 了:

image

使用效果如下:

image

毫秒级解决!

咋做到的

简述一下这个项目的原理和设计,其实站内我也见过有其他佬友做的类似的项目,但和我的项目在设计上还是有一些区别。

大多数人可能对 Codex 的会话本体文件($CODEX_HOME/sessions/$YEAR/$MONTH/$DAY/$SESSION_ID.jsonl)有所了解,比如搞注册机的时候都知道去里面伪造对话什么的(不是)。这个 jsonl ,也称之为 Thread,即本项目要撕裂的对象(bushi

jsonl里有一个字段:model_provider。就在第一行:

image

我这里显示的是 openai (小写),这个字段大小写敏感。而小写的 openai 是 Codex 的内置 Model Provider,APIKEY(应该没人用官 key 吧)和 ChatGPT 登录后,走的就是这个 Provider。它默认直打官方后端,且不能在 config.toml 里修改这个 Provider。

因此,中转使用,和官方登录使用,这两者之间的会话绝对是隔离开的。除非你 Patch 掉 Codex APP 和 CLI。

那么,很自然的我们就会想到,通过直接改 jsonl 里的 model_provider,统一为一个,不就可以实现解除隔离了吗?

是的,有的佬友的项目就是靠这个方式实现的。我一开始也是这样想的,但是实际上碰到了一个问题:

image

我的老天鹅,你知道 77 个 G 是什么概念吗,想修改这里面的所有 jsonl,跑一次就得好几分钟,体验极差。

不过幸好,可能 OpenAI 内部也有和我一样懒得删懒得清理又大量跑批处理的工程师吧,他们很自然的想到了一个办法:Sqlite 做索引。

得益于 Codex 出色的 APP-Server 架构,Codex APP 和 Codex CLI 都可以连接到一个统一的本地 app-server,而线程列表最终会落到一个 thread/list 接口上。这个接口直接去查 $CODEX_HOME/state_5.sqlite 里的 threads 表。

这个表里保存了每条线程的索引信息,比如:

id
rollout_path
created_at / updated_at
cwd
title
source
archived
model_provider

并且,Codex 不但把 model_provider 存在这里,还专门给它建了索引。

所以切 Provider 后会话看不到了的真实原因就不是因为在 jsonl 里的 model_provider 字段不同了,而是数据库层面的,实际上就可以简化为下面这个查询逻辑:

SELECT * FROM threads
WHERE archived = 0
  AND model_provider IN ('当前 provider')
ORDER BY updated_at DESC

所以 codex-threadripper 做的事情就很简单粗暴了。搞清楚之后,我们就顺势而为::

  1. 读取当前 $CODEX_HOME/config.toml 里的 model_provider
  2. 如果没配置,就按 Codex 默认的 openai 处理
  3. 先用 SQLite 官方 backup API 备份 state_5.sqlite
  4. 然后把 threads.model_provider 统一改成当前 Provider
  5. 后台 watch 模式继续监听配置变化和新增线程,自动继续撕裂线程(

核心逻辑约等于:

UPDATE threads
SET model_provider = '当前 provider'
WHERE model_provider <> '当前 provider';

这样做的好处就很显而易见,秒级改动,不用碰 77G 的 jsonl,不用逐个解析大文件,不用改会话正文。只改索引层,速度快,风险小。

而且 codex-threadripper 其实并没有把 jsonl 文件里的原始 model_provider 改掉。也就是说如果想真的去了解一下某个会话最初是从哪个 Provider 创建的,还是可以直接回源去看的。

说完了

以上就是这个小项目,希望对大家有帮助。有问题也欢迎直接丢 issue 进来。

后续还会有其他围绕 Codex 开发的项目分享,欢迎佬友插眼,我尽快写出来,也会作为合集更新到每个分帖子。

4 个帖子 - 3 位参与者

阅读完整话题

来源: linux.do查看原文