OmniAICreator/Japanese-Roleplay-Dialogues
Viewer • Updated • 28.5k • 194 • 16
ある Discord サーバーのログだけからゼロから学習した日本語の会話モデル。 既存の重みからの派生ではなく、tokenizer も含めて全部このサーバーのために作ってある。
この節を読まずに使うと、まともな出力は出ません。普通の instruct モデルでも
chat template でもなく、記号だけで会話の構造を表す独自の形です。
<|conv|> から始めて <|end|> で終わる 1 行が 1 会話になります。
<|c2|><|conv|><|s0|>これバグってる?<|s3|><|re|><|s0|>どこで止まってる?<|end|>
| トークン | 個数 | 意味 |
|---|---|---|
| `< | conv | >` |
| `< | end | >` |
| `< | c0 | >..< |
| `< | cx | >` |
| `< | s0 | >..< |
| `< | a | >..< |
| `< | z | >` |
| `< | re | >` |
<nl> |
1 | 発言の中の改行 |
<url> <file> <mention> <channel> <time> |
5 | 正規化した中身。学習で損失から外してあるので、モデルは自分では書きません |
<code> </code> |
2 | コードブロックの囲み |
<|a|>今日ひま?<|a|>あ、やっぱいいや)<話者><|re|><返信先>本文 の順。自分への返信には付けません<|conv|> の前。学習データは 100% がこれで始まるので、省くと分布の外になります続きを書かせたい人のトークンを末尾に置くと、その人の発言として続きます:
<|c2|><|conv|><|a|>日本の首都どこ<|s0|>
model.py と tok.model がこのリポジトリに入っています。
import json
import torch
import sentencepiece as spm
from safetensors.torch import load_file
from model import Config, MicroLM # このリポジトリの model.py
cfg = Config(**{k: v for k, v in json.load(open('config.json')).items()
if k in Config.__dataclass_fields__})
model = MicroLM(cfg)
state = load_file('model.safetensors')
state['head.weight'] = state['embed.weight'] # weight tying。head は保存していない
model.load_state_dict(state)
model.eval()
sp = spm.SentencePieceProcessor(model_file='tok.model')
prompt = '<|c2|><|conv|><|a|>日本の首都どこ<|s0|>'
ids = torch.tensor([sp.encode(prompt, out_type=int)])
got = model.generate(ids, max_new_tokens=80, temperature=0.9, top_k=40,
stop_id=sp.piece_to_id('<|end|>'))
print(sp.decode(got[0].tolist())[len(prompt):])
生成は <|end|> か、次の話者トークンが出たところで切ってください。
切らずに流すと、他の人の発言まで作り続けます。
多段で学習しています。外部データで日本語と会話の土台を作り、最後はこのサーバーのログだけで仕上げるという順序です。 混合比だけで比率を守ろうとすると、外部が数倍あるぶん永久に薄まります。
| 段 | 中身 | 量 |
|---|---|---|
| 段1 | 外部の会話 + このサーバーの素の会話 | 403,711,060 字 |
| 段2 | このサーバーだけ (窓の水増しと切り出し込み) | 90,949,883 字 |
| 段3 | リアクションの付いた発言の切り出しだけ | 2,118,256 字 |
話者トークンは発言数の多い順に 147 人ぶん (全発言の 96.6% を被覆)。 件数は 最多 55,964 / 最少 203 で、275 倍の開きがあります。 順位が小さいほどよく学習されています。
段1 に使った外部データ:
| データ | ライセンス |
|---|---|
| OmniAICreator/Japanese-Roleplay-Dialogues | Apache-2.0 |
| nntsuzu/JESC | CC-BY-4.0 |
| p1atdev/open2ch (元: 1never/open2ch-dialogue-corpus) | Apache-2.0 |
<|sN|> は匿名の順位で、userId は含まれていません。ただし発言の癖は重みに入っているので、特定の順位で生成した文がその人の書き方に似ることはありますtok.model はこのサーバーのログから学習しているので、会話の中でよく呼ばれる名前はBPE が 1 トークンにまとめます。実測で 147 人中 16 人 (上位20人では 7 人) の表示名がそのまま語彙にあり、列挙すれば読めます。<|sN|> の番号と名前の対応は含まれていませんが、「このサーバーによく居る人の呼び名」は分かります