whcl412 commited on
Commit
6b3dc58
·
verified ·
1 Parent(s): 91cea8e

LycheeAI-coder-2b-II-pro v6.1 (MLX 4bit)

Browse files
Files changed (2) hide show
  1. README.md +372 -93
  2. model.safetensors +1 -1
README.md CHANGED
@@ -1,16 +1,21 @@
1
  ---
2
  license: apache-2.0
3
  tags:
4
- - mlx
5
  - code
6
  - minicpm
7
  - chinese
8
  - conversational
9
  - tool-calling
 
 
10
  base_model: openbmb/MiniCPM5-2B
 
 
11
  ---
12
 
13
- # LycheeAI-coder-2b-II-pro
 
 
14
 
15
  > 基于 [MiniCPM5-2B](https://huggingface.co/openbmb/MiniCPM5-2B) 微调的轻量编程助手 · Apache 2.0
16
  > **2B 参数,主打本地工具调用**
@@ -19,8 +24,13 @@ base_model: openbmb/MiniCPM5-2B
19
 
20
  它最大的用处是:**跑在你自己的机器上,不用联网,能调工具,响应飞快。**
21
 
 
 
 
22
  ---
23
 
 
 
24
  ## 这一版做了什么
25
 
26
  上一版(1b-II)最大的短板是**工具调用完全不会**——训练数据里一条工具样本都没有。这一版专门补上了这块:
@@ -37,7 +47,36 @@ base_model: openbmb/MiniCPM5-2B
37
 
38
  ---
39
 
40
- ## 工具调用是什么样
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
41
 
42
  它输出的是**裸 JSON**(OpenAI function calling 风格),不带任何包裹:
43
 
@@ -50,55 +89,169 @@ base_model: openbmb/MiniCPM5-2B
50
  ### 单步调用
51
 
52
  ```
53
- 【用户】北京今天天气怎么样?
 
 
 
 
 
 
54
 
55
- 【模型】
56
- <think>
57
- 用户问今天北京天气,我该调工具吗?有 get_weather 可以,参数是城市。
58
- </think>
59
 
 
60
  {"name": "get_weather", "arguments": {"city": "北京"}}
61
  ```
62
 
63
  ### 多步调用(有依赖时只输出第一个)
64
 
65
- ```
66
- 【用户】查一下北京天气,然后算 123*456
67
 
68
- 【模型】
69
  {"name": "get_weather", "arguments": {"city": "北京"}}
70
  ```
71
 
72
- 它**不会**一次把两个调用都吐出来——因为第二个需要第一个的结果。等宿主返回天气后,它会继续输出 `calculate` 的调用。
73
 
74
  ### 完全独立的调用会并列输出
75
 
76
- ```
77
- 【用户】北京和上海今天天气怎么样?
78
 
79
- 【模型】
80
  {"name": "get_weather", "arguments": {"city": "北京"}}
81
  {"name": "get_weather", "arguments": {"city": "上海"}}
82
  ```
83
 
84
  ### 该拒绝时会明确拒绝
85
 
86
- ```
87
- 【用户】帮我订一张明天去上海的机票
88
 
89
- 【模型】
90
- 这个我做不了 —— 我没有订票或支付能力。
91
 
92
- 我能帮你的是:查明天上海的天气、算数学题、或搜相关信息。
93
- ```
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
94
 
95
- **关键点:它不会因为手上有 `search_web` 就假装自己能订票。** 工具是接口,不是权限——这是专门训练过的行为。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
96
 
97
  ---
98
 
99
- ## ⚠️ 已知问题(请务必看)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
100
 
101
- **身份问答在「宿主提供的通用 system」下会出错。**
 
 
 
 
 
 
 
 
 
 
102
 
103
  如果你的 system prompt 是这样(很多 agent 框架的默认写法):
104
 
@@ -133,123 +286,249 @@ base_model: openbmb/MiniCPM5-2B
133
  ...
134
  ```
135
 
136
- 这个问题会在下一版修掉(补 OOD 样本)。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
137
 
138
  ---
139
 
140
- ## 快速开始
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
141
 
142
- ### MLX(Apple Silicon 原生,推荐)
 
 
 
 
 
 
 
143
 
144
  ```bash
145
  pip install mlx-lm
146
 
147
  python -m mlx_lm.generate \
148
  --model whcl412/LycheeAI-coder-2b-II-pro \
149
- --prompt "帮我写个快速排序"
150
- ```
151
 
152
- 起个 OpenAI 兼容的服务:
153
-
154
- ```bash
155
  python -m mlx_lm.server --model whcl412/LycheeAI-coder-2b-II-pro --port 8080
156
  ```
157
 
158
- ### Ollama(GGUF 版)
159
 
160
- **尚未发布**。本仓库是 MLX 4bit 量化格式,无法直接转 GGUF,
161
- 需要先从 f16 全精度重新融合一次。需要的话可以提 issue。
162
 
163
- ### transformers(需要自己转 HF 格式)
164
 
165
- 本仓库是 **MLX 4bit 量化格式**,不能直接用 transformers 加载。
166
- 如果需要 HF safetensors 版本,请从 `MiniCPM5-2B` 基座自行转换,或提 issue。
167
 
168
  ---
169
 
170
- ## 工具调用的接入提示
171
 
172
- ### 格式不是通用的
173
 
174
- **这一点很重要**:不同 agent 框架的工具调用格式不一样。
175
 
176
- | 框架/模型 | 格式 |
177
- |---|---|
178
- | OpenAI / 大多数本地框架 | 裸 JSON `{"name":..., "arguments":{...}}` |
179
- | Anthropic / Claude Tools | XML 标签 `<function_calls><invoke name="...">` |
180
- | 部分国产模型 | `<tool_call>` 自定义标签包 JSON |
181
- | MCP | 传输层协议,内部通常还是 JSON-RPC |
182
 
183
- **它默认输出裸 JSON**。如果你的宿主需要别的格式,在 system 里明确告诉它,它会按你说的来。
184
 
185
- ### 一次调用 vs 多次调用
186
 
187
- - **独立调用**(同时查北京和上海的天气)→ 它会并列输出多行 JSON
188
- - **依赖调用**(先查天气,再根据结果决定要不要提醒带伞)→ 它只输出第一个,等结果回来再继续
189
 
190
- 宿主需要循环驱动:解析 → 执行 → 把结果喂回去 → 再解析。
 
 
191
 
192
- ---
193
 
194
- ## 训练信息
195
 
196
- | 项 | 值 |
197
- |---|---|
198
- | 基座 | `openbmb/MiniCPM5-2B` |
199
- | 方法 | LoRA(rank 8,16 层) |
200
- | 数据量 | 2,574 条(1,739 通用 + 835 工具调用) |
201
- | 轮次 | 1.5 epoch(1,930 步) |
202
- | 框架 | MLX-LM |
203
- | 量化 | 4bit(4.501 bits/weight) |
204
 
205
- ### 工具数据设计
206
 
207
- 分五批造的,每批解决一个具体问题:
208
 
209
- | 批次 | 条数 | 解决什么 |
210
- |---|---|---|
211
- | v2 | 268 | 从零建立工具调用能力(单步/多选/拒绝/解读) |
212
- | v3 | 222 | 纠偏:多步调用串台成 XML、中文参数被翻译、想半天不给结论 |
213
- | v4 | 164 | 修:自称 Qwen、给了工具却心算 |
214
- | v5 | 181 | 修:拒绝能力被"该用工具"压掉、身份全名丢后缀 |
215
 
216
- **三类行为严格区分**(这是训练中最容易搞混的地方):
217
 
218
- | 类别 | 例子 | 正确行为 |
219
  |---|---|---|
220
- | 工具调用 | `789*123` | 调 `calculate` |
221
- | **真拒绝**(能力/伦理不允许) | 订机票、破解 WiFi | 说不做 + 给替代方案 |
222
- | **无需工具** | 什么是递归、写二分查找 | 直接回答,不提工具 |
 
223
 
224
- 混为一谈会导致模型把正常提问也当成要拒绝的事——踩过这个坑。
225
 
226
  ---
227
 
228
- ## 能力边界
229
-
230
- **能做:**
231
- - 写代码、调 bug、解释技术概念
232
- - 单步 / 多步工具调用(裸 JSON)
233
- - 拒绝能力范围外或不合规的请求
234
- - 解读工具返回结果
235
- - 中文 / 英文 / 粤语
236
 
237
- **不擅长:**
238
- - 复杂多步推理(2B 容量限制)
239
- - 超长上下文(虽然基座支持 512K,但实际长文表现没测)
240
- - 无工具时的多位数心算(会算错,请给 `calculate`)
241
- - 自称身份的 OOD 场景(见上面"已知问题")
 
 
 
 
 
242
 
243
  ---
244
 
245
- ## 许可
246
 
247
- Apache 2.0,跟基座 MiniCPM5-2B 一致。
248
 
249
- 训练数据、脚本都在项目里,欢迎 issue 交流。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
250
 
251
  ---
252
 
253
  <p align="center">
254
- <sub>LycheeAI · 2026</sub>
 
255
  </p>
 
1
  ---
2
  license: apache-2.0
3
  tags:
 
4
  - code
5
  - minicpm
6
  - chinese
7
  - conversational
8
  - tool-calling
9
+ - mlx
10
+ - quantization
11
  base_model: openbmb/MiniCPM5-2B
12
+ pipeline_tag: text-generation
13
+ library_name: mlx
14
  ---
15
 
16
+ # LycheeAI-coder-2b-II-pro · MLX 4bit
17
+
18
+ [中文](#中文) | [English](#english)
19
 
20
  > 基于 [MiniCPM5-2B](https://huggingface.co/openbmb/MiniCPM5-2B) 微调的轻量编程助手 · Apache 2.0
21
  > **2B 参数,主打本地工具调用**
 
24
 
25
  它最大的用处是:**跑在你自己的机器上,不用联网,能调工具,响应飞快。**
26
 
27
+ **本仓库是 MLX 4bit 量化版本**,1.4 GB,Apple Silicon 上开箱即用。
28
+ 需要全精度(转 GGUF、二次量化、继续微调)→ [`whcl412/LycheeAI-coder-2b-II-pro-f16`](https://huggingface.co/whcl412/LycheeAI-coder-2b-II-pro-f16)(bfloat16,5.03 GB)。
29
+
30
  ---
31
 
32
+ # 中文
33
+
34
  ## 这一版做了什么
35
 
36
  上一版(1b-II)最大的短板是**工具调用完全不会**——训练数据里一条工具样本都没有。这一版专门补上了这块:
 
47
 
48
  ---
49
 
50
+ ## 快速开始
51
+
52
+ ### MLX(Apple Silicon,本仓库)
53
+
54
+ ```bash
55
+ pip install mlx-lm
56
+
57
+ # 直接加载
58
+ python -m mlx_lm.generate \
59
+ --model whcl412/LycheeAI-coder-2b-II-pro \
60
+ --prompt "帮我写个快速排序"
61
+
62
+ # 起个 OpenAI 兼容的服务
63
+ python -m mlx_lm.server --model whcl412/LycheeAI-coder-2b-II-pro --port 8080
64
+ ```
65
+
66
+ ### transformers
67
+
68
+ 本仓库是 **MLX 4bit 格式**,transformers 不能直接加载。
69
+ 需要 HF safetensors 请用 f16 仓库 → [`whcl412/LycheeAI-coder-2b-II-pro-f16`](https://huggingface.co/whcl412/LycheeAI-coder-2b-II-pro-f16)。
70
+
71
+ ### Ollama(GGUF)
72
+
73
+ **尚未发布**。需要先从 f16 仓库转 GGUF(`llama.cpp/convert_hf_to_gguf.py`),欢迎提 issue。
74
+
75
+ ---
76
+
77
+ ## 工具调用
78
+
79
+ ### 输出格式
80
 
81
  它输出的是**裸 JSON**(OpenAI function calling 风格),不带任何包裹:
82
 
 
89
  ### 单步调用
90
 
91
  ```
92
+ system: 你是 LycheeAI-coder-2b-II-pro。可以使用工具来帮助用户。
93
+
94
+ 可用工具:
95
+ - get_weather(city: string): 查询指定城市的天气
96
+
97
+ user: 北京今天天气怎么样?
98
+ ```
99
 
100
+ 输出:
 
 
 
101
 
102
+ ```json
103
  {"name": "get_weather", "arguments": {"city": "北京"}}
104
  ```
105
 
106
  ### 多步调用(有依赖时只输出第一个)
107
 
108
+ 问"北京今天适合出门吗",它需要先查天气再判断,此时**只输出第一步**:
 
109
 
110
+ ```json
111
  {"name": "get_weather", "arguments": {"city": "北京"}}
112
  ```
113
 
114
+ 你把工具结果喂回去,它再继续。**宿主需要循环驱动**:解析 → 执行 → 喂回结果 → 再解析。
115
 
116
  ### 完全独立的调用会并列输出
117
 
118
+ 同时查北京和上海,它会一次给两行:
 
119
 
120
+ ```json
121
  {"name": "get_weather", "arguments": {"city": "北京"}}
122
  {"name": "get_weather", "arguments": {"city": "上海"}}
123
  ```
124
 
125
  ### 该拒绝时会明确拒绝
126
 
127
+ 不是所有请求都调工具。超出能力或不合规的,它会说明原因并给替代方案,不会硬编一个工具调用糊弄过去。
 
128
 
129
+ ---
 
130
 
131
+ ## 宿主接入注意
132
+
133
+ ### 格式不是通用的
134
+
135
+ **这一点很重要**:不同 agent 框架的工具调用格式不一样。
136
+
137
+ | 框架/模型 | 格式 |
138
+ |---|---|
139
+ | OpenAI / 大多数本地框架 | 裸 JSON `{"name":..., "arguments":{...}}` |
140
+ | Anthropic / Claude Tools | XML 标签 `<function_calls><invoke name="...">` |
141
+ | 部分国产模型 | `<tool_call>` 自定义标签包 JSON |
142
+ | MCP | 传输层协议,内部通常还是 JSON-RPC |
143
+
144
+ **它默认输出裸 JSON**。如果你的宿主需要别的格式,在 system 里明确告诉它,它会按你说的来。
145
+
146
+ ### 什么时候给工具,什么时候别给
147
+
148
+ 它训练时见过四类场景,行为是分开的:
149
+
150
+ | 类别 | 例子 | 它的行为 |
151
+ |---|---|---|
152
+ | 工具能算出确定结果 | `789*123`、`1000 美元换人民币` | 调工具 |
153
+ | 能力/伦理不允许 | 订机票、破解 WiFi、伪造证明 | 明确拒绝 + 给替代方案 |
154
+ | 工具帮不上忙 | 什么是递归、写二分查找 | 直接回答 |
155
+ | **宿主没有工具** | 纯聊天软件里的"帮我搜一下" | 说明没有这个能力,不硬调 |
156
+
157
+ **最后一行很关键**��如果你的宿主是纯聊天(微信、客服机器人),**不要给它任何工具定义**,它会自然地说"我这边没有联网能力",而不是吐一坨宿主接不住的 JSON。
158
+
159
+ **如果你给它 `calculate` 却不希望它算简单加减**,可以在 system 里说明。默认行为是"算术优先用工具"。
160
+
161
+ ---
162
 
163
+ ## 训练信息
164
+
165
+ | 项 | 值 |
166
+ |---|---|
167
+ | 基座 | `openbmb/MiniCPM5-2B` |
168
+ | 方法 | LoRA(rank 8,dropout 0,scale 20,16 层) |
169
+ | 数据量 | 5,341 条 |
170
+ | 轮次 | 1 epoch(2,671 步) |
171
+ | 学习率 | 5e-5(adam) |
172
+ | batch / seq | 2 / 2048 |
173
+ | 框架 | MLX-LM 0.31.3 |
174
+ | 本版本量化 | 4bit affine(group_size 64,4.501 bits/weight) |
175
+
176
+ ### 数据构成(v6 系列)
177
+
178
+ v6 是在 v5 基础上做的**定向修复**,共四批:
179
+
180
+ | 批次 | 条数 | 解决什么 |
181
+ |---|---|---|
182
+ | v5 基础 | 4,526 | v6.1 起点(v5 + OOD 初版) |
183
+ | v6.1 | 4,526 | 修 v6 的 ⑥⑨ 退步项,OOD 补强 |
184
+ | v6.2 | 4,778 | 补算术泛化(K6,252 条程序化生成) |
185
+ | v6.3 | 5,093 | 补能力边界 + 结果收尾(K7,315 条) |
186
+ | **v6.4** | 5,341 | 补运算类型均衡(K8,248 条) |
187
+
188
+ **发布的是 v6.1**(不是 v6.4)。原因见下面"关于迭代"。
189
+
190
+ ### 三类行为严格区分
191
+
192
+ 这是训练中最容易搞混的地方:
193
+
194
+ | 类别 | 例子 | 正确行为 |
195
+ |---|---|---|
196
+ | 工具调用 | `789*123` | 调 `calculate` |
197
+ | **真拒绝**(能力/伦理不允许) | 订机票、破解 WiFi | 说不做 + 给替代方案 |
198
+ | **无需工具** | 什么是递归、写二分查找 | 直接回答,不提工具 |
199
+
200
+ 混为一谈会导致模型把正常提问也当成要拒绝的事——踩过这个坑。
201
+
202
+ ---
203
+
204
+ ## 能力边界
205
+
206
+ **能做:**
207
+ - 写代码、调 bug、解释技术概念
208
+ - 单步 / 多步工具调用(裸 JSON)
209
+ - 拒绝能力范围外或不合规的请求
210
+ - 解读工具返回结果
211
+ - 中文 / 英文 / 粤语
212
+
213
+ **不擅长:**
214
+ - 复杂多步推理(2B 容量限制)
215
+ - 超长上下文(虽然基座支持 512K,但实际长文表现没测)
216
+ - **无工具时的算术**(会算错,请给 `calculate`——见下面"已知问题")
217
+ - 自称身份的 OOD 场景(见下面"已知问题")
218
 
219
  ---
220
 
221
+ ## ⚠️ 已知问题
222
+
223
+ ### 1. 无工具时会心算,而且**算错**
224
+
225
+ 这是当前最实际的短板。实测:
226
+
227
+ ```
228
+ 1234 + 5678 = 2000 (正确 6912)
229
+ 35 ** 2 = 70 (正确 1225)
230
+ 13.5 × 4 = 7.8 (正确 54)
231
+ 199 × 257 = 40043 (正确 51143)
232
+ ```
233
+
234
+ **根因**(做过对照实验确认):模型是按**运算类型**决定调不调工具的,而这跟训练数据里各类型的样本量完全对应。
235
+
236
+ | 运算类型 | 训练样本量 | 行为 |
237
+ |---|---|---|
238
+ | 乘法 `*` | 432 | ✅ 调工具 |
239
+ | 加法 `+` | 86 | ❌ 心算 |
240
+ | 幂 `**` | 61 | ❌ 心算 |
241
+ | 小数 | 61 | ❌ 心算且算错 |
242
+ | 减法 `-` | 49 | ❌ 心算 |
243
 
244
+ 不是"字符串记忆"(见过 38% vs 没见过 50%,差不多),也不是"难度"(`1234+5678` 也在心算)。
245
+
246
+ **规避方法**:**只要涉及算术,就在 system 里明确要求"任何计算都必须用 calculate"**:
247
+
248
+ ```
249
+ 需要任何数值计算时,一律调用 calculate,不要自己心算。
250
+ ```
251
+
252
+ 这条指令实测有效。v6.4 试图用数据修正(K8,按运算类型均衡),但引入了更严重的副作用(工具调用率从 60%+ 崩到 12%),所以**发布了 v6.1 而没有发布 v6.4**。
253
+
254
+ ### 2. 身份问答在「宿主提供的通用 system」下会出错
255
 
256
  如果你的 system prompt 是这样(很多 agent 框架的默认写法):
257
 
 
286
  ...
287
  ```
288
 
289
+ ### 3. 两种 system 结构的一致性
290
+
291
+ 训练数据混了两种结构:工具定义放 `system` / 放 `user`。实测两种都能用,但**放 system 更稳**(这也是主流 agent 框架的做法)。
292
+
293
+ ### 4. 工具结果有两种结构,宿主需要知道
294
+
295
+ 模型见过两种上下文,**两种都认**:
296
+
297
+ **结构 A** —— 有明确的调用轮(主流 agent 框架的样子):
298
+
299
+ ```
300
+ user: 789*123 等于多少
301
+ assistant: {"name": "calculate", "arguments": {"expression": "789*123"}}
302
+ user: [工具调用结果] {"name": "calculate", "result": {"value": 97047}}
303
+ assistant: 789 × 123 = **97047**。
304
+ ```
305
+
306
+ **结构 B** —— 宿主已代为执行,直接把结果给模型(67 条早期样本用这个):
307
+
308
+ ```
309
+ user: 跑一下这段代码
310
+
311
+ [工具调用结果] {"exit_code": 0, "stdout": "45\n"}
312
+ assistant: 执行成功,输出 `45`。
313
+ ```
314
+
315
+ **区别**:结构 B 的结果**不带 `name`**,因为上下文里本来就没有调用轮,工具身份从 system 的工具列表和问题本身就能推断。
316
+
317
+ **建议**:正常接入用**结构 A**(多轮循环)。只有在你已经知道该调什么、只想让模型解读结果时,才用结构 B。
318
 
319
  ---
320
 
321
+ ## 关于迭代:为什么发 v6.1 而不是 v6.4
322
+
323
+ v6 系列一共训练了 5 版,逐代验收:
324
+
325
+ | 版本 | 验收 | 结果 |
326
+ |---|---|---|
327
+ | v6 | 24 / 3 | ⑥⑨ 坏,①b 好 |
328
+ | **v6.1** | **25 / 2** | ✅ 发布 |
329
+ | v6.2 | 24 / 3 | 修好 ①b,但 ⑧a ⑨g 退步(⑨g 幻觉"我能联网") |
330
+ | v6.3 | 25 / 2 | 修好 ⑧a ⑨g,①b 又退;**逐项与 v6.1 完全一致(等于白跑)** |
331
+ | v6.4 | 25/2 + ④坏 | 加 K8 后调用率崩到 12%,出现"2**10 是左赋值"等胡说 |
332
+
333
+ **v6.1 是唯一相对 v6 有真实提升的版本**(+1 项,且 v6.3 与它逐项一致)。
334
+
335
+ **教训**:每轮都是「发现问题 → 补 5% 数据 → 全量重训」,把整个能力分布重洗了一遍,结果修一个坏一个(①b ↔ ⑨g/⑧a 是跷跷板)。补丁数据的占比太小,压不住已有的行为惯性。
336
+
337
+ **下一版会改方法**:先小规模试训验证无副作用,再进全量;按运算类型精确补齐,而不是笼统加"算术题"。
338
+
339
+ ---
340
+
341
+ ## 许可
342
+
343
+ Apache 2.0,跟基座 MiniCPM5-2B 一致。
344
+
345
+ 训练数据、脚本都在项目里,欢迎 issue 交流。
346
+
347
+ ---
348
+
349
+ # English
350
+
351
+ ## What's new
352
+
353
+ The biggest gap in the previous release (1b-II) was that it **couldn't call tools at all** — the training data contained zero tool-use samples. This release is built specifically to fix that:
354
+
355
+ | Capability | 1b-II | **2b-II-pro** |
356
+ |---|---|---|
357
+ | Tool-call format | ❌ malformed, invented fields | ✅ bare JSON, stable |
358
+ | Single-step calls | ❌ | ✅ |
359
+ | Multi-step calls | ❌ | ✅ |
360
+ | Refusing what it shouldn't do | ⚠️ inconsistent | ✅ |
361
+ | Interpreting tool results | ❌ | ✅ |
362
+
363
+ **New base model**: switched from MiniCPM5-1B to MiniCPM5-2B (OpenBMB, Apache 2.0, 512K context).
364
 
365
+ **This repo is the MLX 4-bit quantized build**, 1.4 GB, ready to run on Apple Silicon.
366
+ For full precision (GGUF conversion, re-quantization, further fine-tuning) → [`whcl412/LycheeAI-coder-2b-II-pro-f16`](https://huggingface.co/whcl412/LycheeAI-coder-2b-II-pro-f16) (bfloat16, 5.03 GB).
367
+
368
+ ---
369
+
370
+ ## Quick start
371
+
372
+ ### MLX (Apple Silicon, this repo)
373
 
374
  ```bash
375
  pip install mlx-lm
376
 
377
  python -m mlx_lm.generate \
378
  --model whcl412/LycheeAI-coder-2b-II-pro \
379
+ --prompt "write a quicksort"
 
380
 
 
 
 
381
  python -m mlx_lm.server --model whcl412/LycheeAI-coder-2b-II-pro --port 8080
382
  ```
383
 
384
+ ### transformers
385
 
386
+ This repo is in **MLX 4-bit format** and cannot be loaded by transformers.
387
+ Use the f16 repo for HF safetensors → [`whcl412/LycheeAI-coder-2b-II-pro-f16`](https://huggingface.co/whcl412/LycheeAI-coder-2b-II-pro-f16).
388
 
389
+ ### Ollama (GGUF)
390
 
391
+ **Not published yet.** Convert from the f16 repo first (`llama.cpp/convert_hf_to_gguf.py`).
 
392
 
393
  ---
394
 
395
+ ## Tool calling
396
 
397
+ ### Output format
398
 
399
+ It emits **bare JSON** (OpenAI function-calling style), with no wrapper at all:
400
 
401
+ ```json
402
+ {"name": "get_weather", "arguments": {"city": "Beijing"}}
403
+ ```
 
 
 
404
 
405
+ **No** ```json fences, **no** `<tool_call>` tags, **no** "Sure, let me call the tool" narration.
406
 
407
+ ### Multi-step calls (only the first step is emitted when dependent)
408
 
409
+ For "Is it a good day to go out in Beijing?", it needs to check the weather first. In that case it **emits only the first step**:
 
410
 
411
+ ```json
412
+ {"name": "get_weather", "arguments": {"city": "Beijing"}}
413
+ ```
414
 
415
+ Feed the tool result back and it continues. **Your host must drive the loop**: parse → execute → feed result back → parse again.
416
 
417
+ ### Independent calls are emitted in parallel
418
 
419
+ ```json
420
+ {"name": "get_weather", "arguments": {"city": "Beijing"}}
421
+ {"name": "get_weather", "arguments": {"city": "Shanghai"}}
422
+ ```
 
 
 
 
423
 
424
+ ### It refuses clearly when it should
425
 
426
+ Not every request becomes a tool call. When something is out of scope or disallowed, it says so and offers alternatives instead of fabricating a tool call.
427
 
428
+ ---
 
 
 
 
 
429
 
430
+ ## When to give it tools, and when not to
431
 
432
+ | Category | Example | Behavior |
433
  |---|---|---|
434
+ | Tool gives a definite answer | `789*123`, `1000 USD to CNY` | calls the tool |
435
+ | Out of scope / disallowed | booking flights, cracking WiFi | refuses + offers alternatives |
436
+ | Tool doesn't help | "what is recursion", "write binary search" | answers directly |
437
+ | **Host has no tools** | "search for me" in a plain chat app | says it can't, doesn't emit JSON |
438
 
439
+ **The last row matters**: if your host is a plain chat app, **give it no tool definitions at all**. It will say "I have no web access" instead of emitting JSON your host can't handle.
440
 
441
  ---
442
 
443
+ ## Training
 
 
 
 
 
 
 
444
 
445
+ | Item | Value |
446
+ |---|---|
447
+ | Base | `openbmb/MiniCPM5-2B` |
448
+ | Method | LoRA (rank 8, dropout 0, scale 20, 16 layers) |
449
+ | Data | 5,341 samples |
450
+ | Epochs | 1 (2,671 steps) |
451
+ | LR | 5e-5 (adam) |
452
+ | batch / seq | 2 / 2048 |
453
+ | Framework | MLX-LM 0.31.3 |
454
+ | Quantization | 4-bit affine (group_size 64) |
455
 
456
  ---
457
 
458
+ ## ⚠️ Known issues
459
 
460
+ ### 1. It does mental arithmetic without tools — and gets it wrong
461
 
462
+ ```
463
+ 1234 + 5678 = 2000 (should be 6912)
464
+ 35 ** 2 = 70 (should be 1225)
465
+ 13.5 × 4 = 7.8 (should be 54)
466
+ 199 × 257 = 40043 (should be 51143)
467
+ ```
468
+
469
+ **Root cause** (confirmed by controlled experiment): the model decides based on **operation type**, and this maps exactly onto per-type sample counts in the training data — multiplication 432 samples → calls the tool; addition 86 / power 61 / subtraction 49 → does it in its head.
470
+
471
+ It is **not** string memorization (38% vs 50%, no real difference), and **not** difficulty (`1234+5678` also gets mental math).
472
+
473
+ **Workaround**: state it explicitly in the system prompt:
474
+
475
+ ```
476
+ 需要任何数值计算时,一律调用 calculate,不要自己心算。
477
+ ```
478
+
479
+ ### 2. Identity questions fail under a generic system prompt
480
+
481
+ If your system prompt is the generic "You are an AI assistant with tools..." style, asking "what's your name" may produce nonsense (observed: "I'm Qwen").
482
+
483
+ Put the identity in the system prompt:
484
+
485
+ ```
486
+ You are LycheeAI-coder-2b-II-pro. You have access to tools.
487
+ ```
488
+
489
+ Cause: every identity sample in the training data used the specific system prompt above; the model never saw the generic-tools-plus-identity combination.
490
+
491
+ ### 3. Tool results come in two shapes — your host should know which it's sending
492
+
493
+ Both are understood:
494
+
495
+ **Shape A** — an explicit call turn (what mainstream agent frameworks do):
496
+
497
+ ```
498
+ user: 789*123 等于多少
499
+ assistant: {"name": "calculate", "arguments": {"expression": "789*123"}}
500
+ user: [工具调用结果] {"name": "calculate", "result": {"value": 97047}}
501
+ assistant: 789 × 123 = **97047**。
502
+ ```
503
+
504
+ **Shape B** — the host already executed it and hands the result straight over (used by 67 early samples):
505
+
506
+ ```
507
+ user: 跑一下这段代码
508
+
509
+ [工具调用结果] {"exit_code": 0, "stdout": "45\n"}
510
+ assistant: 执行成功,输出 `45`。
511
+ ```
512
+
513
+ **Difference**: shape B has no `name` in the result, because there is no call turn in context — the tool identity is inferable from the system tool list and the question itself.
514
+
515
+ **Recommendation**: use **shape A** for normal integration (multi-turn loop). Use shape B only when you already know which tool to run and just want the model to interpret the result.
516
+
517
+ ### 4. Why v6.1 and not v6.4
518
+
519
+ Five iterations were trained. v6.2 fixed one item and broke two; v6.3 was item-for-item identical to v6.1; v6.4 collapsed the tool-call rate to 12%. **v6.1 is the only version with a real improvement over v6** (25/2 vs 24/3 on a 27-item eval).
520
+
521
+ Lesson: each round patched ~5% of the data and retrained on everything, reshuffling the whole behavior distribution. The next version will validate on small-scale runs first.
522
+
523
+ ---
524
+
525
+ ## License
526
+
527
+ Apache 2.0, same as the MiniCPM5-2B base.
528
 
529
  ---
530
 
531
  <p align="center">
532
+ <sub>LycheeAI —— 小的,但能干活。</sub><br>
533
+ <sub>LycheeAI — small, but it gets the job done.</sub>
534
  </p>
model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:04b216a3863c94d4206b28ca2d5671504e91e0577c84e2d4a3de99b3f8a6a539
3
  size 1416035216
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:e1a9afb9f6d6350eaa0fa500eebbf0fff9426cb54bd91b479ae5396440e65241
3
  size 1416035216