Text Generation
MLX
Safetensors
llama
code
minicpm
chinese
conversational
tool-calling
quantization
4-bit precision
Instructions to use whcl412/LycheeAI-coder-2b-II-pro with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- MLX
How to use whcl412/LycheeAI-coder-2b-II-pro with MLX:
# Make sure mlx-lm is installed # pip install --upgrade mlx-lm # Generate text with mlx-lm from mlx_lm import load, generate model, tokenizer = load("whcl412/LycheeAI-coder-2b-II-pro") prompt = "Write a story about Einstein" messages = [{"role": "user", "content": prompt}] prompt = tokenizer.apply_chat_template( messages, add_generation_prompt=True ) text = generate(model, tokenizer, prompt=prompt, verbose=True) - Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- LM Studio
- Pi
How to use whcl412/LycheeAI-coder-2b-II-pro with Pi:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "whcl412/LycheeAI-coder-2b-II-pro"
Configure the model in Pi
# Install Pi: npm install -g @earendil-works/pi-coding-agent # Add to ~/.pi/agent/models.json: { "providers": { "mlx-lm": { "baseUrl": "http://localhost:8080/v1", "api": "openai-completions", "apiKey": "none", "models": [ { "id": "whcl412/LycheeAI-coder-2b-II-pro" } ] } } }Run Pi
# Start Pi in your project directory: pi
- MLX LM
How to use whcl412/LycheeAI-coder-2b-II-pro with MLX LM:
Generate or start a chat session
# Install MLX LM uv tool install mlx-lm # Interactive chat REPL mlx_lm.chat --model "whcl412/LycheeAI-coder-2b-II-pro"
Run an OpenAI-compatible server
# Install MLX LM uv tool install mlx-lm # Start the server mlx_lm.server --model "whcl412/LycheeAI-coder-2b-II-pro" # Calling the OpenAI-compatible server with curl curl -X POST "http://localhost:8000/v1/chat/completions" \ -H "Content-Type: application/json" \ --data '{ "model": "whcl412/LycheeAI-coder-2b-II-pro", "messages": [ {"role": "user", "content": "Hello"} ] }' - Hermes Agent
How to use whcl412/LycheeAI-coder-2b-II-pro with Hermes Agent:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "whcl412/LycheeAI-coder-2b-II-pro"
Configure Hermes
# Install Hermes: curl -fsSL https://hermes-agent.nousresearch.com/install.sh | bash hermes setup # Point Hermes at the local server: hermes config set model.provider custom hermes config set model.base_url http://127.0.0.1:8080/v1 hermes config set model.default whcl412/LycheeAI-coder-2b-II-pro
Run Hermes
hermes
- Atomic Chat
- OpenClaw
How to use whcl412/LycheeAI-coder-2b-II-pro with OpenClaw:
Start the MLX server
# Install MLX LM: uv tool install mlx-lm # Start a local OpenAI-compatible server: mlx_lm.server --model "whcl412/LycheeAI-coder-2b-II-pro"
Configure OpenClaw
# Install OpenClaw: npm install -g openclaw@latest # Register the local server and set it as the default model: openclaw onboard --non-interactive --mode local \ --auth-choice custom-api-key \ --custom-base-url http://127.0.0.1:8080/v1 \ --custom-model-id "whcl412/LycheeAI-coder-2b-II-pro" \ --custom-provider-id mlx-lm \ --custom-compatibility openai \ --custom-text-input \ --accept-risk \ --skip-health
Run OpenClaw
openclaw agent --local --agent main --message "Hello from Hugging Face"
LycheeAI-coder-2b-II-pro v6.1 (MLX 4bit)
Browse files- README.md +372 -93
- 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 |
-
|
| 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 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 96 |
|
| 97 |
---
|
| 98 |
|
| 99 |
-
## ⚠️ 已知问题
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 100 |
|
| 101 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 102 |
|
| 103 |
如果你的 system prompt 是这样(很多 agent 框架的默认写法):
|
| 104 |
|
|
@@ -133,123 +286,249 @@ base_model: openbmb/MiniCPM5-2B
|
|
| 133 |
...
|
| 134 |
```
|
| 135 |
|
| 136 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 137 |
|
| 138 |
---
|
| 139 |
|
| 140 |
-
##
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 141 |
|
| 142 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
-
###
|
| 159 |
|
| 160 |
-
**
|
| 161 |
-
|
| 162 |
|
| 163 |
-
###
|
| 164 |
|
| 165 |
-
|
| 166 |
-
如果需要 HF safetensors 版本,请从 `MiniCPM5-2B` 基座自行转换,或提 issue。
|
| 167 |
|
| 168 |
---
|
| 169 |
|
| 170 |
-
##
|
| 171 |
|
| 172 |
-
###
|
| 173 |
|
| 174 |
-
**
|
| 175 |
|
| 176 |
-
|
| 177 |
-
|
| 178 |
-
|
| 179 |
-
| Anthropic / Claude Tools | XML 标签 `<function_calls><invoke name="...">` |
|
| 180 |
-
| 部分国产模型 | `<tool_call>` 自定义标签包 JSON |
|
| 181 |
-
| MCP | 传输层协议,内部通常还是 JSON-RPC |
|
| 182 |
|
| 183 |
-
**
|
| 184 |
|
| 185 |
-
###
|
| 186 |
|
| 187 |
-
|
| 188 |
-
- **依赖调用**(先查天气,再根据结果决定要不要提醒带伞)→ 它只输出第一个,等结果回来再继续
|
| 189 |
|
| 190 |
-
|
|
|
|
|
|
|
| 191 |
|
| 192 |
-
|
| 193 |
|
| 194 |
-
##
|
| 195 |
|
| 196 |
-
|
| 197 |
-
|
| 198 |
-
|
| 199 |
-
|
| 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 |
-
|
|
| 221 |
-
|
|
| 222 |
-
|
|
|
|
|
| 223 |
|
| 224 |
-
|
| 225 |
|
| 226 |
---
|
| 227 |
|
| 228 |
-
##
|
| 229 |
-
|
| 230 |
-
**能做:**
|
| 231 |
-
- 写代码、调 bug、解释技术概念
|
| 232 |
-
- 单步 / 多步工具调用(裸 JSON)
|
| 233 |
-
- 拒绝能力范围外或不合规的请求
|
| 234 |
-
- 解读工具返回结果
|
| 235 |
-
- 中文 / 英文 / 粤语
|
| 236 |
|
| 237 |
-
|
| 238 |
-
-
|
| 239 |
-
|
| 240 |
-
|
| 241 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 242 |
|
| 243 |
---
|
| 244 |
|
| 245 |
-
##
|
| 246 |
|
| 247 |
-
|
| 248 |
|
| 249 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 250 |
|
| 251 |
---
|
| 252 |
|
| 253 |
<p align="center">
|
| 254 |
-
<sub>LycheeAI
|
|
|
|
| 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:
|
| 3 |
size 1416035216
|
|
|
|
| 1 |
version https://git-lfs.github.com/spec/v1
|
| 2 |
+
oid sha256:e1a9afb9f6d6350eaa0fa500eebbf0fff9426cb54bd91b479ae5396440e65241
|
| 3 |
size 1416035216
|