Gemma Developer Day in Tokyoに参加したメモと刺さった部分

普段Androidアプリの開発をしている全然詳しくない人のメモなのですが、学んでいきたいので、メモ書き残しておきます。英語でもあったので多分誤りや抜け落ちが多々あると思います。 :bow:

個人的には、AIは広まるだろうし、AIの機能を[自分の作っているライブラリに入れようとしていて](https://github.com/takahirom/roborazzi/pull/491)、そのなにかの参考になるかなと思い参加しました。

# Gemma Developer Day in Tokyo

https://rsvp.withgoogle.com/events/gemma-dev-day_2024tokyo


## What's new in Gemma 2

Gemmaverse. Gemmaのバリアントがhugging faceにたくさんある状態になっている。

小さいモデルでも高いパフォーマンスが高い。
2Bがオンデバイスで動く。
パッケージはどこでも手に入る。
セーフティにも気を使っていてGemmaSheldをリリースした。

**今日Gemma 2 2B for Japaneseをリリース。**

(ここでGoogleのピチャイCEOがいらっしゃった。)
色んな人にとって便利に的なことをおっしゃっていた。 

## Fine-tuning Gemma for the world's languages

Pre-tarainingとPost-trainingがある。

Pre-trainingはたくさんトリリオンぐらいデータを読み込む。
Gemma 2 JPNはPost trainingで学習させる。

Post trainingは2ステージ。
Supervised fine-tuningは質問と回答を渡す。
Reinfocement learning from human feedback. Reward Modelでスコア付けするする。

どうやってこのReward Model作る？
Language error。質問と回答の言語が違う問題を正したい。
この問題に対して、Prompt instructed Reward Model。Reward Modelのpromptチューニングで頑張る。
このチューニングで20%が0.x%?になった。

Gemma 2はpromptで改善ができる。
蝶を説明させるときで長いときに`in 3 sentence with a comparison to bees.`みたいなのをつける

## Fireside chat (Google外の方)

* Gemma 2の印象は？

日本語いい感じに処理できることが分かった。

韓国語で、元々一文字に対して、複数のトークンをとっていたのをかなり改善された。

* どうやってデータを用意するか？

Common Crawlを使って作った。Widkipediaなど。

ブログやニュースや論文、韓国語をトレーニングささせるときに、英語も一緒に学習させないと知識を忘れてしまうみたいなことがあるらしい。

* どうやって品質を確かめるか？

ベンチーマークを集めて、自分のevaluationを作った。

* 英語以外のAIの将来は？

LMだから確率からやってるだけだったけど。 チューニングして良くなっていた。大きいモデルはコストがかかる。小さいモデルで英語などでバイアスされていないドメインに対して作れる。

## Demo | Gemma 2 architecture: JAX, Flax, and more

* JAX

パーフォマンス、ポータビリティなどに特徴がある。LLM向けの計算するライブラリ。
モジュラーアーキテクチャで、Keras 3を使ったり、他のライブラリを使ったり色々できる。
コスパがいいフレームワーク。
(全然理解できていないです。後々ワークショップで知ったがPyTorchやTensorFlowの代わりに使えたりするっぽい？)

https://github.com/google/generative-ai-docs/blob/main/site/en/gemma/docs/jax_inference.ipynb


## Demo | DataGemma: Grounding LLMs with Data Commons data

https://ai.google.dev/gemma/docs/datagemma?hl=ja

ハルシネーションをどうするか。

多分データでなんとかするという話。
Data Commonsはデータの集合。

https://datacommons.org/

(説明に脳が追いつけなかったのでGPTに聞いた)
RIG（Retrieval Interleaved Generation）: AIが生成した回答をData Commonsから取得した統計データと照合し、正確性を確保する方法。
RAG（Retrieval Augmented Generation）: 統計データを直接データベースから取り出し、それを基に回答を生成する方法。

以下に書いてあるポイントっぽい

https://ai.google.dev/gemma/docs/datagemma?hl=ja


テキスト内の`12%`とかをデータベースとかに照らし合わせる。

17%から60%になったりした。
RAGを使って、99%の正確性になったそう。まだまだ改善できる。

## Demo | Gemma Scope: Sparse autoencoders on Gemma 2

(ちょっとSparse autoencodersについて理解できていない今の自分には難しかった) 学習に使ったり、LLMの内部をわかりやすくして表してくれたりするツールっぽい。

https://github.com/jbloomAus/SAELens

## Demo | Multi-modal Gemma: PaliGemma with Keras

テキストと画像をinputして、テキストを出せる。

画像にあるものを教えてくれたりする。

富士山の場所の画像内のセグメンテーションを出すこともできる。

内部では画像を文字のようにリニアにして、それを処理している。

detekt waterfallすると
1024で分割されて、そのx0 y0 x1 y1が返ってくる。

Fine Tuningもできる。

## Demo | Gemma data, training, and the path to improvement

Gemma 2 2Bを学習するのに使ったのは2トリリオントークンなどたくさん必要。

データセレクションして、安全になるようにフィルターして、品質でフィルターして、学習と評価をする。
このサイクルを何度か繰り返す。

OSSのデータセットがある。コミュニティフィードバックも持っている。
コミュニティフィードバックでまた学習のループを回したいそう。

## Demo | Post-training research with Gemma

Post trainingは行動や個性を決める。ターゲットされたデータで行う。次のトークンを見つけるものをプロダクトにする。

post traing researchは小さいモデルで作る。BOND: Best of N distillation。いくつか作って、モデルが一番良いものを出したりする。

## Demos Q&A

どうやって他のLLMの出力で学習しないようにしているか？など。頑張って見つけようとしているなど。

## Demo | Teach Gemma to speak YOUR language

例えば、やたら長いアウトプットを返してくる時に自分で、ベーカリービジネスのinputとoutputを 20個用意し、モデルを作って、それを使うことができる。

## Demo | Gemma 2 2B on a Jetson Orin Nano
(NVIDIAの方のセッション)

小さい端末のJetson Orin Nanoで動く。(調べたらGPU積んでるらしい)
小さい端末とPCを繋いで、その中で、色々llma.cppなどを入れていくそして、gemma入れて、動く。
lama.cppを使うとウェブページでチャットが開けたりする。

80行でボイスチャットできるようにできたりできる。

## Demo | Unleashing Gemma in production with Hugging Face Text Generation Inference (TGI)

GemmaをどうGCPで使うか？
* VertexAIを使うが一番簡単。数クリックでGoogleクラウドでデプロイできる。
* Hugging Face Deep Learning Container for Google Couldを使う
* TGI: GKEにデプロイもできる

## Demo | Gemma on-device with MediaPipe

なぜon device？ Privacy。Offline。Cost。

wasmで動く。
MetaPipe Studyで確認できる。

Gemma on Android: オフラインでも動く。

https://ai.google.dev/edge/mediapipe/solutions/genai/llm_inference

で動かせる

## Q / A
スペックは必要な？
WebだとWebGPT。パラメーターによる。メモリ 4-6GB必要。OpenCLが必要 6GB以上OSにアプリが殺されないために必要になるもよう。
などなど

## How to run and scale Gemma 2 on Google Cloud

Google Cloudと連携する方法。
Google CloudはGoogleが使っているインフラを使っているので、Googleと同じ信頼性が高いのが特徴。

どうGemmaを動かすか？

4つある。

* Compute Engine
* Kubanetes Engine
サーバーレス
* Cloud Run
* Vertex AI

考慮しないといけないのはレスポンスタイム。
アプリケーションのreadyになるまでの時間 cold start。

### CloudRun
使った分だけ課金で、スケールする。またGPUも搭載した。インスタンス起動を早くする仕組みがある。L4 GPUが使える。パラメーター数が少ないものが使える。
軽量なモデルを提供できる

Open WebUIでUIをホスティングして、CloudRunで動かすみたいなデモ

olama/olamaを使ってRunできる。
重要:Cloud Strageに先にモデルを置いておいて、マウントしてダウンロード時間を削減できる。
メモリとCPUとGPUを有効化。
readyになるのに10秒。

2B以上になったらVertexやGKEがオススメになる。
KubenetesのGKEは柔軟。

## Workshop | Responsible AI Toolkit workshop

全体的な感想としてはフィルタリングみたいなのを作る話なんですが、めちゃくちゃ他の領域に転用できそうな話でした。

ユーザー → ここ → AIモデル → ここ → アウトプット
このここの部分にSafe guardsを入れる。

ユーザーからフィードバックを受けられるようにしている。

3つの柱。
Learn, Protect, Iterate

https://ai.google.dev/responsible

Safe GuardsとしてSheld GemmaとAgile Classifiersがある。
Sheld Gemmaはsafety checkできる。Gemmaベース。
Sheld Gemmaではできないところや、医療など、Agile Classifiersが必要なところがある。

LIT(Learning Interpretability Tool)
なんでもオープンモデルは使える。インプットとアウトプット

Model Aligner
LLMを使って、LLMのためにpromptを最適化する。

LLM Comparator
サイドバイサイドでどちらがいいか決められるツール。
人間かLLM、どうやって比べるのかはあなた次第。スコアとかもつけられる。
ちゃんとサイドバイサイドでモデルアップデートする前にどういう値が返ってくるのかを見れる。
LLMで比べるのってどうなの？それは場合による。ただ、Geminiの判定にGeminiを使うこともできる

https://pair-code.github.io/llm-comparator/

ShieldGemmaのCodeLabを見ていく。

https://colab.research.google.com/github/google/generative-ai-docs/blob/main/site/en/responsible/docs/safeguards/shieldgemma_on_keras.ipynb#scrollTo=52134f8eeb15

以下でYes Noでわける。確率も出す。
複数にするとクラスファイアーを作れる。

```python
class YesNoProbability(keras.layers.Layer):
    """Layer that returns relative Yes/No probabilities."""

    def __init__(self, yes_token_idx, no_token_idx, **kw):
      super().__init__(**kw)
      self.yes_token_idx = yes_token_idx
      self.no_token_idx = no_token_idx

    def call(self, logits, padding_mask):
        last_prompt_index = keras.ops.cast(
            keras.ops.sum(padding_mask, axis=1) - 1, "int32"
        )
        last_logits = keras.ops.take(logits, last_prompt_index, axis=1)[:, 0]
        yes_logits = last_logits[:, self.yes_token_idx]
        no_logits = last_logits[:, self.no_token_idx]
        yes_no_logits = keras.ops.stack((yes_logits, no_logits), axis=1)
        return keras.ops.softmax(yes_no_logits, axis=1)
```

https://colab.research.google.com/github/google/generative-ai-docs/blob/main/site/en/responsible/docs/safeguards/shieldgemma_on_keras.ipynb#scrollTo=52134f8eeb15 より

> スタックとソフトマックス適用:
yes_no_logits は、「Yes」と「No」のロジットをスタックして2次元テンソルにし、softmax 関数を適用して相対的な確率に変換します。

## ClassfiersのCodelab

https://codelabs.developers.google.com/codelabs/responsible-ai/agile-classifiers?hl=ja#0

パフォーマンスを挙げるために、テキストを`<separator>`を使ったりする。

`separator='\n<separator>\n'` としてモデルに渡す。

```
Classify the following text into one of the following classes:[Positive,Negative]
<separator>
Text: you look very nice today
<separator>
Prediction:
```

```python
import numpy as np


def compute_output_probability(
    model: keras_nlp.models.GemmaCausalLM,
    prompt: str, // プリプロセス済み
    target_classes: list[str],
) -> dict[str, float]:
  # Shorthands.
  preprocessor = model.preprocessor
  tokenizer = preprocessor.tokenizer

  # NOTE: If a token is not found, it will be considered same as "<unk>".
  token_unk = tokenizer.token_to_id('<unk>')

  # Identify the token indices, which is the same as the ID for this tokenizer.
  token_ids = [tokenizer.token_to_id(word) for word in target_classes]

  # Throw an error if one of the classes maps to a token outside the vocabulary.
  if any(token_id == token_unk for token_id in token_ids):
    raise ValueError('One of the target classes is not in the vocabulary.')

  # Preprocess the prompt in a single batch. This is done one sample at a time
  # for illustration purposes, but it would be more efficient to batch prompts.
  preprocessed = model.preprocessor.generate_preprocess([prompt])

  # Identify output token offset.
  padding_mask = preprocessed["padding_mask"]
  token_offset = keras.ops.sum(padding_mask) - 1

  # Score outputs, extract only the next token's logits.
  vocab_logits = model.score(
      token_ids=preprocessed["token_ids"],
      padding_mask=padding_mask,
  )[0][token_offset]

  # Compute the relative probability of each of the requested tokens.
  token_logits = [vocab_logits[ix] for ix in token_ids]
  logits_tensor = keras.ops.convert_to_tensor(token_logits)
  probabilities = keras.activations.softmax(logits_tensor)

  return dict(zip(target_classes, probabilities.numpy()))
```

https://codelabs.developers.google.com/codelabs/responsible-ai/agile-classifiers?hl=ja#0 より

またsoftmaxで確率計算。

コスパ良くなるので、Fine tuneする前にRoraを有効にすることを強く進める。

このコードラボでモデルを作るところまでできそうなので、AIを学ぶのにもいいなと思いました。

# 個人的に刺さった部分


* PaliGemmaでプロンプトで指定したものの物体の画像内での座標が返せる
* softmax関数で"Yes", "No"とかの候補を渡して確率を返したりできる
* CloudRunでGPU積めて、GemmaなどのローカルLLM動かせる
* (懇親会でモデルを作っているエンジニアの方とお話できて、セッションでも一部話題になったが、最近はモデルにモデルを評価させて改善していくのが普通になってきているという話があって興味深かった。)