🎁 福利专区全网大模型免费应用 + 新用户福利 + 注册活动入口,低成本玩转 AI

监督微调流水线 xiciyang/training-sft

DeepSeek Harness
xiciyang11 天前有提交已提供中文文档扫描:含敏感能力

用真实 GPU 做 LoRA 微调,每步留痕可审计

30/100
综合分
0
GitHub 星标
—
npm 周下载
—/5
用户评分

数据截至 2026/10/21 · 周下载取自 npm 全网(含 CI / 镜像),非本站安装数;综合分由星标、活跃度与兼容性检查合成。

安装命令 · 需先装 dsh CLI 引擎
dsh plugin --profile web add xiciyang/training-sft
该包不可直接 npm 安装,改从 GitHub 源安装(明细见下方安装检查)

状态速览

判定依据:实装验证 · 静态安装检查 · 自动扫描 · 仓库维护状态
信任档位:已验证
是什么
dsh 原生插件 · dev
装得上吗
本站已在 dsh 0.2.1-rc.2 下真实安装成功
非静态推断
L4 · 真实安装等级说明 →
安全吗
本站尚未对该插件做风险分级
暂未覆盖,不等同于无风险
还在维护吗
活跃:最近一次提交在 11 天前
档位由哪些信号合成

本站实装验证(真实安装 L4 覆盖全站;L5 为运行时冒烟或实机截图,覆盖范围小于 L4) · 验证所用 dsh 版本 · 静态安装检查 · 风险分级 · 仓库维护状态。 下方各区块是它的证据明细。

验证判据与等级说明 →
社区实装还没有人打卡 · 装过的第一个就是你
安全扫描自动 · 静态分析源码
v2.7.0
🔵 扫描:含敏感能力尚无人工评估
展开查看扫描说明与证据 ↓

静态扫描发现插件具备触达本地系统的能力:执行外部命令、读写/删除本地文件、读取剪贴板或密钥类环境变量(至少其一)。这是能力清单,不是危险判定——具体能力项与证据见下方,安装前请自行判断是否需要。

可执行外部命令读写/删除本地文件发起外部网络请求
查看扫描证据(共 46 处,展示前 32 条)
  • 读取本地文件
    src/index.mjs:59
    if (!existsSync(p)) continue
  • 读取本地文件
    src/index.mjs:60
    const text = readFileSync(p, 'utf8')
  • 读取本地文件
    src/core.mjs:36
    function schemaPath() { return existsSync(SCHEMA_FILE) ? SCHEMA_FILE : null }
  • 读取本地文件
    src/core.mjs:91
    if (!datasetDir || !existsSync(join(datasetDir, 'train.jsonl'))) throw new ToolError(ERROR_CODES.E_DATASET_INVALID, { hint: `数据集未就绪:${datasetDir}(先调 t
  • 读取本地文件
    src/core.mjs:92
    const lineage = JSON.parse(readFileSync(join(datasetDir, 'lineage.json'), 'utf8'))
  • 读取本地文件
    src/core.mjs:94
    if (!existsSync(join(baseModel, 'config.json'))) throw new ToolError(ERROR_CODES.E_BASE_MODEL_NOT_FOUND, { hint: `基座模型目录不合法:${baseModel}`, recoverable
  • 读取本地文件
    src/core.mjs:108
    if (!existsSync(join(srcDir, 'adapter'))) throw new ToolError(ERROR_CODES.E_RUN_NOT_FOUND, { hint: `续训源 checkpoint 缺 adapter 目录:${srcDir}`, recoverabl
  • 读取本地文件
    src/core.mjs:112
    const payload = JSON.parse(readFileSync(join(srcDir, 'payload.json'), 'utf8'))
  • 写入本地文件
    src/core.mjs:488
    writeFileSync(join(run.runDir, 'eval-result.json'), `${JSON.stringify(evalResult, null, 2)}\n`)
  • 执行外部命令固定命令
    src/core.mjs:599
    const out = execFileSync('nvidia-smi', ['--query-gpu=name,driver_version', '--format=csv,noheader'], { encoding: 'utf8', timeout: 20000 }).trim()
  • 执行外部命令固定命令
    src/core.mjs:605
    imageId = execFileSync('docker', ['images', '-q', TRAINING_IMAGE], { encoding: 'utf8', timeout: 20000 }).trim() || null
  • 读取本地文件
    src/serving-client.mjs:23
    if (existsSync(cfg)) {
  • 读取本地文件
    src/serving-client.mjs:24
    const p = readFileSync(cfg, 'utf8').trim()
  • 读取本地文件
    src/serving-client.mjs:25
    if (p && existsSync(p)) return { root: p, serverPath: join(p, 'mcp', 'server.mjs'), from: 'config file', tried }
  • 读取本地文件
    src/serving-client.mjs:31
    if (existsSync(join(cand, 'mcp', 'server.mjs'))) return { root: cand, serverPath: join(cand, 'mcp', 'server.mjs'), from: 'sibling/env', tried }
  • 执行外部命令来自配置/变量
    src/serving-client.mjs:48
    this.child = spawn(process.execPath, [this.serverPath], { stdio: ['pipe', 'pipe', 'pipe'] })
  • 发起网络请求
    src/serving-client.mjs:66
    await this.request('initialize', { protocolVersion: '2024-11-05', capabilities: {}, clientInfo: { name: 'training-sft', version: '0.1.0' } })
  • 发起网络请求
    src/serving-client.mjs:88
    const res = await this.request('tools/call', { name, arguments: args })
  • 读取本地文件
    src/data/prepare.mjs:83
    const t = readFileSync(p, 'utf8')
  • 读取本地文件
    src/data/prepare.mjs:92
    if (existsSync(root)) {
  • 读取本地文件
    src/data/prepare.mjs:93
    for (const d of readdirSync(root)) {
  • 读取本地文件
    src/data/prepare.mjs:95
    if (!existsSync(p)) continue
  • 读取本地文件
    src/data/prepare.mjs:97
    sets.push({ name: `wikitext-test(${d.includes('c512') ? 'c512' : 'c128'})`, kind: 'lm', file: p, rows, keyOf: (r) => r.t, sha256: `sha256:${contentHas
  • 读取本地文件
    src/data/prepare.mjs:101
    if (existsSync(mmlu)) {
  • 写入本地文件
    src/data/prepare.mjs:375
    mkdirSync(out, { recursive: true, mode: 0o700 })
  • 写入本地文件
    src/data/prepare.mjs:377
    writeFileSync(join(out, 'train.jsonl'), `${finalCalib.map(toLine).join('\n')}\n`, { mode: 0o600 })
  • 写入本地文件
    src/data/prepare.mjs:378
    writeFileSync(join(out, 'heldout.jsonl'), `${split.test.map(toLine).join('\n')}\n`, { mode: 0o600 })
  • 写入本地文件
    src/data/prepare.mjs:379
    writeFileSync(join(out, 'lineage.json'), `${JSON.stringify(lg, null, 2)}\n`, { mode: 0o600 })
  • 写入本地文件
    src/data/prepare.mjs:380
    writeFileSync(join(out, 'exclusions.json'), `${JSON.stringify({ pii: piiDropped, evalCollisions: evalDropped, evalContainment: containsDropped, note:
  • 执行外部命令固定命令
    src/worker.mjs:66
    this.child = spawn('docker', this.args(), { stdio: ['pipe', 'pipe', 'pipe'] })
  • 读取本地文件
    src/data/replay.mjs:93
    const rl = createInterface({ input: createReadStream(file).pipe(createGunzip()), crlfDelay: Infinity })
  • 读取本地文件
    src/data/replay.mjs:136
    createReadStream(file).on('data', (d) => h.update(d)).on('end', () => {
扫描于 2026/11/1(0 天前) · 范围 入口闭包 + 发布文件清单 · 来源 GitHub 仓库

静态扫描只反映源码中出现的调用,不构成安全背书;人工评估与自动扫描相互独立、互不覆盖。

依赖的 DSH / Cordis 模块
@deepseek-ai/dsh-tools
给这个插件打分还没有人投票↓
用户评分
还没有人投票,来当第一个

README

由 DeepSeek 最新模型翻译生成
@xiciyang/training-sft 用真实 GPU 对基座模型做 LoRA 监督微调(SFT),并把每一步变成可审计的产物:数据准备、训练、合并、验收、回退,全部留下哈希链与机器可读报告。 这是 DSH(DeepSeek Harness)插件包;也可以把它当作普通 Node 库调用(src/index.mjs 的导出面)。 它解决的问题 「训练跑完了」和「训练真的改变了权重」是两件事。本包在训练前后对权重取指纹,空操作训练(lr=0、数据为空、步数没生效)会被判为失败,而不是记成一次成功的 run。精度侧同理:验收要求先过「测量是否有效」再谈「数值是否达标」——输出退化(困惑度等于词表大小)不会被当成 0% 损失。 安装 dsh plugin add github:xiciyang/training-sft 或从 npm(元数据)。注意:本包的运行依赖是 @xiciyang/* 系列库,已发布到 npm。
展开完整文档(README 剩余 1 节)
@xiciyang/training-sft

用真实 GPU 对基座模型做 LoRA 监督微调(SFT),并把每一步变成可审计的产物:数据准备、训练、合并、验收、回退,全部留下哈希链与机器可读报告。

这是 DSH(DeepSeek Harness)插件包;也可以把它当作普通 Node 库调用(src/index.mjs 的导出面)。

它解决的问题

「训练跑完了」和「训练真的改变了权重」是两件事。本包在训练前后对权重取指纹,空操作训练(lr=0、数据为空、步数没生效)会被判为失败,而不是记成一次成功的 run。精度侧同理:验收要求先过「测量是否有效」再谈「数值是否达标」——输出退化(困惑度等于词表大小)不会被当成 0% 损失。

安装

dsh plugin add github:xiciyang/training-sft
或从 npm(元数据)。注意:本包的运行依赖是 @xiciyang/* 系列库,已发布到 npm。

要求:

- Node.js >= 20(DSH 侧),engines.dsh >= 0.2.0 < 0.3.0
- 真实训练需要:NVIDIA GPU + 容器运行时 + 训练镜像;缺失时 training_sft_health 会报明是哪一层不可用,而不是笼统地「不健康」
- Python 侧框架(torch / transformers / peft / trl / accelerate)在 optionalDependencies 里显式声明,缺哪个报哪个

工具面(DSH)

| 工具 | 作用 |
| training_sft_prepare | 数据准备:去重、确定性切分、去泄漏(train/val/test 三组交集必须为空)、PII 剔除(只剔除不改写源文件)、血缘与内容哈希 |
| training_sft_train | 训练:预算闸门(步数/GPU 小时)、权重指纹守卫、checkpoint 保留、审计链 |
| training_sft_merge | 合并 LoRA 适配器到基座 |
| training_sft_validate | 验收:双重门禁(先判测量是否有效,再判数值变化),产出机器可读的 eval-result |
| training_sft_rollback | 回退:回到指定 run 的状态;purge 只允许删 run 目录,越界拒绝 |
| training_sft_get_report | 取人类可读报告 |
| training_sft_health | 环境自检:GPU / 容器 / 镜像 / 基座模型 / 依赖,逐项给出可用性 |

配置(不把本机布局写死)

| 环境变量 | 用途 |
| DSH_BASE_MODEL | 基座模型本地目录(只读)。未设置时健康检查会指出缺这一项,而不是猜一个路径 |
| DSH_ALPACA_PATH | 原始数据集文件路径(复现数据准备测试时需要) |
| DSH_SHARD_PATH | 预处理语料分片路径(引用时用) |
| TRAINING_SFT_ROOT | 运行目录根(默认 ~/.ai-infra) |

硬件与后端都可替换:基座路径、镜像名、容器运行时、设备都不写死。没有 GPU 时,纯逻辑测试与契约测试仍然可以跑。

测试

node tests/run.mjs # 单元 + 契约 + 缺陷回归

测试分两类:纯逻辑/契约(任何机器都应绿)与需要本机历史产物的判据自检。后者在产物不存在时显式 SKIP 并写明原因,不伪装成通过——汇总行会打印 skipped 数。CI 上看到 skip 属预期,看到 fail 才是问题。

安全边界

- 训练与合并都需要显式确认令牌(每类一次、24 小时内同类操作免重复确认;高风险操作每次都要)
- 预算超限直接拒绝,不「先跑再说」
- 回退只作用于本插件自己的 run 目录

许可

BSD-3-Clause。见 LICENSE。
预览分享卡片长什么样 ↓xiciyang/training-sft
分享 · DeepSeek Harness Hub
xiciyang/training-sft

用真实 GPU 做 LoRA 微调,每步留痕可审计

回到顶部