StartLux-Decision 源码深度分析

StartLux-Decision 源码深度分析

分析日期:2026-10-04

项目地址:https://github.com/StartLuxLabs/StartLux-Decision

Stars:178 | Language:Python | Size:~85MB

模型权重:HuggingFace / ModelScope


一、项目概览

属性 信息
定位 类型化决策模型(Typed Decision Model)
模型规格 5 个 Dense 尺寸(0.8B/2B/4B/9B/27B)+ 1 个 MoE(35B-A3B)
核心能力 给定状态+问题集合 → 每个选项返回概率,不生成任何文本
上下文窗口 256K tokens(262,144)
多模态 支持图像输入(视觉塔)
延迟 0.8B: 12ms / 4B: 26ms / 27B: 102ms / 35B-A3B: 52ms(单 H200)
协议 TypeSafe /v1/systemone 格式,兼容 Jev API
许可证 自定义(非标准开源许可)

应用场景

  • 客服工单分类/路由
  • 国际象棋落子决策
  • 游戏 AI(超级马里奥、星际争霸、Doom)
  • 浏览器自动化(Computer Use)
  • 体育比赛策略(JevBall 足球)

二、项目结构

复制代码
StartLux-Decision/
├── startlux_decision/          # 核心推理代码
│   ├── __init__.py
│   ├── model.py                # ⭐ 核心模型推理引擎(38KB)
│   ├── server.py               # HTTP 服务
│   ├── jevfmt.py               # 问题格式渲染
│   ├── check.py                # 快速内核检查
│   ├── mlx_model.py            # Apple Silicon MLX 后端
│   ├── mlx_int8.py             # MLX INT8 量化
│   └── gguf_server.py          # GGUF 格式服务
├── finetune/                   # 微调代码
│   ├── finetune_lora.py        # ⭐ LoRA 微调脚本
│   └── calibrate.py            # 温度校准
├── eval/                       # 评估代码
│   ├── typed_decisions.py      # 评估套件
│   ├── suites.py               # 基准测试集
│   ├── latency.py              # 延迟测试
│   └── di/                     # Decision Index 评估
├── demos/                      # 演示
│   ├── chess/                  # 国际象棋对弈
│   └── computer_use/           # 浏览器自动化
├── docs/                       # 文档
│   ├── inference.md            # 推理指南
│   ├── finetuning.md           # 微调指南
│   ├── evaluation.md           # 评估指南
│   └── results.md              # 结果数据
├── results/                    # 原始评估结果
└── requirements.txt

三、是否包含模型网络结构?

结论:包含推理代码,但网络结构依赖 HuggingFace Transformers,不是从头定义的。

模型加载方式

python 复制代码
# startlux_decision/model.py
def load_model(path, device):
    config = transformers.AutoConfig.from_pretrained(path)
    extra = {"experts_implementation": "grouped_mm"} if getattr(config.get_text_config(), "num_experts", 0) else {}
    model = getattr(transformers, config.architectures[0]).from_pretrained(path, ...)
    return model, getattr(model.model, "language_model", model.model)

这意味着:

  • 网络结构定义在 HuggingFace 的 transformers 库中(通过 config.architectures[0] 动态加载)
  • 模型使用了线性注意力层 (Linear Attention),需要 flash-linear-attention 和 causal-conv1d 加速库
  • MoE 变体使用 grouped_mm(分组矩阵乘法)实现专家层
  • 包含视觉塔(Vision Tower),用于图像理解
  • model.py 的核心是推理引擎(CUDA Graphs、共享 KV 缓存、分块预填充),而不是网络层定义

简言之: 你看不到 class TransformerBlock(nn.Module) 这样的定义------结构由 HuggingFace 的 AutoConfig + 检查点中的 config.json 决定。


四、能否自己训练?

可以做 LoRA 微调,但不能从头预训练。

✅ 提供的:LoRA 微调

finetune/finetune_lora.py 提供了完整的 LoRA 微调流程:

bash 复制代码
# 1. LoRA 微调
python finetune/finetune_lora.py --model StartLux-Decision-4B \
  --train train.jsonl --dev dev.jsonl --out runs/mine

# 2. 温度校准(拟合每种问题类型的最优温度)
python finetune/calibrate.py --model runs/mine/merged --dev dev.jsonl

# 3. 部署
python -m startlux_decision.server --model runs/mine/merged --port 8090

训练数据格式(JSONL):

json 复制代码
{
  "state": {"ticket": "Refund still missing after two weeks", "customer_tier": "pro"},
  "questions": {
    "team": {"type": "choice", "instructions": "Which team?",
             "criteria": {"billing": "Payments", "shipping": "Delivery", "technical": "Bugs"}},
    "urgent": {"type": "noul", "instructions": "Solved today?"},
    "severity": {"type": "score", "criteria": ["cosmetic", "annoying", "blocks customer"]}
  },
  "targets": {"team": {"billing": 1.0}, "urgent": {"false": 1.0}, "severity": {"1": 0.7, "2": 0.3}}
}

微调参数:

  • rank=16, alpha=32, dropout=0.05
  • lr=1e-4, warmup=5%, cosine decay
  • 2 epochs, 4 micro-batches per optimizer step
  • 损失函数:选项字母 logits 上的交叉熵

性能参考: 单 H200 上,4B 模型 6000 条样本约 3 分钟完成。

❌ 不提供的

缺失项 说明
预训练代码 没有从头训练模型的代码
预训练数据集 只知道用了 14 个公开 benchmark 的训练集(已过滤测试集)
网络结构定义 依赖 transformers 库中的架构类
训练超参细节 预训练的 lr schedule、batch size、数据配比等未公开

五、决策推理的核心原理 ⭐

核心机制:Logit Readout(Logits 直读)

这是最关键的创新------完全不做文本生成,一次前向传播直接读出答案。

复制代码
用户输入: state + questions
           │
           ▼
   ┌─ 将每个问题渲染为 prompt ──────────────┐
   │  "工单: 退款两周未到账...               │
   │   Question: 哪个团队处理这个工单?       │
   │   A. billing (Payments, refunds)        │
   │   B. shipping (Delivery, tracking)      │
   │   C. technical (App bugs, outages)      │
   │   Answer:"                              │
   └─────────────────────────────────────────┘
           │
           ▼
     一次前向传播 (single forward pass)
           │
           ▼
   读取 "Answer:" 位置的 hidden state (h)
           │
           ▼
   logits = h × letter_rows^T    ← 只乘 A-Z 这 26 个字母的 output embedding
           │
           ▼
   probabilities = softmax(logits / temperature)
           │
           ▼
   返回: {"billing": 0.877, "shipping": 0.005, "technical": 0.118}

源码关键片段

python 复制代码
# 初始化时:只提取选项字母(A-Z)对应的 output embedding 行
self.letter_rows = head.index_select(0, torch.tensor(self.letters)).float()

# 推理时:一次前向传播,取最后一个有效 token 的 hidden state
hidden = self.body(input_ids=ids, use_cache=False).last_hidden_state
h = hidden[torch.arange(ids.shape[0]), last].float()

# 矩阵乘法得到 26 个字母的 logits → softmax 得到概率
logits = h @ self.letter_rows.T

与传统 LLM 的对比

维度 传统 LLM(如 GPT/Claude) StartLux-Decision
输出方式 自回归生成文本(token by token) 一次前向传播,直读 logits
计算量 生成 N 个 token → N 次前向传播 1 次前向传播
确定性 采样有随机性 确定性(softmax 固定)
输出格式 自由文本,需要解析 结构化概率分布
延迟 数百毫秒到数秒 12-102ms
置信度 无内置置信度 每个选项都有概率值
幻觉风险 可能生成不存在的选项 不可能(只能选给定选项)

三种问题类型

类型 说明 输出
choice 从 N 个选项中选(最多 26 个) 选中项 + 所有选项的概率分布
noul Yes/No 二选一 yes 的概率(0-1)
score 评分等级(最多 10 级) 概率加权平均分 + 每级概率

超过 26 个选项时自动分组:先分组淘汰,top-3 进入决赛轮,落选选项保留残余概率。


六、为何能做到极快?------ 三层加速

1️⃣ 无生成(最大贡献)------ 省掉 90%+ 计算量

复制代码
传统 LLM:  "我认为应该分配给 billing 团队..." → 30+ tokens → 30+ 次前向传播
Decision:  [billing=0.877, shipping=0.005, technical=0.118] → 1 次前向传播

2️⃣ CUDA Graphs ------ 消除 kernel 启动开销

python 复制代码
# 启动时预录制 CUDA 图:每种输入长度一张图
GRAPH_LENGTHS = (128, 192, 256, 320, 384, 512, 640, 768, 1024, 1536, 2048, 3072, 4096)
GRAPH_ROWS = (1, 2, 3, 4)  # 每个请求的问题数 → 共 40 张图

# 推理时直接重放图,跳过逐层 kernel 调度
graph = torch.cuda.CUDAGraph()
with torch.cuda.graph(graph, pool=pool):
    out = self._slot_logits(ids, last)

效果对比(4B 模型):

  • CUDA Graphs ON: 26.0 ms
  • CUDA Graphs OFF: 90.3 ms
  • 差距:3.5 倍

3️⃣ Flash Linear Attention + 共享 KV 缓存

  • 线性注意力层 :模型混合使用标准注意力和线性注意力,后者需要 flash-linear-attention + causal-conv1d 加速(没有这两个库会慢 10 倍以上)
  • 共享 KV 缓存:同一请求的多个问题共享相同的 state/evidence,共享部分只计算一次:
python 复制代码
SHARE_MIN = 4096       # 共享前缀超过此长度才触发
PREFILL_CHUNK = 32768  # 分块处理长输入,控制激活内存

# 同一请求中多个问题:"哪个团队?""是否紧急?""严重程度?"
# 三个 prompt 都包含完整的 state → 共享前缀只计算一次
# 后面的问题部分作为一个 batch 在共享 KV 上运行

延迟实测(单 H200 GPU,bf16)

模型 3 个问题(一次前向) 单个 Yes/No
0.8B 12.2 ms 8.3 ms
2B 15.5 ms 9.6 ms
4B 26.0 ms 14.7 ms
9B 35.7 ms 17.6 ms
27B 102.3 ms 50.7 ms
35B-A3B (MoE) 52.5 ms 36.4 ms

35B-A3B 比 27B 快一半,因为 MoE 每次只激活约 3B 参数。

与竞品延迟对比

模型 3 fields 延迟 硬件
StartLux-Decision-0.8B 12.2 ms H200
StartLux-Decision-4B 26.0 ms H200
Intern-Decision-0.8B 34.0 ms RTX 4090
Intern-Decision-4B 44.2 ms RTX 4090
Jev 1.13 64.0 ms TypeSafe API (server time)

七、长输入处理(256K tokens)

python 复制代码
# 长 prompt 分块处理,控制内存
PREFILL_CHUNK = 32768  # 每次处理 32K tokens

# 每个 chunk:
# 1. 对之前的 keys 做非因果注意力(无 mask)
# 2. 对自己的 keys 做因果注意力
# 3. 两部分的输出通过 log-sum-exp 合并
  • 256K tokens 的 27B/35B 需要约 80GB GPU 显存
  • 内存主要由 KV 缓存占用,激活内存通过分块控制

八、多模态(图像输入)

python 复制代码
# 图像作为证据的一部分
answers, usage = m.decide(
    "Photo at delivery: <image>",
    {"damaged": {"type": "noul", "instructions": "Is the parcel damaged?"}},
    images=["parcel.jpg"]
)
  • 每张图像 resize 到最多 1,048,576 像素(max_pixels)
  • 每 32×32 像素 → 1 个 token(1024×1024 图 = 1024 tokens)
  • 视觉塔每个请求只运行一次,所有问题共享图像 token
  • 视觉塔额外占用 0.2-0.9 GB 显存
  • 可通过 images=False 关闭以节省显存

九、Decision Index 评估结果

StartLux-Decision-27B 在 Decision Index 0.2.1 上得分 63.88,超过 Jev 1.13 的 57.91。

领域 StartLux-27B Jev 1.13 差距
Decision Index 总分 63.88 57.91 +5.97
语言理解 74.5 62.0 +12.5
检索与分类 66.8 55.4 +11.4
工具与自动化 82.2 75.1 +7.1
艺术与人类品味 47.9 37.7 +10.2
知识与推理 44.3 51.4 -7.1

弱项: 在 GPQA Diamond(研究生级科学问答)、MMLU-Pro、BBH 等纯知识推理基准上不如 Jev 1.13。


十、技术总结

问题 答案
包含网络结构吗? 推理代码完整,结构定义在 HuggingFace transformers 中,不是自定义网络
能自己训练吗? ✅ LoRA 微调(完整代码),❌ 从头预训练(无代码和数据)
决策原理? 一次前向传播 → 读取选项字母位置的 logits → softmax 得到概率分布。不生成任何文本
为何快? ① 无生成(1 次 vs N 次前向传播)② CUDA Graphs 消除启动开销 ③ Flash Linear Attention + 共享 KV
创新点? 把"分类/决策"问题重新定义为"读 logits"问题,用 transformer 的 output embedding 空间直接做分类

本质上: 这不是一个新的模型架构,而是一个巧妙的推理范式------把 transformer 当成"概率分配器"而非"文本生成器"。创新在于"怎么读答案",而非"模型长什么样"。