CLM 实战:用 Chrome 恐龙游戏 T-Rex 实时对打 TypeSafe Jev,评测 System One 决策延迟与安全性
【免费下载链接】CLM项目地址https://gitcode.com/gh_mirrors/clm2/CLM点击查看免费下载本指南以 examples/t_rex/README.md 为骨架讲解如何用同一个 System One 客户端clm.CLMClient驱动 CLM 与 TypeSafe Jev 两个端点在 Chrome 离线恐龙游戏的确定性 Python 克隆中实时比赛 60 秒验证模型在高频决策、真实网络延迟与安全护盾下的综合表现。读完本文你将掌握 T-Rex 基准测试的完整架构确定性引擎、物理规划器、多请求在途、护盾干预并能在本仓库中一键复现、解读results/*_realtime.json报告。一、概览同一套 wire format一个客户端打两个端点T-Rex runner 的核心实验设计是**“同一个被服务的 head、原封不动”CLM 与 TypeSafe 托管的 Jevjev-latest在 Chrome 离线恐龙游戏上实时比赛。因为 CLM 的POST /v1/systemone原生兼容 TypeSafe 的线格式wire format两边玩家可以复用同一个客户端**——即 examples/common.py 中基于clm.CLMClient构建的Judge封装——只有 base URL 与 API key 不同。从 examples/common.py 的ENDPOINTS可以看到两个端点的默认配置玩家base URL 环境变量默认 base URL模型环境变量默认模型key 环境变量clmCLM_BASE_URLhttp://127.0.0.1:8700CLM_MODELclm-latestCLM_API_KEYjevTYPESAFE_BASE_URLhttps://api.typesafe.aiTYPESAFE_MODELjev-latestTYPESAFE_API_KEY/JEV_API_KEYJudge在裸客户端之上额外提供了几层能力均与实时评测场景直接相关指数退避重试对 429 / 529 / 5xx 与传输错误重试RETRY_STATUS适合脚本化批量评测而实时比赛中真正发请求的ApiBackendexamples/t_rex/trex/backends.py则不做重试因为迟到的答案在实时游戏里已经无用失败调用直接计入报告的errors。延迟与 token 记账每次请求记录客户端侧 wall-clock 延迟与输入 token 数judge.stats()可汇总 p50/p95。可选 sqlite 答案缓存断点续跑时命中缓存的回复不计入延迟cachedTrue时latency_ms0。choose分块锦标赛Jev 每题最多 255 个选项max_options255超出时按块询问再对每块头部做最终 ChoiceCLM 无上限。二、评测任务与计分口径README 定义的任务非常明确让恐龙存活 60 秒。比赛场地是 examples/t_rex/trex/engine.py 实现的确定性 Python 克隆与 Chromium 原版恐龙游戏保持相同常量、跳跃物理、碰撞盒、障碍规则与速度曲线该克隆源自 laya-vs-jevApache-2.0引擎 docstring 注明规则源自 ChromiumBSD-3-Clause。游戏以固定的60 FPS步进、实时推进FPS 60FRAME_MS 1000 / 60。共5 个带种子的赛道--seeds 5默认--seed 0每个赛道 60 秒--duration 60.0撞毁后1.5 秒自动重开RESTART_DELAY_MS 1500。“存活”定义为观察窗口内零死亡survived: game.deaths 0。评测夹具的护盾shield默认开启与上游一致若规划器将某答案标为 unsafe则用模型概率最高的安全动作替换另有应急检查可在碰撞前代为行动。报告会逐条统计这类干预。因此一个清晰的读数口径是存活数字衡量的是“系统整体”模型 规划器 护盾而 agreement与规划器最佳动作的一致性与 intervention干预行衡量的是模型本身。三、确定性 T-Rex 引擎可复现的 60 FPS 世界examples/t_rex/trex/engine.py 是一个纯 Python、无渲染依赖的确定性仿真它保证“同一种子从同一状态开始的两局游戏只要都还活着就遇到完全相同的障碍序列”。关键实现事实确定性随机流RandomCourse为每个(seed, run_index, obstacle_index)派生独立随机流random.Random(fcourse-{seed}-{run_index}-{index})因此无论哪个进程、何时询问同一障碍都能重现。原版常量与规则SPEED6、ACCELERATION0.001、MAX_SPEED13、GAP_COEFFICIENT0.6、MAX_OBSTACLE_LENGTH3、MAX_OBSTACLE_DUPLICATION2、INVERT_DISTANCE700等以及三种障碍类型cactusSmall / cactusLarge / pterodactyl各自带 width/height/y 高度档位/min_speed/碰撞盒翼龙还有multiple_speed999与双帧动画。碰撞判定沿用原版的两段式先做外接矩形粗判再做细化碰撞盒逐对相交check_collision。跳跃物理jump_step逐帧更新GRAVITY0.6、INITIAL_JUMP_VELOCITY-10、DROP_VELOCITY-5并复刻了“跳跃初速随当前速度略微降低”INITIAL_JUMP_VELOCITY - speed / 10与 speed drop / duck 的相互转换细节。障碍生成规则障碍移动量用math.floor((speed offset) * FPS / 1000 * dt)精确复算连续同类障碍受too_many限制Obstacle的gap由当前速度解析spec.gap0~1 区间得出。正因为它把原版的规则、常量和碰撞盒都搬进了 Python规划器才能在同一套算术上做逐帧前瞻而不是用近似模型。四、物理规划器精确到帧的安全性分析examples/t_rex/trex/planner.py 是整套评测的灵魂一个确定性物理规划器只观察屏幕上已有的障碍用引擎自身的算术预测它们未来的运动并以固定的决策粒度搜索恐龙未来的按键序列。它最重要的特点是把回答延迟计入安全分析当前选择的动作只有在模型的答案真正到达的时刻才会生效并且会一直保持到下一个答案到达。也就是说规划器要为“答案落地那一帧”标注每个动作jump/duck/run是 safe 还是 unsafe并选出时序余量最佳的那个动作。两个模型收到的是完全相同的标签可选的护盾也用同一份 safe 集合来否决模型的不安全选择。4.1 搜索结构与“自己的答案时序”下棋Search类把安全性证明建模成一场玩家与自身答案时序之间的对抗游戏每个答案落在上一答案之后若干帧落点区间gap (lo, hi)由对手任选。一个位置“可赢”当且仅当存在某个动作对区间内的每一个落点都能继续赢而超过 horizon 的位置视为已赢。这正是玩家在下一次答案被规划时所处的处境——所以标为 safe 的动作总能保证在下一个答案落地时无论何时落地仍有安全动作可用。搜索在(frame, trex state, held keys, zero gap allowed, lock)上做记忆化memoise并对“同一帧落两个答案zero gap但不可能落三个”做了特判。StaggeredSearch处理多请求在途的玩家提问每隔几帧发出等待下一问题的时间至多为period帧若某个答案保持按键不变则它对之后每一个可能的提问帧都必须是安全的若答案改变了按键则在落点区间内逐帧验证而在此期间按旧按键问出的答案作废会被丢弃。horizon 由屏幕上最远障碍的到达帧数推导Planner.horizon默认max_horizon150帧。当没有任何动作能扛过全部时序时规划器退化为best-effort 选择对每个动作逐一评估“若后续答案按往常时间到达游戏还能否继续”优先选择存活落点最多的动作并在Plan.robustFalse上记录这次降级报告中对应best_effort_decisions。4.2 推荐策略给“迟到答案”留足余量recommend()的原则是“答案只会迟到、不会早到”因此最佳动作是在最早能独立清除威胁的那一刻开始机动把整个时序窗口都变成余量空中时快速 drop 能更早落地但它是按键变更下一答案还很远时不轻易花掉只有safe[duck]且run不安全或玩家足够快且当前弧线不足以越过障碍时才选duck否则保持run。地面时若threat is None就继续run否则先看翼龙是否足够近DUCK_LEAD_FRAMES 14的提前量再考虑duck再试jump用(action, until)lock 验证单一机动能否独立过关最后才是run等待。4.3 发给模型的标签规划器输出的notes会把每个动作翻译成模型可读的自然语言例如jump: Clears the {label}/Jumps too early/Jumps for no reasonduck: Passes under the {label}翼龙/Crouches; no benefitrun: Waits; must act soon/Keeps running五、请求格式每个决策一个 ChoiceREADME 给出了比赛双方收到的逐决策请求原文完全相同state: Dino runner game. 2 large cacti ahead, 96 px away. question: Choose the best safe action for the dinosaur. jump: Safe. Clears the 2 large cacti. Best. duck: Unsafe. Hits the 2 large cacti. Collision. run: Unsafe. Hits the 2 large cacti. Collision.从 examples/t_rex/trex/backends.py 的build_question看它把规划结果构造成一次 Choice 请求state描述局面Dino runner game. …含“前方是什么、距离多少像素”空中时追加The dino is in the air.question是 Choice 的instructions三个criteria键分别承载jump / duck / run的标签与注释。两种提示词风格labeled默认Safe. {note}. Best./Safe. {note}./Unsafe. {note}. Collision.——不直接说出答案只给标注。guidedBest: {note}, safe./Safe: {note}./Collision: {note}.并在 state 里追加Recommended action: {best}.。模型返回三个动作上的概率分布answers[action][probabilities]decide会先做合法性检查概率必须有限且落在 0~1 之间。玩家取概率最高的动作执行护盾模式下若该动作不在plan.safe_actions中则改为 safe 集合内概率最高的动作。六、实时决策回路多请求在途、迟到答案作废examples/t_rex/trex/pilot.py 实现实时决策主循环README 的两个关键设计点是模型持续保持忙碌一个答案就绪后立即就“最新一帧”发问并把“尚未落地的答案”告知规划器pending。空窗会让 GPU 降频而且真人看屏幕也不会等下一帧才开始思考。每个答案在到达后的第一个帧边界生效所以模型的完整延迟本身就是游戏的一部分。多请求在途托管模型能并行应答因此 Pilot 可以同时保持多个请求在途、每隔几帧发问stagger帧 round(typical_frames / min(inflight, 4))上限 12 帧。每个答案仍然比发出时“老一个往返”但玩家每几帧就轮到一次而不是每个往返才轮到一次。每条请求都建立在“落地前按键不变”的前提上一旦有别的答案改变了按键前提即被打破迟到的答案被丢弃、绝不执行报告里对应answers_discarded。6.1 独立进程隔离延迟trex/brain.py每个玩家运行在自己的进程里examples/t_rex/trex/brain.py 的RemoteBrain通过 multiprocessing spawn 子进程跑serve原因是 Python 解释器锁如果窗口、赛道设计器和另一个玩家在同一进程一次由大量短 Python 步骤组成的模型调用可能要为解释器锁等待数百毫秒。子进程内用ThreadPoolExecutor(workersinflight)为每个在途请求开一条线程并通过sys.setswitchinterval(0.001)让规划线程不至于卡住模型线程。开局前还有warm-upwarm()先用当前帧快照向模型问 4 次测出该玩家的答案延迟分布得到latency_frames / typical_frames / jitter_frames / interval_frames都以帧计供规划器设定(first, gap, period)时序inflight 1时还会在赛前打开所有连接避免比赛中途为 TCP 握手买单。6.2 时序自适应的实时性Pilot 会持续观察实际落地帧observe_timing一旦延迟突然超过latency_frames max(4, jitter_frames*2)就立即清空历史快速遗忘旧 regime随后在最近 16 次回复内逐渐恢复。timing()把观测转成规划器需要的(first, gap, period)单请求在途时gap等于落地时间多请求在途时period取最近提问间隔的 p95longest_wait上限 24 帧。七、护盾到达检查与应急检查护盾并非简单的“按标签否决”而是由 examples/t_rex/trex/safety.py 的protect(snap, action)做有界到达检查独立于递归规划器可逆按键如保持 run/duck做 12 帧碰撞检查urgent12。跳跃与空中按键变更要检查到“即将到来的障碍被清除”为止上限 42 帧horizon42因为一次不安全的起跳或下坠可能在很远的未来才造成碰撞。若“立刻起跳”被拒会尝试有界延迟跳跃是否可行在恢复范围内搜索至多十二条固定轨迹绝不递归展开决策树。对“已处于安全弧线”的空中 drop 会格外保守只有当继续 hold 原按键真的会失败时才允许缩短弧线。护盾在 Pilot 中有两个触发点分别计数arrival_saves到达时护盾答案落地、即将应用时protect把 unsafe 的原始动作替换为安全动作decision.arrival_intervened。emergency_saves应急护盾答案仍在途或已失败时主循环每帧用protect(snapshot, held)检查当前按键不安全就代为改键。README 明确提醒护盾开启计数的是“系统整体”的干预而agreement_with_planner模型所选与规划器最佳动作的一致性与 intervention 行才是衡量模型本身的口径。八、复现运行从启动 clm-serve 到跑完 5 个种子8.1 前置本地 CLM 服务README 要求先按主 README.md 的 Quickstart 启动clm-serve# 1. encoderQwen3-8B embeddings vllm serve Qwen/Qwen3-8B --served-model-name qwen3-8b --runner pooling --max-model-len 2048 --port 8090 # 2. CLM API on :8700首次运行会下载约 75 MB 的参考 head clm-serve对 Jev 玩家则需要在repo/.env中写入TYPESAFE_API_KEY...load_env会把KEYVALUE行导出进环境变量已有环境变量优先。8.2 安装与运行pip install -r requirements.txt # 仓库根目录下clm-serve 已启动见主 README 的 Quickstart python examples/t_rex/run.py --model clm # 5 seeds × 60 s实时护盾开启 python examples/t_rex/run.py --model jev python examples/t_rex/run.py --model clm --no-shield # 模型的答案原样执行 python examples/t_rex/run.py --model clm --lockstep 6 # 模型回答期间游戏冻结每次运行会实时打印一行摘要survived / deaths / best_score / decisions / agreement / latency_p50 / model_p50 / errors并把完整结果写入 examples/t_rex/results 下的results/model_mode.json。8.3 环境变量覆盖变量作用默认值CLM_BASE_URLCLM 端点地址http://127.0.0.1:8700CLM_API_KEYCLM 鉴权本地服务通常留空无CLM_MODELCLM 请求模型名clm-latestTYPESAFE_BASE_URLJev 端点地址https://api.typesafe.aiTYPESAFE_MODELJev 请求模型名jev-latestTYPESAFE_API_KEY/JEV_API_KEYJev 鉴权也可放repo/.env无8.4 run.py 全部命令行参数对照 examples/t_rex/run.py除 README 中的--model外还有一批实验旋钮参数默认值说明--model {clm,jev}必填选择玩家端点--seeds N5运行局数第 i 局使用--seed i--seed N0起始种子--duration S60.0每局秒数--no-shield关模型答案即使被标 unsafe 也原样执行--lockstep FRAMES无游戏等待模型回答期间冻结之后每个决策推进 FRAMES 帧延迟被移除--inflight N6实时模式保持的在途请求数1–8越界报错--course-style {original,staged}originaloriginal 用 Chrome 原版障碍规则staged 用上游更平缓的分阶段赛道examples/t_rex/trex/course.pyWarm-up / Sprint / Bird attack / Final challenge 四阶段为鸟类出现前的暖身期保留更多恢复空间--prompt {labeled,guided}labeled两种提示词风格见第五节--out PATH自动结果 JSON 输出路径默认results/model_mode[_noshield].json注意--no-shield与--lockstep是供你自己做实验的旋钮不在 README 的对比表口径内。九、结果报告解读每局运行产出results/model_realtime.jsonREADME 说明其内容per-seed 报告deaths、score、decisions、answer latency、与规划器最佳动作的一致性、被丢弃的迟到答案、errors。仓库已附 examples/t_rex/results/clm_realtime.json 作为示例另一个玩家 examples/t_rex/results/jev_realtime.json 亦随仓库提供可自行对照。每个 seed 的字段如下字段含义seed该局种子survived/deaths存活零死亡与否 / 死亡次数best_score/scores最好成绩 / 每轮成绩decisions实际生效的决策数agreement_with_planner模型所选与规划器最佳动作的一致性比例衡量模型latency_ms_p50 / p95客户端侧端到端延迟分位含排队与网络model_ms_p50模型侧推断延迟分位answers_discarded前提被打破、被丢弃的迟到答案数errors/last_error请求失败次数与最后一条错误best_effort_decisions规划器降级为 best-effort 的次数shield_interventions/arrival_saves/emergency_saves规划阶段干预 / 到达时护盾 / 应急护盾input_tokens输入 token 总量game_seconds/wall_seconds游戏内时间 / 墙上时间host_stall_seconds_dropped主机停顿被跳过的墙上时间model/endpoint应答模型与端点描述文件头部summary则汇总moderealtime / lockstepN、shield、course_style、prompt、duration_s、seeds、总survived / deaths、mean_best_score、mean_decisions、mean_agreement_with_planner、latency_ms_p50_median、model_ms_p50_median、errors、answers_discarded、shield_interventions三项护盾计数之和与inflight。以随仓库附带的 CLM 示例clm-latestCLM_v0.1-8B.ptQwen3-8B 编码器单卡 RTX 40906 请求在途为例5 个种子全部存活、总死亡 0mean_best_score 697.0mean_decisions 3341.8mean_agreement_with_planner 0.658latency_ms_p50_median16.5 ms、model_ms_p50_median2.6 mserrors 0answers_discarded 合计 1250护盾干预合计 4883其中 arrival_saves 逐 seed 为 760/807/889/1029/1034emergency_saves 为 0。需要强调的是这些数字只代表仓库内该次运行样本任何跨模型的胜负结论都应基于你自己在同一环境、同一批种子下重跑两边的结果。9.1 host_stall_seconds_dropped 的含义实时运行依赖宿主机节奏examples/t_rex/trex/pilot.py 的Pacer把墙上时间换算成 60 FPS 游戏帧若主机停顿错过的帧数会被丢弃而不是补跑成 burstburst 会让游戏在无答案可落地的窗口里“盲跑”。被跳过的墙上时间计入host_stall_seconds_dropped因此一台停顿的主机会在结果中直接可见——这是判断某次运行是否“实时可信”的第一指标。十、评测边界与可验证性最后把 README 的原始口径再强调一遍避免误读实验设计同一个 head两端点收到相同的 state 与相同的 Choice 问题CLM 侧clm-latest在 2026-09-23 运行CLM_v0.1-8B.ptQwen3-8B 编码器单卡 RTX 4090Jev 侧在 2026-09-22 以jev-latest应答为jev-1.13.0运行README 明确延迟为客户端侧、按请求计。可复现同一种子 → 同一障碍序列规划器与引擎共享同一套算术双端点共用同一个客户端。这些设计让任何第三方都能在自备环境中重跑并对照。实验旋钮的边界--no-shield与--lockstep不属于对比表口径——前者让模型答案原样执行衡量纯模型后者把延迟从游戏中移除衡量无延迟上限时的决策质量README 的表格则反映“系统整体 真实延迟”的默认组合。赞分享【免费下载链接】CLM项目地址https://gitcode.com/gh_mirrors/clm2/CLM点击查看免费下载相关推荐axios-retry与TypeScript类型安全的重试插件开发指南axios retry与TypeScript类型安全的重试插件开发指南 axios retry是一个强大的Axios插件它能够拦截失败的请求并在可能的情况下后端网络华硕笔记本终极优化指南G-Helper轻量级控制工具完全解析华硕笔记本终极优化指南G Helper轻量级控制工具完全解析 还在为Armoury Crate的臃肿和资源占用而烦恼吗G Helper作为华硕笔记本的轻量级桌面应用系统编程实测Sunshine游戏串流性能对决AMD/NVIDIA/Intel显卡延迟与帧率全面对比实测Sunshine游戏串流性能对决AMD/NVIDIA/Intel显卡延迟与帧率全面对比 为什么选择自托管串流 还在为云游戏高延迟烦恼Sunshine音视频后端创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考