---
license: gpl-3.0
language:
- zh
- en
base_model:
- unsloth/Qwen2.5-3B-Instruct-unsloth-bnb-4bit
pipeline_tag: text-generation
tags:
- not-for-all-audiences
- text-generation-inference
- transformers
- unsloth
- qwen2
- gguf
---

一个更好的实现，试试这个：DeepSeek-V3.2-asks-the-user-questions-while-they-are-thinking

https://modelscope.cn/studios/likewendy/DeepSeek-V3.2-asks-the-user-questions-while-they-are-thinking/summary

显然，ds也开始实现在思考中调用工具了。

# Qwen2.5-3B-YiLin-GGUF-q4_k_m

## 概述

该模型基于 Qwen2.5-3B-Instruct 的动态4位量化，使用 QLoRA 在两个开源数据集一个合成数据集上训练了 3 epochs，最大上下文长度为 8192。

成功的将类似于 DeepSeek-r1 的思维链迁移到 Qwen2.5-3B-Instruct ，并且实现了 **“使用系统提示控制思维链”** 使模型可以**更灵活的产生思维链**并**在思考的过程中与外界交互调用工具**，从而实现模型自身 **“具身智能”**。

该特性旨在解决：**模型在输出思考过程的时候，遇到需要查询资料或者用户补充问题时，无法与外界交互，从而导致推理性能得不到释放的问题。**

>作者认为，该特性应用前景巨大，配合 MCP 可以完全摆脱传统 Agent 以多轮对话的形式调用工具的不足，将工具调用搬到思维链中来，借助思维链提高工具使用的水平和效益，更好的利用起现实世界中的各种工具。

合成数据集使用该仓库 [yilin-chatgpt-prompts](https://github.com/youyi0218/yilin-chatgpt-prompts) 的提示词通过自动化数据合成管道，合成了 2000 余篇意林风格的文章。

<!-- 两个开源数据集一个私有数据集上训练了 5 epochs，最大上下文长度为 8192。

成功的将类似于 DeepSeek-r1 的思维链迁移到 Qwen2.5-3B-Instruct ，并且实现了 “选择性人类对齐” 使模型在原始人类对齐的基础上，针对特定领域的问题进行豁免，减少了在特定领域上的拒绝回复，增强了模型的适应性、安全性。

还重塑了类似于 DeepSeek-r1 的思维链，使思维链更紧凑，消除了多于的语气词，对于基于云的API调用来说，降低了tokens消耗。 -->

## 权重

提供合并到 Qwen2.5-3B-Instruct 的16位 .safetensors 文件，和 GGUF 格式的 BF16、Q4_K_M 文件以方便 ollama 部署。

## 预期用途

研究 “使用系统提示控制思维链” 的可行性与效益。

作为一个吃螃蟹的模型，它旨在抛出一个引子，引导人们继续相关研究，从而推进 LLM 在 AGI 道路上的进程。

<!-- 用于 Pron 文本检测模型，对抗数据集生成。 -->

## 滥用

几乎可以用模型做任何事情，它拥有良好的人类对齐，符合普遍价值观。并且善于编写文笔具有艺术性的文章。

<!-- 不可以用于 角色扮演、Pron小说生成。 -->

## 快速开始

### 推理

1. 你可以使用 ollama 部署，尽可能的使用 16 位 GGUF 文件，除非你的硬件难以运行它，那么，你可以使用 Q4_K_M ，如果你使用 Q4_K_M 一个好的技巧是，请尝试使用类似于这样的 user prompt ：

```
这里是你的提示词\n<think>
```

2. VLLM

你可以直接使用 vllm 运行此模型，只需传入 likewendy/Qwen2.5-3B-YiLin-GGUF-q4_k_m 。

3. 使用代码，常规推理

```python
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
  model_name="likewendy/Qwen2.5-3B-YiLin-GGUF-q4_k_m",
  max_seq_length=8192,
  dtype=None,
  load_in_4bit=Flase,
)

from unsloth.chat_templates import get_chat_template

# 获取 Qwen-2.5 的聊天模板，并应用到分词器
tokenizer = get_chat_template(
  tokenizer,
  chat_template="qwen-2.5",
)

FastLanguageModel.for_inference(model)  # 启用原生 2 倍速推理

# 定义消息列表，包含用户角色和内容
messages = [
    {"role": "system", "content": "如果需要搜索网页，你需要在</think>标签之前，输出这样格式的文本来调用工具搜索网页：{'search':'此处为需要搜索的关键词'}"},
    {"role": "user", "content": "给我邓文怡的最新歌曲"},
]

inputs = tokenizer.apply_chat_template(
    messages,
    tokenize=True,
    add_generation_prompt=True,
    return_tensors="pt",
).to("cuda")

from transformers import TextStreamer
text_streamer = TextStreamer(tokenizer, skip_prompt=True)
# 使用模型生成输出
_ = model.generate(
    input_ids=inputs,
    streamer=text_streamer,
    max_new_tokens=8192,
    use_cache=True,
    temperature=0.7,
    top_p=0.7,
)
```

4. 使用代码，**通过 “使用系统提示控制思维链” 实现让用户补充问题的完整demo**

```python
from unsloth import FastLanguageModel

model, tokenizer = FastLanguageModel.from_pretrained(
  model_name="likewendy/Qwen2.5-3B-YiLin-GGUF-q4_k_m",
  max_seq_length=8192,
  dtype=None,
  load_in_4bit=Flase,
)

from unsloth.chat_templates import get_chat_template

# 获取 Qwen-2.5 的聊天模板，并应用到分词器
tokenizer = get_chat_template(
  tokenizer,
  chat_template="qwen-2.5",
)

FastLanguageModel.for_inference(model)  # 启用原生 2 倍速推理

import json
from transformers import TextStreamer, StoppingCriteria, StoppingCriteriaList

should_stop_ok = False

class CustomStreamer(TextStreamer):
    def __init__(self, tokenizer, **kwargs):
        super().__init__(tokenizer, **kwargs)
        self.should_stop = False
        self.issue_content = None
        self.buffer = ""
        self.output_text = ""

    def put(self, value):
        # 实时输出到控制台（父类方法）
        # 如果您只想解码新增的最后一个 token，也可以只 decode 最后一个
        super().put(value)
        
        # 如果 value 是张量，先把它移到 CPU 并转换成列表
        # 如果已经是列表，可以根据实际情况判断是否需要做类似的操作
        if hasattr(value, "cpu"):
            value = value.cpu()
        if hasattr(value, "numpy"):
            value = value.numpy().tolist()
        elif hasattr(value, "tolist"):
            value = value.tolist()
    
        # 如果是批量大小=1，则取出第一行
        # 这里假设传入的 value 是二维 [batch_size, sequence_length] 结构
        # 如果 batch_size 不是 1，需酌情修改
        if isinstance(value[0], list):
            value = value[0]
    
        # 现在 value 应该是一维的 token 列表
        last_token = value[-1:]
        text_chunk = self.tokenizer.decode(last_token, skip_special_tokens=True)
        self.buffer += text_chunk
    
        # 分割处理完整行
        while '\n' in self.buffer:
            newline_pos = self.buffer.find('\n')
            line = self.buffer[:newline_pos]
            self.buffer = self.buffer[newline_pos+1:]
            self._process_line(line)

    def _process_line(self, line):
        self.output_text += line + '\n'  # 记录完整输出
        
        # 检测是否包含停止条件
        line = line.strip()
        if line.startswith("{'issue_add':") or line.startswith('{"issue_add":'):
            try:
                # 处理单引号并解析JSON
                json_str = line.replace("'", '"')
                data = json.loads(json_str)
                if 'issue_add' in data and not should_stop_ok:
                    self.should_stop = True
                    self.issue_content = data['issue_add']
            except json.JSONDecodeError:
                pass

    def end(self):
        # 处理剩余缓冲区内容
        if self.buffer:
            self._process_line(self.buffer)
            self.buffer = ""
        super().end()

class StopCondition(StoppingCriteria):
    def __init__(self, streamer):
        super().__init__()
        self.streamer = streamer

    def __call__(self, input_ids, scores, **kwargs):
        return self.streamer.should_stop

# 定义消息列表，包含用户角色和内容
messages = [
    {"role": "system", "content": "如果需要让用户补充更多信息，你需要在</think>标签之前，输出这种格式的文本来调用工具，以实现让用户补充更多信息，格式是：{'issue_add':'这里你需要告诉用户缺少什么信息'}"},
    {"role": "user", "content": "我买了点散装称重的零食，花了100块钱，每袋多少钱？"},
]

while True:
    # 准备模型输入
    inputs = tokenizer.apply_chat_template(
        messages,
        tokenize=True,
        add_generation_prompt=True if not should_stop_ok else False,
        return_tensors="pt"
    ).to("cuda")

    # 创建流式处理器和停止条件
    streamer = CustomStreamer(tokenizer, skip_prompt=True)
    stop_condition = StopCondition(streamer)

    if should_stop_ok:
        inputs_str = tokenizer.decode(inputs[0], skip_special_tokens=False)
        # delete <|im_end|>
        inputs_str = inputs_str[:-11]
        # print(inputs_str)
        import torch
        inputs = torch.tensor([tokenizer.encode(inputs_str,add_special_tokens=False)], dtype=torch.long, device='cuda')
    
    # 执行生成（带停止条件）
    model.generate(
        input_ids=inputs,
        streamer=streamer,
        max_new_tokens=8192,
        use_cache=True,
        temperature=0.7,
        top_p=0.7,
        stopping_criteria=StoppingCriteriaList([stop_condition]),
    )

    # 将模型输出添加到对话历史
    if streamer.output_text.strip():
        messages.append({"role": "assistant", "content": streamer.output_text.strip()})

    # 检测停止条件
    if streamer.should_stop:
        print(f"\n---\n检测到issue_add内容: {streamer.issue_content}")
        user_input = input("请输入您的回复: ")
        print("---\n")

        should_stop_ok = True
        
        # 将用户拼接到assistant消息
        messages[len(messages)-1]['content'] += f"\n工具调用结果：{user_input}\n我已经得到了工具的调用结果：“{user_input}”，下面我需要根据工具调用结果继续推理。\n首先，"
        # print(messages)
    else:
        break  # 正常结束生成
```
上述代码的终端输出：
```
<think>
我现在得解决这个问题。题目说，我买了一些散装称重的零食，总共花了100块钱，但是不知道每袋的价格是多少。那应该怎么做呢？

首先，我得仔细看看问题。题目里提到的是“散装称重”的零食，也就是可能是一些大包装的东西，比如一包饼干、一盒巧克力或者某种混合坚果，这些都是没有明确标价的，所以每袋的价格可能不同。不过题目中并没有给出具体的种类和数量，只是总价100块钱。

那可能的问题在于，题目中的“散装”是否意味着每袋价格不同？比如说，有的袋子可能更贵一些，而有的便宜一些，这样的话，总金额100元的话，可能无法平均分配到每个袋子上。这时候可能需要更多的信息来确定每袋的价格，比如有多少种不同的袋子，每种的数量等等。

不过题目里并没有提供这些额外的信息。那可能题目本身存在假设或隐含条件，比如是否存在折扣或者优惠活动，但题目里没有提到这些情况。或者可能是题目设计时忽略了这些细节，导致无法直接计算出每袋的价格。

那么，按照常规的处理方法，如果每袋的价格不同，且总金额为100元，可能需要知道具体每种袋子的数量，才能计算出每袋的价格。例如，如果有5种不同大小的袋子，每种的数量分别是2、3、4、5、6个，那么总共有5×(2+3+4+5+6)=55个袋子，总重量是2+3+4+5+6=20公斤，每公斤的价格就是100/20=5元。这样每袋的价格应该是5元除以对应的数量，比如第一种袋子可能每袋5元，第二种可能8元，第三种10元，以此类推。但题目里并没有给出具体的数据，所以无法准确计算。

或者题目可能假设所有袋子的价格相同，或者总共有几种不同的袋子，但数量未知。比如，如果有三种袋子，分别是A、B、C，每袋的价格分别为a元、b元、c元，总数量为n袋，那么总费用就是a*n+a*b+n*c=100元。但同样，题目里没有给出a、b、c的具体数值，也没有n的值，所以无法解出答案。

另外，可能题目中存在其他隐藏条件，比如是否有优惠券、打折等情况，但题目里没有提及，所以只能按照最简单的处理方式，即假定每袋价格相同，或者有不同价格的情况，但题目里没有说明。因此，根据题目给定的信息，无法得出准确的答案。

总结一下，由于题目没有提供足够的信息，比如每袋的价格类型、数量等，所以无法确定每袋的具体价格。可能需要更多数据才能解答。所以，正确的回答应该是：“无法确定，因为缺少必要的信息。” 或者更简洁地说，“需要更多信息。” 这样既符合逻辑，又尊重题目提供的有限信息。
{"issue_add":"缺少每袋的价格类型和数量"}<|im_end|>

---
检测到issue_add内容: 缺少每袋的价格类型和数量
请输入您的回复:  20袋
---

我需要确认这个结果是否合理。散装零食通常会有多种规格，比如小袋、中袋、大袋等，每种规格的价格不同。假设每袋的价格都是整数，那么总金额100元的情况下，每袋的价格应该是100除以袋数的结果。如果袋数是20，那么每袋的价格就是5元。但实际散装零食的袋数可能不是20，而是其他数字，比如10袋、25袋、50袋等等。我们需要验证这个结果是否符合实际情况。

接下来，考虑散装零食的常见规格和价格分布。例如，常见的零食袋装价格可能如下：
- 小袋（如50克）：5元左右
- 中袋（如100克）：10元左右
- 大袋（如200克）：15元左右

假设每袋的价格分布在这个范围内，我们可以尝试将100元分成几个部分。例如，如果每袋都是5元，那么需要20袋；如果是10元，需要10袋；如果是15元，需要6.67袋，这显然不合理。因此，每袋的价格应该是介于5元和10元之间，且总和为100元。

现在，假设每袋的价格是5元，那么需要多少袋才能凑成100元？计算如下：
100 ÷ 5 = 20 袋
所以，如果每袋价格是5元，需要20袋。这个结果与工具给出的结果一致，因此是合理的。

结论：每袋的价格是5元，共购买了20袋。<|im_end|>
```









### 技巧

<!-- 1. 建议将 system prompt 设为空字符串，这样设置往往比不这样设置效果要好。 -->
1. 建议的参数 temperature=0.7 top_p=0.7

### 例子

1. 通过 “使用系统提示控制思维链” 实现搜索网页

**系统提示词：**
```
如果需要搜索网页，你需要在</think>标签之前，输出这样格式的文本来调用工具搜索网页：{'search':'此处为需要搜索的关键词'}
```

**用户提示词：**
```
给我邓文怡的最新歌曲
```

**模型回复：**
```
<think>
用户让我提供邓文怡的最新歌曲。首先，我需要确认邓文怡是谁，可能是一个歌手的名字。然后，我应该回想一下她最近有什么新歌发布。邓文怡是中国台湾的女歌手，她的音乐风格可能是流行或者电子舞曲？

接下来，我需要检查最近是否有她的新专辑或单曲发布。我记得她曾经和林俊杰合作过《不分手》，但不知道有没有其他作品。另外，她也参与过一些合辑，比如《超级星光大道》之类的选秀节目吗？不过用户可能更想听她的原创作品。

根据我的知识库，邓文怡最近的一首比较热门的单曲是《爱在月光下》，这是一首电子舞曲风格的歌曲，通常用于舞蹈场合。另外，她还有一首《你是我最爱的人》，这首歌听起来像是抒情风格，可能适合晚间的温柔氛围。不过这些信息可能需要进一步验证。

然后，我需要考虑用户的潜在需求。他们可能是在寻找邓文怡的新歌来播放，或者准备演唱会、活动等场合。如果是演唱会的话，可能需要推荐她的主打曲目，而如果只是日常听歌，可能需要更多选择。

还要注意版权问题，确保提供的链接是合法的，并且没有侵犯任何版权。所以最好直接给出歌词和歌曲名称，或者提供下载链接，但要注意不要提供非法内容。

最后，我应该组织这些信息，分点列出最新的几首歌曲，并简要说明类型和风格，让用户可以根据自己的喜好选择。同时提醒用户可能需要通过官方渠道获取最新信息，因为歌手可能会有新的动态。
{'search':'邓文怡 最新 歌曲'}
</think>
邓文怡（Yumi）是中国台湾的知名女歌手，以电子舞曲和流行音乐为主打风格。以下是她近期的热门单曲及最新作品：

---

### **1. 《爱在月光下》**
- **类型**：电子舞曲  
- **特点**：节奏强烈、动感十足，常作为派对或健身音乐使用。  
- **推荐场景**：夜店、健身房、户外活动。  

---

### **2. 《你是我最爱的人》**
- **类型**：抒情流行  
- **特点**：旋律温暖，歌词表达深情与思念，适合夜晚安静聆听。  
- **推荐场景**：浪漫约会、电影配乐。  

---

### **3. 《不分手》**
- **类型**：轻快舞曲  
- **特点**：与林俊杰合作的经典作品，旋律朗朗上口，常用于社交场合。  
- **推荐场景**：聚会、KTV、广告背景音乐。  

---

### **4. 《心跳》**
- **类型**：流行电子  
- **特点**：节奏感强，歌词描述心动时刻，适合恋爱主题MV或广告。  

---

### **5. 《逆光飞翔》**
- **类型**：励志流行  
- **特点**：鼓励积极向上的歌词，适合正能量场合。  

---

### **如何获取最新歌曲？**
1. **官方平台**：访问邓文怡的微博、抖音或YouTube频道，关注最新动态。  
2. **数字音乐平台**：如Spotify、Apple Music、YouTube Music等，搜索歌曲名称即可找到完整版。  
3. **实体发行**：部分单曲可通过线上商城购买实体CD或下载。  

---

如果你需要具体的歌词或下载链接，请告诉我！<|im_end|>
```

2. 通过 “使用系统提示控制思维链” 实现让用户补充问题

**系统提示词：**
```
如果需要让用户补充更多信息，你需要在</think>标签之前，输出这种格式的文本来调用工具，以实现让用户补充更多信息，格式是：{'issue_add':'这里你需要告诉用户缺少什么信息'}
```

**用户提示词：**
```
我买了点散装称重的零食，花了100块钱，每袋多少钱？
```

**模型回复：**
```
<think>
我现在要解决这个问题。题目说，我买了一些散装称重的零食，总共花费了100块钱。每个袋子的价格不同，所以我想知道每袋多少钱。不过问题好像有点不太对头，因为散装零食通常都是按重量收费的，而不是按袋子来卖的。比如，可能是一箱一箱的，每个袋子里面装的是不同重量的零食。

那问题中的“每袋多少钱”应该是指每个袋子里面的单价，对吧？但这里的问题似乎把重量和袋子的数量混在一起了。比如说，假设我买了5袋零食，每袋20元的话，那么总费用就是5×20=100元，刚好符合题目的条件。这样的话，每个袋子就是20元？

或者有没有可能是题目中的“散装称重”的零食，指的是按照不同的重量来计价的呢？比如，每袋里有不同的重量，而价格也是根据重量来计算的。这样的话，每个袋子里的重量可能不同，所以单价也不一样。比如，第一个袋子可能有1斤，第二个袋子可能有2斤，这样总价就是1+2=3斤，每斤的价格就是100/3≈33.33元。这样的话，每个袋子的单价应该是不同的。

但是题目中并没有说明每个袋子的具体重量是多少，只是说每袋的钱数。这时候应该怎么处理呢？可能题目中的“每袋多少钱”指的是每个袋子的单价，而这个单价可能根据袋子的大小或重量来决定。比如，可能每个袋子的价格是固定的，不管里面有多少重量。这样的话，每个袋子的单价就是100元除以袋子的数量。比如，如果买了5袋，每个袋子就是100/5=20元。这和前面的例子一致。

不过题目中没有明确说明是否每个袋子的价格固定，还是根据重量来计算。如果是后者的话，可能每个袋子的价格不同，所以不能直接算出每个袋子的单价。例如，如果第一个袋子是1斤，第二个袋子是2斤，第三个袋子是3斤，那么总价就是6斤，平均每个袋子的价格就是60元，每个袋子的单价是60/3=20元。这时候每个袋子的单价应该是相同的，等于总价除以袋子数量。

不过题目中的问题看起来更复杂，可能需要更多的信息才能确定每个袋子的单价。比如，题目中可能提到每个袋子的重量不同，或者每个袋子的价格不同。这时候可能需要进一步的信息，比如每个袋子的重量分别是多少，或者每个袋子的价格分别是多少。如果没有这些信息，可能无法准确回答问题。

所以，根据当前给出的信息，可能有两种情况：

1. 如果每个袋子的价格是固定的，比如每个袋子都是20元的话，那么每个袋子就是20元。
2. 如果每个袋子的价格不同，比如第一个袋子是1斤，第二个是2斤，第三个是3斤，那么总价是6斤，每个袋子的单价就是60元，每个袋子的单价是20元。

但题目中并没有提供足够的信息来确定每个袋子的具体重量和价格。因此，可能需要更多的细节才能解答这个问题。比如，题目中是否有提到每个袋子的重量和对应的单价，或者是否有其他相关信息？

假设题目中的每个袋子的价格是固定的，比如每个袋子都是20元的话，那么答案就是每个袋子20元。但如果每个袋子的价格不同，就需要更多数据才能计算每个袋子的单价。在这种情况下，可能需要用户提供更多信息来确定每个袋子的单价。
{'issue_add':'这里你需要告诉我每个袋子的重量以及它们各自的单价'}
散装零食通常按重量计费，但题目描述的“每袋多少钱”可能存在歧义。需先确认以下关键信息：

1. **散装零食的包装单位**：是否为独立包装（如小袋）或统一容器（如大桶）？
   - 若为独立包装，需了解每袋的重量或容量。
   - 若为统一容器，需了解其总重量及包含袋数。

2. **定价方式**：
   - 是否存在不同单价的袋子？例如，部分袋装零食标价为20元/袋，而另一些为30元/袋。
   - 是否有固定单价的包装（如每袋20元），还是按重量分档收费？

若缺乏具体数据，无法直接计算。例如：
- 假设每个袋子均为20元/袋，则100元可购买5袋。
- 若存在不同单价，需列出所有选项进行组合验证。

建议补充以下信息：
- 每个袋子的重量（如1斤、2斤等）。
- 具体定价方案（如20元/袋、30元/袋等）。
- 总共购买了多少个袋子（或总重量）。

根据现有信息，无法准确计算单价，需提供更详细数据。<|im_end|>
```

3. 通过 “使用系统提示控制思维链” 实现让用户补充问题，在界面实现中可能的样子

![image/png](https://cdn-uploads.huggingface.co/production/uploads/66719e03a4dd9ce916a82688/azssO7njGWkSfi-blC5Ef.png)