Downloads · 30 days
36
6% of all-time downloads
tako080614/evex-3.5
evex-3.5 is a text generation model from tako080614. Use it when you need the model to write or continue text. It is set up for pytorch. The card lists the license as mit.
ある Discord サーバーの過去ログを主材料に、tokenizer からゼロで作った 18.9M パラメータの言語モデル。事前学習済みの重みは1つも使っていない。
Downloads · 30 days
36
6% of all-time downloads
All-time downloads
644
Public
Parameters
18.9M
2.7 GB on disk
Likes
0
Public
Click a slice to open those files.
.pt953 MB · 93%
From the Hugging Face model README
ある Discord サーバーの過去ログを主材料に、tokenizer からゼロで作った 18.9M パラメータの言語モデル。事前学習済みの重みは1つも使っていない。
evex-3(15.74M)から変えたのは 2 つだけ:
同じ系統の兄弟 — evex-1 / evex-2(5.87M)/ evex-3(15.74M)。
<|s0|> から <|s146|> は実在の人ひとりひとりに対応する。
つまりこのモデルは特定の人になりきって書ける。
speakers.json は順位と発言数だけ)<|sN|> が指すのは
このサーバーの人だけで、なりきり掲示板の投稿者ではない| データ | 目的 | |
|---|---|---|
| 段1 | 公開のなりきり掲示板 78% + このサーバー 22% | 会話の交代・話の受け方 |
| 段2 | このサーバーだけ | 口調と 147 人 |
混合比だけで「このサーバーらしさ」を守ろうとすると、外部が数倍あるぶん永久に 薄まる。最後がこのサーバーなら分布は戻り、土台の恩恵だけ取れる。
外部データには相対の役 <|a|>..<|h|> しか使わない。
「会話とはこう進むもの」だけを外から教え、誰が誰かはこのサーバーだけが持つ。
同じコーパス・同じ語彙で、段2 をゼロからも回した。
| 段2 | val (epoch 1) | val (epoch 3) | 噛み合い |
|---|---|---|---|
| 段1 から | 5.0638 | 4.9405 | 38.3% |
| ゼロから(対照) | 5.6111 | 5.1017 | 30.0% |
**段1 からの方が全 epoch で上。**しかも段1 からの epoch 1 が対照の epoch 3 より 良いので、土台があると 3 分の 1 の学習で追い越せる。
このモデル自身の val を同じ尺度で測った値を地の値として並べる。
匿名の役 <|b|>(bot の既定経路)
| evex-3 | evex-3.5 | 地の値 | |
|---|---|---|---|
| 噛み合い(質問の語が返答に出る) | 37.3% | 45.3% | — |
| 20字以上で返す | 55.3% | 60.0% | 31.2% |
| 平均の長さ | 30字 | 32字 | 19字 |
| 未知語 | 9.9% | 10.0% | 14.9% |
| 逐語コピー(20字以上の完全一致) | 0.0% | 0.0% | — |
名前持ち <|s0|>(なりきり)
| evex-3 | evex-3.5 | |
|---|---|---|
| 噛み合い | 24.0% | 34.0% |
| 20字以上 | 64.7% | 48.7% |
| 平均の長さ | 41字 | 29字 |
両方の経路で噛み合いが大きく伸びた(+8pt / +10pt)。なりきり時は短くなったが、 噛み合いが 24% → 34% なので、中身の薄い長文が減って的を射た短文になった形。
**なりきり掲示板の口調は漏れていない。**地の文((微笑み のような括弧)を
含む返答は 0.7% で、このサーバー自身の val(0.9%)を下回る。
元データは本文の 74% が地の文だったが、ビルド時に落としてある。
**20字以上の完全一致だけを数える。**閾値なしで測ると あ(学習に1877回)
それはそ(114回)のような誰でも言う相槌が「丸写し」として数えられ、
なりきりが 25.3% と出る。中身を見ると 14 件すべてが 10 字以下で、
21字以上の一致は 0 件だった。短い相槌を返しやすい経路ほど高く出るだけの
指標になっていたので、下限を入れている。
| パラメータ | 18,880,896(埋め込み 4.72M + 8層 14.2M) |
| 形 | d_model 384 / 8層 / 6 head / context 1024 / RoPE + RMSNorm + SwiGLU + weight tying |
| 語彙 | 12,288(ログから作った sentencepiece BPE) |
| 学習 | 段1 3 epoch (lr 1e-3) → 段2 6 epoch (lr 3e-4 → 1.5e-4) |
| val loss | 4.9299(記号を外した尺度)/ 素の val 5.0206 |
| ハードウェア | HF Jobs t4-small / 55,493 tok/s / 約60分 |
**val は evex-3(4.0741)と比べられない。**語彙が 3 倍になると 1 トークンあたりの 情報量が増えて loss は上がる。比べられるのは同じ語彙で回した対照との間だけ。
| 語彙 | 日本語 | 英字 | 英字トークン | docker compose up -d |
|---|---|---|---|---|
| 4096(evex-3) | 1.56字 | 1.94字 | 641 | 11 tok |
| 12288 | 2.06字 | 2.62字 | 3,058 | 7 tok |
| 16384 | 2.21字 | 3.08字 | 4,218 | 7 tok |
evex-3 は「100回以上出る語 9,342 に対しマージ枠 3,670」で、英字は 2,663 語に対し
トークン 641 しかなかった。出力に出ていた Cloberlop PHTHPAPAPA は、
この断片を組み立て損ねた形。
他の設定は全部いまの値が最善だった(総トークン数で比較): coverage 0.9995 は +0.8%、coverage 1.0 は +5.8%、split_digits は +2.3%、 unigram は +1.4% で、いずれも悪化。珍しい文字に3トークン払う方が、 頻出語のマージ枠を失うより安い。
| 段1 | 23,267,670 トークン(外部 78%) |
| 段2 | 19,280,662 トークン(このサーバーだけ) |
| 話者 | 147人(200件以上 / 発言の 96.6%)+ 相対の役 8 + 溢れ 1 |
外部は OmniAICreator/Japanese-Roleplay-Dialogues(Apache-2.0)。 なりきりチャット掲示板 4,324 スレッド / 606,492 投稿。 中の人の連絡(OOC)と地の文を落とし、露骨な表現を含む投稿を除いてある。
日本語の Discord データは公開されていない。discord を名前に含む 116 の
データセットに language: ja は 0 件で、92GB の多言語ダンプ 2,863 ギルドを
抽出調査しても日本語が 5% を超えるものは 0 件だった。
transformers では動かない。素の PyTorch で読む。
import json, torch, sentencepiece as spm
from safetensors.torch import load_file
from huggingface_hub import snapshot_download
path = snapshot_download("tako080614/evex-3.5")
cfg = json.load(open(f"{path}/config.json"))
sp = spm.SentencePieceProcessor(model_file=f"{path}/tok.model")
state = load_file(f"{path}/model.safetensors")
state["head.weight"] = state["embed.weight"] # tie_word_embeddings
# model.py は https://github.com/tako0614/sakana の scripts/llm/model.py
from model import Config, MicroLM
model = MicroLM(Config(**{k: cfg[k] for k in
["vocab_size", "n_layers", "d_model", "n_heads", "context", "dropout", "attn_dropout"]}))
model.load_state_dict(state)
model.eval()
prompt = "<|conv|><|a|>これバグってる?<|s0|>"
ids = torch.tensor([sp.encode(prompt, out_type=int)])
out = model.generate(ids, max_new_tokens=80, temperature=0.9, top_k=40,
stop_id=sp.piece_to_id("<|end|>"))
print(sp.decode(out[0].tolist())[len(prompt):])
<|conv|><|s0|>これバグってる?<|s3|><|re|><|s0|>どこで止まってる?<|s0|>
↑147人の誰か ↑別の人 ↑<|s0|> への返信 ↑ここの続きを書かせる
<|s0|>..<|s146|>(固有)と <|a|>..<|h|> / <|z|>(会話ごとの相対)<|re|> のあとに相手のトークンを置く。読む側は
<|re|> と続く話者トークンを落としてから本文を取ること —
相手のトークンを「次の話者」と読むと本文が丸ごと落ちる<|end|> で会話が終わる。<url> <file> <mention> <channel> <time> は
正規化が作った記号で、損失から外してあるので自分では書かないできる: このサーバーの口調、147人の読み分け、会話の交代、話を受けて返すこと
できない: 事実、計算、翻訳、指示に従うこと
18.9M しか無いので内容は当てにならない。狙えるのは「話を受けて、それらしい形で、 このサーバーの口調で返す」まで。
重みは MIT。学習データのうち外部ぶんは Japanese-Roleplay-Dialogues(Apache-2.0)、 残りは非公開の私的な会話。上の「147人の話者が重みに入っている」を必ず読むこと。