Qwen2.5 3B YiLin GGUF Q4 K M
モデル概要
モデル特徴
モデル能力
使用事例
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
Qwen2.5-3B-YiLin-GGUF-q4_k_m
概要
このモデルはQwen2.5-3B-Instructの動的4ビット量子化に基づいており、QLoRAを使用して2つのオープンデータセットと1つの合成データセットで3エポック訓練され、最大コンテキスト長は8192です。
DeepSeek-r1のような思考連鎖をQwen2.5-3B-Instructに移植することに成功し、「システムプロンプトによる思考連鎖の制御」を実現することで、モデルがより柔軟に思考連鎖を生成し、思考過程で外部ツールと対話的に連携できるようにしました。これにより、モデル自身の**「具現化された知能」**を実現しています。
この特性は、モデルが思考過程を出力する際に、情報検索やユーザーからの追加質問が必要な場合に外部と対話できず、推論性能が十分に発揮できない問題を解決することを目的としています。
著者は、この特性の応用可能性が非常に大きく、MCPと組み合わせることで、従来のエージェントが複数回の対話形式でツールを呼び出すという欠点を完全に克服し、ツール呼び出しを思考連鎖内に移動させ、思考連鎖を活用してツール使用のレベルと効果を高め、現実世界のさまざまなツールをより効果的に利用できると考えています。
合成データセットは、yilin-chatgpt-promptsリポジトリのプロンプトを使用して自動化データ合成パイプラインにより、2000以上の意林スタイルの記事を生成しました。
重み
Qwen2.5-3B-Instructにマージされた16ビットの.safetensorsファイルと、ollama展開用のGGUF形式のBF16、Q4_K_Mファイルを提供しています。
想定用途
「システムプロンプトによる思考連鎖の制御」の実現可能性と効果に関する研究。
先駆け的なモデルとして、関連研究を導き、LLMのAGIへの道のりを推進することを目的としています。
悪用
ほぼ何にでも使用できます。良好な人間との整合性を持ち、普遍的価値観に適合しています。また、芸術的な文章を書くことに長けています。
クイックスタート
推論
- ollamaを使用して展開できます。可能な限り16ビットGGUFファイルを使用してください。ハードウェアがそれを実行できない場合は、Q4_K_Mを使用できます。Q4_K_Mを使用する場合の良いテクニックは、次のようなユーザープロンプトを使用することです:
ここにあなたのプロンプト\n<think>
- VLLM
vllmを使用してこのモデルを直接実行できます。likewendy/Qwen2.5-3B-YiLin-GGUF-q4_k_mを渡すだけです。
- コードを使用した通常の推論
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,
)
- コードを使用した**「システムプロンプトによる思考連鎖の制御」を実現し、ユーザーに問題を補足させる完全なデモ**
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):
# コンソールにリアルタイムで出力(親クラスメソッド)
# 最後に追加されたトークンのみをデコードすることも可能
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は一次元のトークンリストであるはず
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元払いました。1袋いくらですか?"},
]
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)
# <|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---\nissue_add内容を検出: {streamer.issue_content}")
user_input = input("あなたの返答を入力してください: ")
print("---\n")
should_stop_ok = True
# ユーザー入力をアシスタントメッセージに連結
messages[len(messages)-1]['content'] += f"\nツール呼び出し結果:{user_input}\nツール呼び出し結果「{user_input}」を得ました。以下、ツール呼び出し結果に基づいて推論を続けます。\nまず、"
# print(messages)
else:
break # 正常に生成終了
上記コードのターミナル出力:
<think>
この問題を解決する必要があります。問題によると、量り売りのお菓子を買って合計100元支払いましたが、1袋あたりの価格がわかりません。どうすればよいでしょうか?
まず、問題をよく見てみましょう。問題には「量り売り」のお菓子とありますが、これは明確な価格表示がない大容量包装のもの、例えばビスケットの袋、チョコレートの箱、または混合ナッツなどで、価格が異なる可能性があります。しかし、問題には具体的な種類や数量が記載されておらず、総額が100元とだけあります。
では、問題の「量り売り」は各袋の価格が異なることを意味するのでしょうか?例えば、一部の袋は高価で、他の袋は安価で、合計金額が100元の場合、各袋に均等に分配できないかもしれません。この場合、各袋の種類や数量など、より多くの情報が必要になる可能性があります。
しかし、問題にはこれらの追加情報が提供されていません。問題自体に仮定や暗黙の条件があるかもしれませんが、問題にはこれらの状況が言及されていません。または、問題設計時にこれらの詳細が省略され、各袋の価格を直接計算できないかもしれません。
では、通常の処理方法に従うと、各袋の価格が異なり、総額が100元の場合、具体的な各袋の数量を知る必要があります。例えば、5種類の異なるサイズの袋があり、各数量が2、3、4、5、6個の場合、合計5×(2+3+4+5+6)=55袋、総重量は2+3+4+5+6=20kg、1kgあたりの価格は100/20=5元となります。この場合、各袋の価格は5元を対応する数量で割ったもの、例えば最初の袋は5元、2番目は8元、3番目は10元などとなります。しかし、問題には具体的なデータがないため、正確に計算できません。
または、問題はすべての袋の価格が同じであると仮定しているか、または異なる袋がいくつかあるが数量が不明であると仮定しているかもしれません。例えば、3種類の袋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袋などかもしれません。この結果が実際の状況に合致するか検証する必要があります。
次に、量り売りのお菓子の一般的な規格と価格分布を考慮します。例えば、一般的なお菓子の袋詰め価格は以下のようになります:
- 小袋(50g):約5元
- 中袋(100g):約10元
- 大袋(200g):約15元
各袋の価格分布がこの範囲内にあると仮定すると、100元をいくつかの部分に分割できます。例えば、各袋が5元の場合、20袋必要です。10元の場合は10袋、15元の場合は6.67袋となり、明らかに不合理です。したがって、各袋の価格は5元から10元の間で、合計が100元になるはずです。
ここで、各袋の価格が5元の場合、100元にするには何袋必要か計算します:
100 ÷ 5 = 20袋
したがって、各袋の価格が5元の場合、20袋必要です。この結果はツールが提供した結果と一致するため、合理的です。
結論:各袋の価格は5元で、合計20袋購入しました。<|im_end|>



