見出し画像

SakanaAI EvoLLM-JP-v1-7Bを試した。これからのマルチモーダルAIに必要なデータについて

話題のSakanaAIが発表した進化学習型LLMを試しました。

>>> from transformers import AutoTokenizer, AutoModelForCausalLM
>>> tokenizer = AutoTokenizer.from_pretrained("SakanaAI/EvoLLM-JP-v1-7B")
>>> model = AutoModelForCausalLM.from_pretrained("SakanaAI/EvoLLM-JP-v1-7B")
Loading checkpoint shards: 100%|█████████████████████████████████████████| 3/3 [00:02<00:00,  1.11it/s]
>>> d  = tokenizer("こんにちは!",padding="max_length",return_tensors="pt")
Asking to pad to max_length but no maximum length is provided and the model has no predefined maximum length. Default to no padding.
>>> t = model.generate(d["input_ids"],attention_mask=d["attention_mask"])
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
>>> tokenizer.decode(t[0])
'<s> こんにちは! 今日は、僕が大好き'
>>> 

お、おう・・・

能登半島についてどこまで知ってるだろうか

>>> d  = tokenizer("能登半島は",padding="max_length",return_tensors="pt")
>>> t = model.generate(d["input_ids"],attention_mask=d["attention_mask"])
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
>>> tokenizer.decode(t[0])
'<s> 能登半島は、石川県の西部に位置し、日'

短い。
最小生成トークン数を100にしてやってみる。

>>> t = model.generate(d["input_ids"],attention_mask=d["attention_mask"],min_new_tokens=100,max_length=200)
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
>>> tokenizer.decode(t[0])
'<s> 能登半島は、石川県の西部に位置し、日本海に面しています。能登半島は、岐阜県の飛騨山地と福井県の越前山地に挟まれた地域で、北陸地方の最西端です。能登半島は、能登地方と穴水地方に分かれています。能登地方は、石川県の西部に位置し、穴水地方は、石川県の最西端に位置しています。能登半島は、能登地方と穴水地方に分かれています。能登地方は、石川県の西部に位置し、穴水地方は'
>>> 

<s> 能登半島は、石川県の西部に位置し、日本海に面しています。能登半島は、岐阜県の飛騨山地と福井県の越前山地に挟まれた地域で、北陸地方の最西端です。能登半島は、能登地方と穴水地方に分かれています。能登地方は、石川県の西部に位置し、穴水地方は、石川県の最西端に位置しています。能登半島は、能登地方と穴水地方に分かれています。能登地方は、石川県の西部に位置し、穴水地方は'

割とちゃんとわかってるっぽい。
JSONとかできるだろうか

>>> d  = tokenizer("能登半島の主要都市をJSON形式にすると {name='",padding="max_length",return_tensors="pt")
>>> t = model.generate(d["input_ids"],attention_mask=d["attention_mask"],min_new_tokens=100,max_length=200)
Setting `pad_token_id` to `eos_token_id`:2 for open-end generation.
>>> tokenizer.decode(t[0])
"<s> 能登半島の主要都市をJSON形式にすると {name='能登半島',coordinates=[[36.0,130.0],[36.0,129.0],[35.0,129.0],[35.0,130.0]]} となります。このJSON形式を用いて、能登半島の地図を描くことができます。 \n\n地図を描くには、HTML、CSS、JavaScriptを用います。以下は、その例です。\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n  <title>能登半島の地図</title>\n  <style>\n    #map {\n"

"<s> 能登半島の主要都市をJSON形式にすると {name='能登半島',coordinates=[[36.0,130.0],[36.0,129.0],[35.0,129.0],[35.0,130.0]]} となります。このJSON形式を用いて、能登半島の地図を描くことができます。 \n\n地図を描くには、HTML、CSS、JavaScriptを用います。以下は、その例です。\n\n```html\n<!DOCTYPE html>\n<html>\n<head>\n <title>能登半島の地図</title>\n <style>\n #map {\n"

気になる。
能登半島の地図も書けるのか。
何を食わせたらこうなるんだ。

まあしかし最近AIに聞くこともある程度パターン化してきたのでこれから作るべきデータセットを逆説的に求めることができそうな気がする。

LLMとプログラムの連携を前提に考えると

1)あらゆるデータはJSON形式に変換する
2)あらゆるロジックはPythonまたはJavaScriptで書いておく
3)あらゆる関係性はgraphvizで扱える形式(mermaidなど)で書いておく
4)あらゆる数式はLaTeX形式で書いておく
5)図版はSVGか、PNGのBASE64エンコードで書く

ということを意識してデータセットを作るのが良さそうだ

人間に何か教えるよりよっぽど効率がいい気がする。
教科書の書き方も変わっていくな。これは。

全ての知識をJavaScriptとJSONとmermaidとLaTeXで記述した本をこれからたくさん書くのがいいだろう。そうすると色々な手間が省け、正しい知識を構造的に説明できるようになっているのがいい。

例えば、目次は関係性なのでmermaidで書く。
ある数式をLaTeXで書いて、その意味するところをJavaScriptまたはPythonで書く。表は全てJSON形式で書き、図版はSVGかBASE64で入れるといったようなことを心がければいい。

マルチモーダルモデルでは、画像は一度レンダリングされてCLIPなどのビジョンエンコーダーを通されてからトークン化される。

マルチモーダルモデルに於いて、例えばLLaVAで画像と絵はこのような関係にある。

graph TD
A[input_ids] --> B{画像トークンの位置を特定}
B --> C{input_idsを画像トークンで分割}
C --> D[分割されたinput_idsをトークン埋め込みに変換]
E[image_features] --> F{画像特徴量を分割}
D --> G{トークン埋め込みと画像特徴量を交互に結合}
F --> G
G --> H[結合されたトークン埋め込みと画像特徴量]
H --> I[パディングとマスキング]
I --> J[new_input_embeds]
Claude-3とMermaidで作成

画像はCLIPなどで特徴ベクトルに変換された後、「どの画像についてテキストのどの部分が話しているのか」に注目して違い違いにトークンに埋め込まれる。正直、これであってるのか俺にはよくわからない。普通に画像の特徴ベクトルをトークンとして渡すのではダメなんだろうか。

まあこんな感じで出てくるので、逆に「こう言う絵が正解です」というのが直接的には出てこないのが問題といえば問題である。

今のところ「画像+テキスト」→「テキスト」はできても、「画像+テキスト」→「画像+テキスト」はできてない。

でも本当は、「画像+テキスト」→「画像+テキスト」が欲しいはずなので、「こういう図を書いて」と言ったら書いてくれないと困る。

試しにClaude-3に書かせてみよう。

Claude-3が作成

しかし、欲しかったのはむしろこう言う図だった

上より下の方が欲しい。
関係性の図とかはMermaidは表現するのは得意だと思うが数学的な図となると俄然難しくなりそうだ。

ちなみにClaude-3に三平方の定理を説明させようとしたらこうなった

惜しい

まだ現状、LLMはプログラムコードの中身を「理解」しているわけではなく、「なんかこんな感じ?」とうろ覚えの知識で適当にそれっぽい答えを出しているだけなので、「このコードを書くとこうなる」と言うところまではわかっていない。「この画面はこのコードからできている」と言う学習をしているはずなので、「このコードを見て、どんな画面になるか考えろ」と言うのはまた次の学習目標になるだろう。StableDiffusionも入力コンテキストを長く(100Kとか)すればできるようになるのかもしれない。

まだまだよのう