Auto-Research
Twinkle Auto 是一个基于终端的智能训练助手,支持通过自然语言控制、监控和调试 ML 训练。它将聊天驱动的 AI 代理与自动化健康监控器相结合,能够自主检测并修复训练故障。
架构概览
┌──────────────────────────────────────────────────────────┐
│ TwinkleAuto (asyncio 聊天循环) │
│ │
│ 核心组件: │
│ AgentLoop ─── LLM 工具调用循环 │
│ TrainingMonitor ─── 定期健康检查与自动修复 │
│ LocalConnection ─── 基于文件系统的通信层 │
│ SkillManager ─── 异步插件加载 │
└──────────────────────────────────────────────────────────┘
安装与启动
Auto 是 twinkle-client 包的一部分:
pip install twinkle-client
命令行用法
# 基本启动(使用默认本地 Ollama 端点)
twinkle-auto
# 指定 LLM 后端
twinkle-auto --llm-base-url http://localhost:11434/v1 --llm-model qwen3.5
# 连接到已有训练运行
twinkle-auto --run-id my-grpo-run
# 使用远程 API(如 OpenAI 兼容接口)
twinkle-auto --llm-base-url https://api.example.com/v1 --llm-api-key sk-xxx --llm-model gpt-4o
# 启用调试日志
twinkle-auto --verbose
也可作为 Python 模块运行:
python -m twinkle_client.auto
CLI 参数
| 参数 | 环境变量 | 默认值 | 说明 |
|---|---|---|---|
--run-id, -r | TWINKLE_AUTO_RUN_ID | None | 连接到已有训练运行 |
--llm-base-url | TWINKLE_LLM_BASE_URL | http://localhost:11434/v1 | LLM API 基础 URL |
--llm-model | TWINKLE_LLM_MODEL | qwen3.5 | LLM 模型名称 |
--llm-api-key | TWINKLE_LLM_API_KEY | not-needed | LLM API 密钥 |
--verbose, -v | TWINKLE_AUTO_VERBOSE | False | 启用 DEBUG 日志 |
--version, -V | — | — | 显示版本并退出 |
聊天代理
Auto 的核心是一个 LLM 驱动的工具调用代理(AgentLoop),通过 OpenAI 兼容 API 处理自然语言命令。代理维护对话历史并自动修剪(保留最近 50 条消息),每次交互最多支持 10 轮工具调用。
你可以这样说
训练生命周期:
- “列出我的训练运行”
- “用 Qwen3.5-4B 在 gsm8k 上启动一个新的 GRPO 训练”
- “暂停当前运行”
- “恢复训练”
- “停止训练”
服务器管理:
- “启动服务器,使用 Qwen3.5-4B 和一个 2 卡的 Qwen3.5-72B 采样器”
- “关闭服务器”
- “有多少 GPU 可用?”
监控与分析:
- “训练进展如何?”
- “显示 reward 相关的指标”
- “放大到 step 100-200”
- “重置图表视图”
搜索:
- “搜索数学数据集”
- “在 ModelScope 上查找 Qwen 模型”
可用工具
代理内置 13 个工具:
| 工具 | 说明 |
|---|---|
list_training_runs | 列出所有训练运行 |
get_training_status | 获取详细状态和最近指标 |
start_server | 启动 Ray 集群 + Twinkle Server(幂等) |
shutdown_server | 关闭服务器并释放 GPU 资源 |
start_training | 创建并启动新的训练运行 |
select_run | 切换监控到另一个运行 |
pause_training | 暂停训练(SIGKILL,服务器保留状态) |
resume_training | 通过重新启动客户端脚本恢复训练 |
stop_training | 停止训练(SIGTERM,保存检查点) |
update_script | 更新训练脚本(带版本归档) |
list_supported_models | 查询服务器支持的模型 |
search_datasets | 在 ModelScope 搜索数据集 |
search_models | 在 ModelScope 搜索模型 |
zoom_metrics | 调整指标图表视图范围 |
select_metrics | 选择显示哪些指标(最多 4 个) |
get_cluster_info | 获取 GPU/集群资源信息 |
服务器启动
start_server 工具自动化一个多步骤流程:
- GPU 检测 —
nvidia-smi硬件扫描 - GPU 分配 — 在训练模型和采样器之间分配 GPU
- 配置生成 — 自动创建
server_config.yaml - Ray 集群启动 — 多节点 GPU 分区,隔离
CUDA_VISIBLE_DEVICES - 服务器启动 — 作为后台进程启动 Twinkle Server
- 健康检查 — 轮询
/api/v1/healthz直到就绪
支持多模型拓扑:1 个训练模型 + N 个采样器/教师模型。
Skills 系统
Auto 支持从三个来源加载可扩展的技能插件:
- 内置技能 — 包含在
twinkle_client/skills/bundled/中 - 用户本地技能 —
~/.cache/twinkle/auto/skills/local/ - 社区技能 — 从 ModelScope 获取(尽力而为,10 秒超时)
技能在启动后异步加载并注入代理的系统提示词中。代理在技能加载完成前即可使用。
训练监控器(自动修复)
TrainingMonitor 是一个后台服务,每 30 秒运行一次,收集当前训练运行的所有可用信号,并提交给 LLM 进行分析。
收集的信号
- 进程状态:alive / dead / unknown
- output.log 尾部:最后 1500 个字符(优先提取 traceback)
- 指标:最近条目 + 前半段 vs 后半段趋势分析
- 停滞时长:自最后一次产生指标以来的秒数
- 当前 train.py:完整脚本源码(用于精确修复)
决策框架
LLM 将每次检查分类为三种操作之一:
| 决策 | 触发条件 | 执行动作 |
|---|---|---|
| LGTM | 训练正常推进 | 无操作 |
| WARNING | Loss 平台期、reward hacking、KL 爆炸等 | 向用户报告观察结果 |
| FIX | 脚本崩溃、进程死亡并有 traceback | 自动修复并重启 |
自动修复流程
当需要 FIX 时:
- LLM 输出诊断 + 完整修复脚本
- 监控器将旧
train.py归档为train_v{N}.py - 将修复脚本写为新的
train.py - 通过
resume_training重新启动训练 - 重置停滞追踪
安全保障:
- 每个运行最多 3 次自动修复尝试(防止无限重试循环)
- 修复尝试按
run_id追踪 - 快照去重避免对未变化状态的重复分析
基于文件的连接层
Auto 通过本地文件系统与训练进程通信:
~/.cache/twinkle/{run_id}/
├── meta.json — 运行元数据(model_id、config、status、pid)
├── metrics.jsonl — 每步一个 JSON 对象(增量)
├── output.log — 训练的 stdout+stderr 合并输出
├── train.py — 当前活动训练脚本
└── train_v{N}.py — 归档的历史脚本版本
训练控制模型
在 Server 模式下,Twinkle Server 将所有模型/优化器状态保留在 GPU 内存中:
- 暂停 = 杀死客户端进程 (SIGKILL) — 服务器状态保留
- 恢复 = 重新启动客户端脚本 — 无缝继续训练
- 停止 = SIGTERM — 触发检查点保存后退出
- 关闭服务器 = 释放 GPU 资源,销毁模型状态
TrainingRuntime(脚本集成)
训练脚本使用 TrainingRuntime 与 Auto 集成:
from twinkle_client.auto.runtime import TrainingRuntime
rt = TrainingRuntime(run_id='my-grpo-run')
rt.start(model_id='Qwen/Qwen3.5-4B', config={'lr': 1e-5})
rt.register_graceful_shutdown(model, dataloader)
for step, batch in enumerate(dataloader):
# ... 训练逻辑 ...
rt.log_metrics(step=step, loss=loss, reward=reward, grad_norm=gn, lr=lr)
rt.log(f'Completed step {step}, loss={loss:.4f}')
rt.finish()
核心方法
| 方法 | 说明 |
|---|---|
start(model_id, config, script_path) | 初始化运行目录和元数据 |
log_metrics(**kwargs) | 向 metrics.jsonl 写入指标条目 |
log(message) | 打印日志消息(被捕获为 output.log) |
get_resume_info() | 获取 last_step 用于从检查点恢复 |
finish(status) | 标记训练完成,关闭文件 |
register_graceful_shutdown(model, dataloader) | 注册 SIGTERM 处理器以保存检查点 |
断点续训支持
TrainingRuntime 自动将训练进度保存到 meta.json(每 5 秒节流写入一次)。脚本可以使用 get_resume_info() 从上次保存的步数恢复:
rt = TrainingRuntime(run_id='my-run')
resume = rt.get_resume_info()
global_step = resume['last_step']
if global_step > 0:
dataloader.skip_consumed_samples(global_step * BATCH_SIZE)
print(f'从 step {global_step} 恢复训练')
优雅关停
调用 register_graceful_shutdown() 后,会安装一个 SIGTERM 处理器:
- 保存模型检查点(LoRA 权重 + 优化器状态)
- 保存数据加载器位置(
consumed_train_samples) - 记录检查点路径
- 标记训练为
stopped并退出
日志记录
所有日志写入 ./auto.log(当前工作目录):
- 5MB 时轮转,保留 3 个备份
- 无控制台输出 — 所有输出写入日志文件
- 使用
--verbose启用 DEBUG 级别日志