evex-ft-2

Qwen3-0.6B-Base に、ある Discord サーバーの過去ログを追加学習したもの。 evex-ft-1 の第2世代で、ベースも 学習方法も同じ。変えたのはコーパスだけ。

ゼロから学習した兄弟もある — evex-1 / evex-2 (5.87M / tokenizer もログから作った)。

⚠️ 表示名が重みに入っている

話者ラベルが実在の人の表示名そのものです (あかり: にょ: たこ:)。 つまりこのモデルは特定の人になりきって書けます

  • 出力をその人が書いたものとして扱ってはいけない
  • 学習データは同意を明示的に取っていない会話。ログそのものと Discord の user ID は公開していない
  • 使える 147 個のラベルは speakers.json にある (表示名と発言数だけ)

ft-1 の何を直したか

ft-1 は口調は移ったが話を受けて返さなかった

A: git rebase と merge の違いって何
B: まじ?

原因はコーパスの分布。598,908 発言のうち 45.3% が10字以下 / 76.6% が20字以下で、 「聞かれたら答える」信号がほぼ無い。忘却ではない — 学習に入っていない普通の 日本語の perplexity は base の 1.12倍で、窓を 4096 に伸ばしても変わらない。 その形を選ぶ確率が低いだけだった。

sft-v5 で2つ足した。外部データは使っていない (混ぜると「借り物の口調」が入る)。

件数 train に占める割合
噛み合った箇所 23,111 12.3%
長い発言 32,593 25.6%
  • 噛み合った箇所 … 直前が疑問で別人が答えた / 直前の人に @名前 で宛てた、 応答が12字以上のもの。直前2行から切り出す
  • 長い発言 … 40字以上の発言を直前の文脈つきで切り出す

長い発言の 91% は名前を持つ人のものなので、ここを重くすると「長く喋る」と 「なりきり度」が同時に上がる。トレードオフにならない。

切り出しの一部は話者を匿名の役 (A/B/C) に付け替えてある (噛み合いは半分、 長い発言は4本に1本)。bot が /as 未指定のとき匿名の役で喋るのに、 「疑問→20字以上の答え」の 88.1% が名前持ちで、既定の経路に信号が届いていなかった。

効果 (実測 / 匿名の役 B: / n=50)

同じプロンプト・同じ乱数で、このサーバー自身の val を同じ尺度で測った値を 地の値として並べる。

evex-ft-1 evex-ft-2 地の値
噛み合い (質問の語が返答に出る) 20.0% 34.0%
平均の長さ 32字 49字 17字
敬体で終わる (借り物の口調) 5.0% 0.0% 3.0%
未知語 (コーパスに無い語) 14.3% 13.8% 14.8%
逐語コピー 0.0%

名前を指定した場合 (あかり:) は噛み合い 55% で ft-1 と同じ、平均 24→30字、 敬体は 20% → 10% に下がった。

epoch の選び方 — val では決まらない

epoch 1  val 2.5980
epoch 2  val 2.6079   ← こちらを推奨

val は epoch 1 の方が良く、ft-1 (2.5415) より両方悪い。val 集合は完全に同じ なので比較できるが、切り出しが train の 38% を占めて分布がずれたため。 val は「口調が移ったか」しか測っていない。

生成で測ると逆になる (匿名の役 / n=50):

epoch 1 epoch 2
噛み合い 42.0% 34.0%
敬体 18.0% 0.0%
未知語 8.5% 13.8%
逐語コピー 4.0% 0.0%

epoch 2 は借り物の口調がゼロ、語彙の手触りが本物とほぼ同じ、逐語コピーもゼロ。 噛み合いだけ 8pt 負けるが誤差寄り (17 vs 21 / 50)。

使い方

素の transformers で動く。独自トークンは1つも足していない。

import torch
from transformers import AutoModelForCausalLM, AutoTokenizer

path = "tako080614/evex-ft-2"
tok = AutoTokenizer.from_pretrained(path, subfolder="epoch-2")
model = AutoModelForCausalLM.from_pretrained(path, subfolder="epoch-2", dtype=torch.float32)
model.eval()

prompt = "#ch2\nA: git rebase と merge の違いって何\nB:"

ids = tok(prompt, return_tensors="pt")
out = model.generate(**ids, max_new_tokens=80, do_sample=True, temperature=0.9,
                     top_k=40, min_p=0.05, repetition_penalty=1.1,
                     pad_token_id=tok.eos_token_id)
print(tok.decode(out[0], skip_special_tokens=True)[len(prompt):])

プロンプトの形

#ch2                       ← #ch0..#ch15 か #other (上位16で全体の 97%)
たこ: これバグってる?        ← 147人は表示名 (speakers.json)
A: どこで止まってる?         ← それ以外は A..H / Z の相対の役
あかり:                     ← 末尾に置いた人として続きを書く

同じ人が続けて喋ることがある (学習データの話者の塊のうち 27.4% が2連続以上)。 素の日本語形式には終端トークンが無いので、放っておくと max_new_tokens を使い切る。 次の 名前: で切ること。

[画像] [動画] などは添付だけの発言で、返答としては出さないよう損失から外してある。

数字

ベース Qwen/Qwen3-0.6B-Base (596,049,920 params)
学習トークン 15.85M (ft-1 は 10.09M) / 73,782 会話
1024 (会話を EOS で継いで詰める / パディングしない)
学習 2 epoch / lr 5e-5 / cosine / AdamW 8bit / fp16 + fp32 master
ハードウェア Kaggle T4 / 峰 12.8GB / 約 6.8 時間

できること / できないこと

できる: そのサーバーの口調、147人の読み分け、話を受けて返すこと、 名前を持たない人の口調 (例を渡せば)

できない: 事実、計算、翻訳、指示に従うこと

内容は当てにならない。 これは ft-1 から変わっていないし、変えられない — Qwen3-0.6B は instruct 版ですら「日本の首都」を大阪と答える。0.6B で狙えるのは 「話を受けて、それらしい長さで、このサーバーの口調で返す」まで。

ライセンス

ベースは Qwen3-0.6B-Base (Apache-2.0) の派生。学習データは非公開の私的な会話なので、 再配布・商用利用は想定していない。上の「表示名が重みに入っている」を必ず読むこと。

Downloads last month

-

Downloads are not tracked for this model. How to track
Inference Providers NEW
This model isn't deployed by any Inference Provider. 🙋 Ask for provider support

Model tree for tako080614/evex-ft-2

Finetuned
(661)
this model