File size: 9,984 Bytes
f5b0b3a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e5f98db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
ce27ff7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
e5f98db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
---
license: apache-2.0
base_model: openbmb/MiniCPM-V-4.7-1B
library_name: transformers
pipeline_tag: image-text-to-text
language:
  - zh
  - en
tags:
  - tool-calling
  - function-calling
  - agent
  - multimodal
  - chinese
---

# FinchAI-Rune1-Preview

> 首个 **FinchAI** 系列模型。底座 [MiniCPM-V 4.7-1B](https://huggingface.co/openbmb/MiniCPM-V-4.7-1B)(面壁智能 OpenBMB),
> 用 LoRA 微调而成,**重点是工具调用时的「判断力」**。

| | |
|---|---|
| **本仓库** | `-f16`(bfloat16 完整权重,2.9 GB) |
| **能力范围** | 文本 + **视觉**(多模态完整) |
| **加载方式** | `AutoModelForImageTextToText`(transformers ≥ 5.18.0) |
| **许可** | Apache 2.0 |

**这是当前唯一发布的版本,也是能力最完整的一份**:含视觉塔,可继续微调、可二次量化。
(GGUF 转换已验证可行,但导出的 GGUF 不含视觉,与「最完整」的定位不符,故暂不单独发布。)

---

## 一、这是什么

一个 1.55B 的本地小助手,专攻**什么时候该调工具、该调哪个**。

大多数小模型的工具调用只学会了「看到工具就调」或者「照抄工具名」。
Rune1-Preview 训练的重点是**判断**:

| 场景 | 期望行为 |
|---|---|
| 用户给了完整参数 | **直接调**,不要再问 |
| 用户漏了必填参数 | **反问**,不要瞎猜一个去试 |
| 两个工具都「能看文件」 | 按语义**选对**那个(按内容筛 vs 列目录) |
| 问题根本不需要工具 | **不调**,直接回答 |
| 调用报错了 | 读错误、**改对再来**,而不是放弃或硬编 |

## 二、验收数据(微调前 vs 微调后)

同一份基座权重,靠切换 adapter 跑两遍,27 条探针:

| 组 | 微调后 | 基座 |
|---|---|---|
| **判断力**(该不该调 / 要不要反问 / 选哪个) | **9/9** | 3/9 |
| 身份 | **3/3** | 0/3 |
| 留出沙箱(训练时从未见过的工具) | **6/6** | 6/6 |
| 已训沙箱 | **6/6** | 6/6 |
| 通用(问答 / 代码 / 拒绝) | **3/3** | 3/3 |
| **合计** | **27/27** | 21/27 |

**净增量 = 判断力 +6、身份 +3,合计 +9 项。**

其中有代表性的对比:

```
问:帮我看下目录里有什么文件。          (没给路径)
  微调后 → 「哪个目录?给我具体路径,我就去看。」   ✓ 反问
  基座   → 直接拿一个猜的路径去调了                  ✗

问:D:/inbox 里哪些文件提到 error?     (两个工具都能碰文件)
  微调后 → 调用搜索工具 seek_*                       ✓ 选对
  基座   → 调用列表工具 catalog_*                    ✗ 选错(但看起来"能跑")
```

### 关于「留出沙箱」

**留出沙箱 = 训练时结构上不可能产出样本的沙箱**(生成器里直接抛异常拦截)。
它存在的意义是给「数据有没有泄漏」一个硬指标:
模型在那些**从未见过的工具名、路径、参数 schema** 上也能正确调用,
说明它学的是「读工具定义、按语义选」,而不是把训练时见过的名字背下来。

## 三、快速开始

### transformers

```bash
pip install "transformers>=5.18.0" torch accelerate
```

```python
from transformers import AutoProcessor, AutoModelForImageTextToText

model_id = "whcl412/FinchAI-Rune1-Preview-f16"
proc = AutoProcessor.from_pretrained(model_id)
model = AutoModelForImageTextToText.from_pretrained(
    model_id, dtype="bfloat16", device_map="auto")

tools = [{"type": "function", "function": {
    "name": "list_files", "description": "列出目录内容",
    "parameters": {"type": "object",
                   "properties": {"path": {"type": "string", "description": "目录路径"}},
                   "required": ["path"]}}}]

msgs = [{"role": "user", "content": "看下 /var/log 里有哪些文件。"}]
text = proc.apply_chat_template(msgs, tools=tools, tokenize=False,
                                add_generation_prompt=True)
out = model.generate(**proc(text=[text], return_tensors="pt").to(model.device),
                     max_new_tokens=256, do_sample=False)
print(proc.tokenizer.decode(out[0], skip_special_tokens=True))
```

**工具调用的输出格式是 XML:**

```
<tool_call>
<function=list_files>
<parameter=path>
/var/log
</parameter>
</function>
</tool_call>
```

思考内容走 `reasoning_content`(不在 `content` 里)。

### Ollama / llama.cpp

**尚未发布。** GGUF 转换本身已验证可行(llama.cpp 自 2026-10-17 起支持
`MiniCPMV4_7ForConditionalGeneration`),但导出的 GGUF **不含视觉能力**
(LoRA 只训了文本主干),与「最完整版本」的定位不符,因此暂不单独发布。

⚠️ **两个必须知道的限制**:

1. 我们**没有发布 MLX 4bit 版本** —— 底座架构 `minicpmv4_7` 不被 `mlx_lm` 支持
   (连最新 main 都没有)。Apple Silicon 用户请走 transformers,MPS 实测可用
   (训练峰值内存 6.5 GB)。
2. 全链路(加载 / 微调 / 融合)**只在 Apple Silicon 的 MPS 上验证过**,未在 CUDA 上实测。

## 四、能力边界

**擅长**
- 本地 agent 的「工具选择大脑」——判断该不该调、调哪个、参数够不够
- 读一份没见过的工具定义并按它调用
- 简短、不谄媚的中文/英文回答

**不擅长**
- 复杂多步推理和算法设计(1B 容量限制)
- 长文档理解(训练时序列 ≤950 token)
- 视觉任务——底座支持图像输入,但**本版 LoRA 只训了文本主干**,视觉能力未经强化

**实测性能**(MacBook Pro M4 / 16 GB,MPS)

| 项目 | 数值 |
|---|---|
| 权重体积 | 2.9 GB(bfloat16) |
| 加载后常驻内存 | ~3.1 GB |
| 训练/推理峰值 | ~6.5 GB |
| 训练速度 | 2.2~3.5 s/样本(≤950 token) |

**已知问题**

| # | 问题 | 规避 |
|---|---|---|
| 1 | 没有 MLX 4bit 版(底座架构不被 `mlx_lm` 支持) | Apple Silicon 走 transformers + MPS |
| 2 | 未发布 GGUF(转出来的不含视觉能力) | 要视觉就用本仓库的 f16 |
| 3 | 输出里偶发游离的 `</think>` 标签 | 宿主输出前过滤 |
| 4 | 思考文案带模板生成痕迹(如中英混排) | 不影响功能 |
| 5 | **偶发工具名幻觉**(吐出不在列表里的名字) | **宿主分发必须查注册表,绝不直接执行** |
| 6 | **工具结果不足时会编数字** | 让工具返回直接可得答案,别让它自己数 |
| 7 | 跨句式泛化有限 | 没见过的说法可能掉线 |
| 8 | 身份细节会补充编造 | 只采信「名字 + 底座」两项 |
| 9 | **工具的顺序会影响它选哪个** | 见下方说明 |

#### 关于第 6 条:工具结果不足时会编数字

如果工具返回的信息不足以回答,它可能**直接编一个结果**,而不是说"信息不够"。

实测:问「目录里有几个 `.gguf` 文件」,它只调了 `list_files`(返回的是目录列表),
却直接答「**有 269 个**」——它根本没数过(真实值是 20)。

**规避**:让工具的返回**直接可得答案**。例如不要指望它"从列表里数个数",
而是提供一个 `count_files(pattern, path)` 这类专用工具。这是 1B 模型的可靠边界。

#### 关于第 9 条:工具的顺序会影响它选哪个

给同一组工具,**只换顺序、问题一字不改**,它的选择会变。

实测(工具:`get_weather` / `query_database` / `send_notification`):

| 工具顺序 | 「查 users 表有多少条」 | 「给张三发通知」 |
|---|---|---|
| 天气, SQL, 通知 | ✗ 没调用工具 | ✓ |
| SQL, 天气, 通知 | ✓ | ✗ |
| 通知, SQL, 天气 | ✓ | ✗ |

**根因**:训练沙箱里工具顺序是固定的,模型学到了一点**位置先验**——
换一组语义完全不同的工具时,它不完全只看描述。

**规避**:
1. 把最可能被用到的工具**排在前面**
2. 一次只传相关的少数工具(工具越少选得越准)
3. 宿主侧校验结果,发现调了不相关工具就重试

**注意:这不是"必须用某个框架"** —— 工具仍然完全由调用方定义,模型没有内置工具,
只是对排列顺序比理想情况更敏感一些。

## 五、怎么训的(简述)

**沙箱式数据**:每个训练样本来自一个程序化生成的「沙箱」,包含独立的
工具名、参数 schema、路径风格、错误消息风格。任务是**真的去读工具定义**才能做对。

**Agent 分五个子类型**,这是模型价值的来源:

| 子类型 | 教什么 | 占比 |
|---|---|---|
| `single` | 标准两步调用 | 25% |
| `recover` | 撞错 → 读错误 → 改对重试 | 20% |
| `disambig` | 两个相似工具里按语义选对 | 20% |
| `no_tool` | 有工具但这个问题不该用 | 20% |
| `ask_back` / `ask_direct` | 缺参数才反问,给了参数就直接调 | 15% |

**防泄漏五层**:命名空间物理隔离 / 生成器硬拦截留出沙箱 / 渲染后 token 预算 /
渲染后文本审计 / 非 Agent 样本禁含沙箱标识符 —— 外加第六层「参数名必须属于该工具定义」。

**防遗忘**(增量训练时):数据保持完整六类配比 + 学习率减半 + 只训 0.5 epoch。

## 六、局限与许可

- 底座 MiniCPM-V 4.7-1B 为 Apache 2.0,本模型沿用
- 这是 **Preview** 版本:判断力已达标(9/9),但句式泛化和拒绝场景仍在扩充
- 训练数据是**合成的**,用于教学/研究/自建 agent 均可,请自测后再用于生产

## 七、项目信息

```
权重    HuggingFace  whcl412/FinchAI-Rune1-Preview-f16
        ModelScope   whcl412/FinchAI-Rune1-Preview-f16
代码    GitHub       hwc-cell/FinchAI-Rune1-Preview
```
GitHub 仓库含训练脚本、数据生成器、验收脚本与 LoRA adapter。
训练数据为**程序化合成**(600 条),不使用任何真实用户数据。

---

*FinchAI 系列 · 训练于 Apple Silicon(transformers + PEFT + MPS)*