ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

第1讲项目初始化:Codex 连上 TaoToken 后能跑通 PieceTable 文本模型

第1讲项目初始化:Codex 连上 TaoToken 后能跑通 PieceTable 文本模型 实时协同编辑引擎第1讲的项目初始化真正的坎在 PieceTable 的边界插入点落在片段中间时要不要拆成两半删除跨多个片段时头尾怎么保留撤销之后版本号该加还是该减。手写这些逻辑很容易栽在细节上。这一讲我沿用原文的 collaborative-editor 骨架但把 Codex 经 TaoToken 接入项目让它负责生成与审查 PieceTable、Document、HistoryManager 这套文本模型最终用 tests/test_document.py 全绿来确认插入、删除、撤销、版本号都符合预期。TaoToken 在中间只做一件事作为 Codex 的 API 接入通道让本地大模型调用稳定可用并不替代 PieceTable 本身的任何文本操作。1. PieceTable 的边界问题比项目骨架更值得先想清楚1.1 先把 collaborative-editor 骨架和环境搭起来原文的项目结构分五块core 放文档引擎document.py、operation.py、cursor.py、history.pyserver 和 client 留给后面的 WebSocket 同步tests 放单元测试examples 放交互演示。第1讲真正会动的文件只有三个core/document.py、core/history.py、core/cursor.py再加tests/test_document.py和examples/simple_editor.py。所以初始化时不必一次把所有依赖装全。网页服务器相关的 websockets、fastapi、uvicorn 可以等第2讲用到再补现在只需要一个能跑 pytest 的 Python 环境mkdir collaborative-editor cd collaborative-editor python -m venv venv source venv/bin/activate pip install -U pytest这一步完成后目录保持原文的core/、server/、client/、tests/、examples/五段结构即可。空目录先建出来第1讲的代码主要落在core/document.py和core/history.py。1.2 数据结构选型为什么选 PieceTable原文对比了六种文本表示方案选型逻辑直接决定第1讲代码怎么写。简单概括数据结构插入复杂度删除复杂度适用场景Python 字符串O(n)O(n)小文本、一次性渲染数组 ListO(n)O(n)简单编辑器Gap BufferO(1)~O(n)O(1)~O(n)单光标编辑器Emacs/Vim 采用Piece TableO(1)O(1)频繁插入删除 操作日志VS Code 采用RopeO(log n)O(log n)大型文本文档CRDT TreeO(log n)O(log n)多人实时协同实时协同编辑器里用户每一次按键都可能触发 insert 或 delete而且每次操作都要能被记录成 Operation 供撤销和同步。Python 字符串每次插入都复制整个文本短文档还能忍长文档和多人协同场景会直接卡顿。Piece Table 不直接改文本而是维护一个“片段表”每个 Piece 指向某个缓冲区里的一段连续区域插入删除只在表上做拆拼所以复杂度稳定在 O(1)还能天然留下操作日志。第1讲选它做核心结构后面第2讲做 Operational Transformation 时这些 Operation 就是变换的基本单位。2. Codex 要连 TaoToken先创建 Key再改 Codex 配置2.1 在官网创建 YOUR_API_KEY先打开 TaoToken 注册并创建 API Key。拿到 Key 后用YOUR_API_KEY这个占位符统一表示不要把它写进代码仓库也不要提交到 config.toml 里。要分清两件事官网页只负责注册账号、创建 Key、看模型广场、看调用用量真正填进 Codex 的接口地址是https://taotoken.net/api末尾不要带/v1。落地页和接口是两个地址很多人把网页地址直接塞进工具结果连半天都是 404。2.2 在 ~/.codex/config.toml 写入 Base URL 和模型供应商Codex 读取的是用户目录下的~/.codex/config.toml在这里新增一个名为taotoken的 model provider# ~/.codex/config.toml model 你的模型ID model_provider taotoken [model_providers.taotoken] name TaoToken base_url https://taotoken.net/api env_key TAOTOKEN_API_KEYenv_key表示 Codex 会从名为TAOTOKEN_API_KEY的环境变量里读取 Key这样密钥不会落在配置文件里。base_url填https://taotoken.net/api不追加/v1。model字段写什么模型 ID要以 TaoToken 模型广场当时列表为准不要凭印象猜“最新版本号”模型 ID 填错时 Codex 会直接报模型不存在而不是给你一个可用的降级提示。提示官网落地页和接口地址不要混用。注册、建 Key、看用量去https://taotoken.net/?utm_sourcetaotoken_aicg_blog_endutm_content填进 Codex 的 Base URL 用https://taotoken.net/api。2.3 用一句“选型问题”验证连接配置写好后先用一条小请求验证 Codex 是否真的连上了 TaoTokenexport TAOTOKEN_API_KEYYOUR_API_KEY codex exec 第1讲的文本模型里PieceTable 和 Python 自带字符串相比为什么更适合实时协同编辑如果 Codex 能正常回答说明 Key、模型 ID、Base URL 三样都对了。如果返回401基本是TAOTOKEN_API_KEY没设置成功或 Key 复制不完整如果返回模型相关的错误就去模型广场重新查一遍 ID。不要一上来就跑大任务先用这句话把链路探通。3. 让 Codex 按第1讲写出 PieceTable并在边界处多审几遍3.1 生成核心类 BufferType、Piece、PieceTable链路通了之后让 Codex 在collaborative-editor里生成第1讲的文本模型核心代码cd collaborative-editor codex exec 请按实时协同编辑引擎第1讲的规范实现以下内容 1. 在 core/document.py 中定义 BufferType、Piece、PieceTable。 2. PieceTable 需要支持 insert、delete、slice、to_string、char_length、_find_position、debug_info。 3. 在 core/history.py 中实现 HistoryManager内部使用 undo_stack 与 redo_stack。 4. 在 core/document.py 中实现 Document组合 PieceTable 和 HistoryManager每次真实修改都递增 version。 5. 不要省略 insert 拆片段、delete 跨片段的边界处理。生成后重点审两类代码。BufferType用ORIGINAL和ADDITION两个常量区分原始缓冲区与追加缓冲区原始缓冲区只读所有新插入文本一律追加到 addition_bufferPiece是 frozen dataclass字段包含 piece_id、buffer、offset、length。任何修改都不能直接改动 original_buffer 里的内容这是 Piece Table 的根。3.2 insert 拆片段是重灾区以Hello, World!为例在 offset 6 处插入Beautiful 后正确结果是Hello, Beautiful World!。Piece Table 的处理顺序是先把新文本追加到 addition_buffer拿到 add_offset再在片段表里定位到旧片段最后把旧片段拆成 left_piece 和 right_piece中间插入指向 addition_buffer 的新 Piece。手写时最容易错的地方集中在三点offset_in_piece为 0 时不生成 left_piece等于旧片段长度时不生成 right_piece很多实现会在这两个边界上产生空 Piece。新 Piece 的 buffer 必须是ADDITION如果复用旧片段的 ORIGINAL buffer会破坏原始缓冲区只读语义。重组顺序必须是“旧片段左侧 新片段 旧片段右侧”漏掉任何一段都会让文本内容对不上。让 Codex 生成完这段后直接让它对照Heorld在位置 2 插入ll的输出预期是Hello World。如果 Codex 给出的实现把中间插入变成了覆盖或重复说明它的片段拆分逻辑不合格让它重写拆分部分而不是继续往后加功能。3.3 Document 串起 HistoryManager 和版本号Document是完整文档引擎的门面它组合了 PieceTable、HistoryManager、CursorManager。insert 和 delete 操作都要遵循同一套流程先让 PieceTable 执行修改如果返回的 Operation 不是 NOOP就 push 进 HistoryManager并把 version 加 1。undo 时从 HistoryManager 取 inverse 操作再调用 PieceTable 应用redo 则是取出原始操作继续应用。CursorManager 负责记录每个用户的光标位置和选区第1讲只保证 position 字段在插入删除后不越界真正的远端同步放到第2讲。version 在这里不只是计数器它后续要作为协同同步的参照系。所以验证时不要只盯着文本内容对不对还要确认每次真实操作后 version 都严格递增。Codex 生成 Document 时如果跳过了 version 自增pytest 里test_version_increment会立刻报红。4. 跑 pytest 验证插入、删除、撤销、版本号4.1 tests/test_document.py 全绿的判据在项目根目录运行source venv/bin/activate python -m pytest tests/test_document.py -v原文的测试用例覆盖了四组行为全绿意味着以下场景全部成立插入空文档插入、开头插入、中间插入、结尾插入、连续多次插入后文本按顺序拼接。删除删除开头、删除结尾、删除中间一个字符删除后剩余文本正确拼接。撤销重做连续两次 undo 后文本回到更早状态再连续两次 redo 后文本完全恢复。版本号每次 insert、delete、undo、redo 后 version 都严格加 1。中间插入是最容易翻车的用例。像Heorld在位置 2 插入ll期望输出是Hello World。如果跑出来的结果是HelloWorld或Heoll World说明 insert 拆分片段时 left_piece 和 right_piece 的 offset 或 length 算错了优先查_find_position返回的offset_in_piece是否正确。4.2 pytest 红了就贴回给 Codex不要急着改断言也不要自己逐行猜。直接把 pytest 的完整输出贴回 Codexcd collaborative-editor codex exec 我运行 pytest tests/test_document.py -v 后失败完整输出如下…… 请判断是 insert 拆分逻辑、delete 尾部处理还是 HistoryManager 的 invert 有错并直接给出修改后的完整代码。常见的失败形态有两个报IndexError: Position out of range说明_find_position在边界位置没有正确落到最后一个片段undo 之后文本没变化说明Operation.invert()得到的 position 或 deleted_text 与原始操作不匹配。把报错和失败断言一起贴回去Codex 通常能定位到具体函数重点检查它有没有改core/history.py里的栈逻辑。4.3 用 simple_editor.py 走一遍交互式演示pytest 全绿后再跑examples/simple_editor.pypython examples/simple_editor.py这个脚本会按“初始文本、插入、删除、撤销、再撤销、重做”的顺序打印每一步的文本和版本号。正常输出序列应该是初始Hello World!插入Beautiful 后变成Hello Beautiful World!删除后变回撤销两次回到初始文本重做又依次恢复。版本号会随着每一步真实操作递增。这里如果撤销和重做后的文本不一致说明 HistoryManager 的 push 或 invert 方向反了回看第3.3节的流程。5. 测试全绿后回 TaoToken 控制台对一次用量5.1 在控制台核对本次调用是否记上账刚才启动 Codex 时用的 Key 和模型 ID会在 TaoToken 控制台形成对应的调用记录。测试跑完后打开 API Keys 页面 检查这次对话是否正常记账确认没有出现“Key 有效但调用数为 0”的异常。如果后续要在浏览器里直接验证某个模型 ID 的回复质量可以先在 模型对话 里用同一把 Key 发一条消息对比结果要长期做第2讲这类多轮代码生成再打开 Coding Plan 看套餐是否合适。5.2 下一讲OT 算法正好用上 Operation 和版本号原文第2讲要进入 OT 算法操作转换需要基于 position、version 和 Operation 本身做变换。第1讲里Operation.invert()已经为撤销打好了底Document 的 version 也会成为冲突检测的参照。Codex 走 TaoToken 这条接入通道不需要改动继续保留~/.codex/config.toml和环境变量即可。到时候直接在项目目录里让 Codex 生成转换函数和冲突测试你负责把 pytest 结果拿回来核对。先把这一讲的绿点守住第2讲就是在这些绿点之上做变换。
返回列表