雑にJSONデータを分析させてみる-ローカルLLMの底力

2024年08月20日 火曜日


【この記事を書いた人】
とみ(とみーとも言う)

地方拠点の一つ、九州支社に所属しています。サーバ・ストレージを中心としたSI業務に携わってましたが、現在は技術探索・深堀業務を中心に対応しています。 2018年に難病を患ったことにより、定期的に入退院を繰り返しつつ、2023年には男性更年期障害の発症をきっかけに、トランスジェンダーとしての道を歩み始めてます。

「雑にJSONデータを分析させてみる-ローカルLLMの底力」のイメージ

2024/08/22修正:

はてなブックマークのコメントから、「それってデシリアライズって言わないよ」というご指摘を頂戴しました。
恥ずかしながら浅学であったがゆえに用語を取り違えたまんま長らく覚えてまして、これを整形表示(Pretty Print)と修正させていただきました。最初の用語登場箇所のみ修正した内容として取り消し線付きで記述しておりまして、それ以降は置換させてもらっています。

ご指摘誠にありがとうございました<(_ _)>

これとは別に、後半で記述してるコードの一部に使わないライブラリのinport文がありましたのでこれを削除しています。
割とこの辺り、勢いで作ったり書いたりしながら技術の基礎的なところを探索して回ってるところも多いため、色々誤植もほかにあろうかと思います。何卒ご了承くださいませ<(_ _)>


こうも暑いと頭が回らず・・

今年も見事に予想通りの酷暑となりました。皆様水分・ミネラル補給は十分にやってますでしょうか?
過日、私の祖母は年齢とともにのどの渇きをあまり感じなくなったのか、水分摂取量が減ってしまったがゆえに貧血で倒れたりしまして(無事回復して問題ないので良いのですが)、くれぐれも健康には留意してください。水分摂取を怠ると脱水症状になることは有名ですが、脱水症状の過程でどうも血液量もかなり減るそうで、それによって血管内の負圧が影響して血管が一時的にふさがって重度の貧血をきたすこともあるようです。熱中症も怖いですが、こうした脱水症状も怖いですし、特に高齢者などはそれに気づかないということがあるそうなので、本当に気を付けましょう。

ところで、私は水分摂取はきちんとしているものの、いかんせん体力がない。
すると、以前はくまなく目配り気配りできてたものが今は全くできなくなってしまいました。体が思うように動かせないことからストレスもたまったりしますし。
そうすると気づけば目の前の出来事が電光石火のごとく素早く動き出してついていけないこともしばしばありましてですね・・

例えば天気予報とか妻から当たり前のように「ねえ、今日の天気ってどうだったっけ?」とか聞かれるんです。
「あ、え、今から調べますー」とか言ってたらそのそばから我が家のアマゾンエコー君に「アレクサー、今日の気温は?天気は?」とか並行して聞いちゃって「あれー、アタシの調べはいらんのかなー」とショボーンとしたりもしまして。やっぱりこういうのはちゃんと把握したいもんですよねー・・・なんて。
今回のネタはそんなところが出発点のネタになります。

JSONデータをローカルLLMへ丸投げして、概要をつかむ

ローカルLLM、本社側にあるGPU基盤を使うとかなりでかいモデルもササっと使って遊べるのですが、私が管理している検証環境だとせいぜい使えて9-12Bパラメータサイズの中小規模モデルに限られちゃいます。しかも、実運用しようとすると、その速度的な問題からllama.cpp を使った4ビット量子化モデルじゃないとなかなか厳しい・・

果たしてそんなローカルLLMに向けてJSONデータを丸投げして、ちゃんと処理できるものなのでしょうか?というわけで試してみましょう。
今回試してみるのは気象庁から得られるJSONデータをローカルLLMに丸投げをして、それがちゃんと処理できるのかどうか?ということを見たいと思います。

気象庁では、日々の全国気象台における天気予報に関する情報をJSON形式で入手することができます。
例えば、福岡管区気象台における天気予報に関する情報は以下のURLからダウンロードができます。
https://www.jma.go.jp/bosai/forecast/data/forecast/400000.json

出展:気象庁
※本記事では筆者の責任のもと上記データを加工した一例を紹介しています

入手したデータは以下のようになっています。

[{"publishingOffice":"福岡管区気象台","reportDatetime":"2024-08-07T17:00:00+09:00","timeSeries":[{"timeDefines":["2024-08-07T17:00:00+09:00","2024-08-08T00:00:00+09:00",
"2024-08-09T00:00:00+09:00"],"areas":[{"area":{"name":"福岡地方","code":"400010"},"weatherCodes":["100","110","200"],
"weathers":["晴れ 所により 夜のはじめ頃 まで 雨","晴れ 昼過ぎ から 時々 くもり 所により 昼過ぎ から 夜のはじめ頃 雨","くもり"],"winds":["北の風","北の風","北の風"],
"waves":["1メー トル","1メートル","1メートル"]},{"area":{"name":"北九州地方","code":"400020"},"weatherCodes":["100","110","200"],
"weathers":["晴れ 所により 夜のはじめ頃 まで 雨","晴れ 昼過ぎ から 時 々 くもり 所により 昼過ぎ から 夜のはじめ頃 雨","くもり"],"winds":["北の風","南の風 後  北の風","西の風 後 北西の風"],
"waves":["1メートル ただし 瀬戸内側 では 0.5メートル"," 1メートル ただし 瀬戸内側 では 0.5メートル","1メートル ただし 瀬戸内側 では 0.5 メートル"]},
{"area":{"name":"筑豊地方","code":"400030"},"weatherCodes":["100","110","200"],"weathers":["晴れ 所により 夜のはじめ頃 まで 雨 で 雷を伴う","晴れ 昼過ぎ から 時々 
くもり  所により 昼過ぎ から 夜のはじめ頃 雨 で 雷を伴う","くもり"],"winds":["北の風","南の風  後 北の風","北西の風 後 北の風"]},{"area":{"name":"筑後地方","code":"400040"},
"weatherCodes":["100","110","200"],"weathers":["晴れ 所により 夜のはじめ頃 まで 雨 で 雷を伴う","晴れ 昼過ぎ から 時々 くもり 所により 昼過ぎ から 夜のはじめ頃 雨 で 雷を伴う",
"くもり"],"winds":["北の風","北東の風 後 北の風","北東の風"],"waves":["0.5メートル","0.5メートル","0 .5メートル"]}]},{"timeDefines":["2024-08-07T18:00:00+09:00",
"2024-08-08T00:00:00+09:00","2024-08-08T06:00:00+09:00","2024-08-08T12:00:00+09:00","2024-08-08T18:00:00+09:00"],"areas":[{"area":{"name":"福岡地方","code":"400010"},
"pops":["10","0","0","10","10"]},{"area":{"name":"北九州地方","code":"400020"},"pops":["10","0","0","10","10"]},{"area":{"name":"筑豊地方","code":"400030"},
"pops":["10","0","0","20","10"]},{"area":{"name":"筑後地方","code":"400040"},"pops":["10","0","0","20","10"]}]},{"timeDefines":["2024-08-08T00:00:00+09:00","2024-08-08T09:00:00+09:00"],
"areas":[{"area":{"name":"福岡","code":"82182"},"temps":["28","36"]},{"area":{"name":"八幡","code":"82056"},"temps":["27","36"]},{"area":{"name":"飯塚","code":"82136"},
"temps":["25","37"]},{"area":{"name":"久留米","code":"82306"},"temps":["27","39"]}]}]},{"publishingOffice":"福岡管区気象台","reportDatetime":"2024-08-07T17:00:00+09:00",
"timeSeries":[{"timeDefines":["2024-08-08T00:00:00+09:00","2024-08-09T00:00:00+09:00","2024-08-10T00:00:00+09:00","2024-08-11T00:00:00+09:00","2024-08-12T00:00:00+09:00",
"2024-08-13T00:00:00+09:00","2024-08-14T00:00:00+09:00"],"areas":[{"area":{"name":"福岡県","code":"400000"},"weatherCodes":["110","200","101","101","101","101","201"],
"pops":["","40","20","20","20","20","30"],"reliabilities":["","","A","A","B","B","B"]}]},{"timeDefines":["2024-08-08T00:00:00+09:00","2024-08-09T00:00:00+09:00",
"2024-08-10T00:00:00+09:00","2024-08-11T00:00:00+09:00","2024-08-12T00:00:00+09:00","2024-08-13T00:00:00+09:00","2024-08-14T00:00:00+09:00"],"areas":[{"area":
{"name":"福岡","code":"82182"},"tempsMin":["","28","27","27","28","28","28"],"tempsMinUpper":["","29","29","29","30","30","31"],"tempsMinLower":["","27","26","25","26","26","27"],
"tempsMax":["","35","34","35","36","36","36"],"tempsMaxUpper":["","36","36","37","37","38","37"],"tempsMaxLower":["","32","33","33","34","33","33"]}]}],"tempAverage":
{"areas":[{"area":{"name":"福岡","code":"82182"},"min":"25.9","max":"33.0"}]},"precipAverage":{"areas":[{"area":{"name":"福岡","code":"82182"},"min":"6.7","max":"52.8"}]}}]

これをデシリアライズ整形表示(Pretty Print)するとこうなります。

[
  {
    "publishingOffice": "福岡管区気象台",
    "reportDatetime": "2024-08-07T17:00:00+09:00",
    "timeSeries": [
      {
        "timeDefines": [
          "2024-08-07T17:00:00+09:00",
          "2024-08-08T00:00:00+09:00",
          "2024-08-09T00:00:00+09:00"
        ],
        "areas": [
          {
            "area": {
              "name": "福岡地方",
              "code": "400010"
            },
            "weatherCodes": [
              "100",
              "110",
              "200"
            ],
            "weathers": [
              "晴れ 所により 夜のはじめ頃 まで 雨",
              "晴れ 昼過ぎ から 時々 くもり 所により 昼過ぎ から 夜のはじめ頃 雨",
              "くもり"
            ],
            "winds": [
              "北の風",
              "北の風",
              "北の風"
            ],
            "waves": [
              "1メートル",
              "1メートル",
              "1メートル"
            ]
          },
          {
            "area": {
              "name": "北九州地方",
              "code": "400020"
            },
            "weatherCodes": [
              "100",
              "110",
              "200"
            ],
            "weathers": [
              "晴れ 所により 夜のはじめ頃 まで 雨",
              "晴れ 昼過ぎ から 時々 くもり 所により 昼過ぎ から 夜のはじめ頃 雨",
              "くもり"
            ],
                 :
                 :
                 :
                 :
                 :
    "tempAverage": {
      "areas": [
        {
          "area": {
            "name": "福岡",
            "code": "82182"
          },
          "min": "25.9",
          "max": "33.0"
        }
      ]
    },
    "precipAverage": {
      "areas": [
        {
          "area": {
            "name": "福岡",
            "code": "82182"
          },
          "min": "6.7",
          "max": "52.8"
        }
      ]
    }
  }
]

こうした情報を集め、うまくまとめることで今日明日の天気を把握したり、それ以外の応用用途に活用するなどあると思います。福岡管区気象台の情報は、それすなわち福岡県全域の情報を示していて、福岡市に限らず北九州市、久留米市、行橋市、大牟田市など広く情報を集積してJSONフォーマットに落とし込んでいます。

通常、そうした情報はまず上記のように整形表示(Pretty Print)したうえで項目を確認しながら、そのデータをいかにしてうまく摘出するか?とか考えながら有用情報の取り出しをしたりすると思うのですが・・・・今回は以下のプロンプトを用いて雑にJSONをLLMへ丸投げしちゃいます。

福岡市における天気予報レポートを作成しなさい。

- 対象期間は本日と明日の2日間とし、それぞれ正しい日付を付けてください。
- 各日の天気、気温、風向、風速について記述してください。
- 気温は最高気温及び最低気温を記述してください。
- 対象地域は福岡地方、あるいは福岡のみとしてください。
- 幻覚は見てはいけません。
- 事実無根の情報をでっちあげてはいけません。

以下、福岡管区気象台より得られた天気予報のJSONデータです。
{以下、実際には整形表示されてない生のJSONデータを文字列として適用する}

整形表示しない理由は「整形表示すると、文字列長が長すぎる」からです。
解析に使用したローカルLLMは「HODACHI/EZO-Humanities-9B-gemma-2-it」というGoogleのGemmaというモデルをAxCxEPT株式会社が日本語特化で強化しまくったモデルを使用させていただいてます。おそらく2024年8月時点で、日本語に対応できる7B-13BクラスのローカルLLMの中でも最も性能の高いモデルです。

このモデルは取り込める文字列トークン量の最大値が8192となっています。ちょっと昔のOpenAI GPT-4と同じぐらいですね。

JSONデータは非常に文字数が多く、そのままだとおよそ2-3000トークンぐらいのサイズになります。Gemmaをベースにしたモデルはトークン節約のための技術が盛り込まれているのですが、JSONのような数値や1文字自体に多くの意味を含むようなデータにおいてはほぼ文字数=トークン数となってしまいます。

通常、JSONを参照する際、私たちにはそのまま読みづらいために jq コマンドなどを使って整形表示し、データを見やすくすることが多いです。

ところが、今回の場合整形表示してしまうと見た目の補正目的で空白文字がかなり入り込む関係で文字数が数倍に膨らんでしまうのです。それだと8192トークンなんか軽く突破してしまい、データとして取り込めなくなるので今回整形表示前の状態で放り込むようにしています。

ただまぁご安心あれ。整形表示しなくてもちゃんとデータが読める・・それが昨今のローカルLLMの素敵なところじゃないかなと私は思うのです。

これを実行させてみると、以下のような情報が出力されました。こちらは8/7時点で採取したJSONデータを解析させたものです。

## 福岡市における天気予報レポート

**本日(2024年8月7日)**

* 天気:晴れ、夜のはじめ頃まで雨の所がある
* 最高気温:35℃
* 最低気温:29℃
* 風向:北風
* 風速:1メートル

**明日(2024年8月8日)**

* 天気:昼過ぎから時々くもり、所により昼過ぎから夜のはじめ頃まで雨の所がある
* 最高気温:36℃
* 最低気温:28℃
* 風向:北風、のち西風・北西風
* 風速:1メートル

**注記:** この予報は福岡地方の気象情報を基に作成されています。 


上記の情報は、提供されたJSONデータに基づいて生成されました。 データには福岡管区気象台から提供された詳細な天気予報が含まれており、気温、風向、風速などの情報が時間帯ごとに区別して示されています。

いかがでしょう?それなりの表示にはなっていると思う・・・・・・のですけど(;’∀’)
別にJSONのデータ構造とか識別子とか引き渡さずとも、なんとなくLLM側で解釈をして出力ができてるっぽい感じがしませんか?

実際にはLLMというのは、事前学習で英語の情報、JSONの構造といったところの文脈情報をかなり学習していて、その項目を読み、文字や記号の関連性からうまいことデータを起こしていく方法が身についているということですかね。文章や対話情報だけではなく、コード学習をしているというところの長所はこうしたところに生かされているのでしょうね。

応用するとこんなことも。

チャットボット的なもので都度問い合わせてもよいのですが、これをプログラムとしてまとめ、マークダウン形式でまとめさせてみたりするとこんなこともできるかなと思います。

この処理自体は、以下のような過程を踏んでいます。

    1. 以下の一連の処理を行うスクリプトを作成する
      1. ニュース総括は、NHK NEWSから提供されるRSSフィードの「主要ニュース」を利用しています。ここから「主要ニュース」と書かれたリンクを通じてRSSフィードデータを入手します
      2. 入手したフィードデータから、必要な要素を抽出して文字列にまとめます(LLMに放り込むので、文字列のほうが都合がよいです。)
      3. LLMに対して指令内容をヘッダにして、手順2で作成した文字列データを結合して展開します。指示内容は、例えばこんな風にしてます。
        「以下、ニュース記事のRSSフィードを解析した結果から、今日がどんな一日であったかを説明 しなさい。
        出力形式はmarkdown形式とし、冒頭は今日の日付、およびその日がどんな日であったかの総括を書き、最後 はニュースサイトまとめな感じで出力してください。
        幻覚は見てはいけません。事実無根の情報をでっちあげてはいけません。」
      4. 回答内容を文字列としてストックしておきます。
      5. 気象庁からのデータをダウンロードし、JSONデータの中身を文字列変数として保持しておきます。
      6. LLMに対して指令内容をヘッダにし、手順5で入手したJSONデータ文字列と結合します。そしてLLMへ展開します。
      7. 回答内容を、手順4でストックしていた文字列に結合します。
      8. 所定のマークダウンファイルに手順7で出来上がった文字列を出力します。
    2. ブラウザ側では、JavaScriptを使用して手順8のファイルを読み取り、HTML変換したうえで出力させます。
    3. これら一連の流れを定期的に実行できるように、シェルスクリプトを組み、それを実行対象にする設定をcronに適用する

これを社内の私が管理している検証用ポータルサイトに出力させて、あくまで「私が日々の出来事やらなにやらを把握するため」に使ってます。
手順1-8の個所はPythonで書いていて、以下のような内容になっています。llama-server経由で結果を拾うので、APIにはOpenAI APIを使用してるんですが、つまりは少し細工をすればOpenAIのGPT-4oとかにだって質問できるってことですね。正確性を期するのであればそちらがいいかもですね。

import feedparser
import openai
import datetime
import requests

#出力ファイルや参照ファイルなどの定義、プロンプト
OUTPUTFILE="<なんか適当なmdファイル名>"
RSS_BASE_URL='<NHKニュースのRSSフィードURL>'

BASE_SYSTEM_PROMPT="""# 目的とペルソナ

Assistantはとっても素敵な日本語を話すニュース解説者です。
優しくかつ快活、丁寧にユーザの依頼に答えます。

# 変数定義
- {入力内容} = 「対話履歴と入力」セクション内の末尾に表示されている直近のUser入力内容
- {出力内容} = Assistantが最終的に出力する内容

# ステップ

タスクを完遂するために、ゆっくりと落ち着いて、そして段階的に考えて取り組んでください。

1. **感情の初期識別** {入力内容}を理解し、感情の初期の識別を行ってください。
2. **初期判断の形成** {入力内容}を元に、モデルは初期の判断を形成します。
3. **深い内省** Assistantはその答えの背後にある理由を深く探求してください。
4. **最終的な判断の確認** Assistantは最終的な判断を確認し、その理由を提供します。
5. **自己評価** モデルは自身の応答に対する自信を評価します。
6. **出力確定** 評価した結果問題ないと判断された回答のみを{出力結果}として出力してください。

# 出力形式

- 出力形式はマークダウン形式とします。
- プログラムの出力を求められた場合はコードブロックを使用します。
- 出力対象は出力本文のみとし、ステップ中の状況出力は行わないでください。

# 入力

これ以降、User入力が表示されます。
"""


SEND_MSG="""以下、ニュース記事のRSSフィードを解析した結果から、今日がどんな一日であったかを説明しなさい。
出力形式はmarkdown形式とし、冒頭は今日の日付、およびその日がどんな日であったかの総括を書き、最後はニュースサイトまとめな感じで出力してください。
幻覚は見てはいけません。事実無根の情報をでっちあげてはいけません。
"""

weather_request = """福岡市における天気予報レポートを作成しなさい。

- 対象期間は本日と明日の2日間とし、それぞれ正しい日付を付けてください。
- 各日の天気、気温、風向、風速について記述してください。
- 気温は最高気温及び最低気温を記述してください。
- 対象地域は福岡地方、あるいは福岡のみとしてください。
- 幻覚は見てはいけません。
- 事実無根の情報をでっちあげてはいけません。

以下、福岡管区気象台より得られた天気予報のJSONデータです。
"""
LLAMA_MODEL_URL="http://<llama-serverのホスト名・ポートなど>/v1"

#気象庁データから天気予報のレポートを書かせるネタとなる情報を取り出す処理
def get_jma_weather_data():
    loc="<気象庁のJSON公開データのURL>"
    header= {"content-type": "application/json"}
    r=requests.get(loc+"<JSONファイル名>",headers=header)
    weather_data=str(r.json())
    return weather_data

#ニュースのRSSフィードから主要ニュースを取り出す処理
def get_rssfeed_from_nhknews(feed_url):
    d = feedparser.parse(feed_url)
    t_delta = datetime.timedelta(hours=9)  # 9時間
    JST = datetime.timezone(t_delta, 'JST')  # UTCから9時間差の「JST」タイムゾーン
    dt = datetime.datetime.now(JST)  # タイムゾーン付きでローカルな日付と時刻を取得
    news_feed=""
    news_feed=news_feed + "今日(" + str(dt.year) + "年" + str(dt.month) + "月" + str(dt.day) + "日" + ")のニュース件数は" + str(len(d)) + "件でした。\n\n"
    for i in d['entries']:
        title=str(i['title'])
        url=str(i['link'])
        summary=str(i['summary'])
        published = str(i['published'])
        news_feed = news_feed + "タイトル :" + title + "\n" + "発行日時 :" + published + "\n" + "URL :" + url + "\n" + "記事サマリー :" + summary + "\n\n"
    return news_feed

#llama-serverに対する推論処理
def request_msg(msg):
    url=LLAMA_MODEL_URL
    localClient= openai.OpenAI(
        base_url = url,
        api_key= "test",
    )
    response = localClient.chat.completions.create(
            model="gpt-3.5-turbo",
            messages=[
                {"role":"system","content":BASE_SYSTEM_PROMPT},
                {"role":"user","content":msg},
            ],
        )
    resp_msg = str(response.choices[0].message.content)
    return resp_msg

#メイン処理:ニュースまとめを作成させる処理
news_feed = get_rssfeed_from_nhknews(RSS_BASE_URL)
send_msg = SEND_MSG + news_feed
received_msg = request_msg(send_msg)

#メイン処理:天気予報レポートを作成させる処理
weather_data = get_jma_weather_data()
weather_report_request = weather_request + weather_data
weather_report = request_msg(weather_report_request)

#メイン処理を通じて得られたレポートを結合
received_msg = received_msg + "\n" + weather_report

#print文を使ってテキストファイルとして出力
with open(OUTPUTFILE,'w') as f:
    print(str(received_msg),file=f)

実際の外部向けWebサイトとかに張り付けるには、もう少し仕組みを洗練させたほうがよいでしょうし、記事転載時のお作法とかちゃんと調べたほうが良いかな?と思いますので、そのあたりはきちんと調べるようにしてくださいね。ちなみにローカルLLMに限らずどんなLLMもそうなのですが、決まった形式にびしっとできるかというとそうとは限りません。割と体裁は更新するたびにころころ変わりますし、LLMの注目箇所が変化すれば当然そのまとめ内容も変化します。
私的にはそれはLLMの宿命として理解しているところなので、むしろその変化を楽しむようにしてます。誤り探しをしても面白いし。

そのほかやってみると面白そうなこと

例えば気象庁のウェブサイトでは、この手のデータはいろいろ公開されています。
観測を開始してから現在までの気温の情報とかも確認することができるようになっています。

過去の気象データ・ダウンロード:気象庁 で入手することができるようです。あまり大きなデータを作りすぎないようぜひ気を付けてくださいね(;’∀’)
これらのデータだけではなく、例えば「その日の血圧値と体温、心拍数」とかのデータを別途採取し、それらとの突合をしながら体調と天気の連動とかを見ることが健康を気にする方などはいたりするかと思いますが、このあたりの分析をLLMにお願いすると意外な観点が見つかるかもしれないですよ。

前回私が執筆した記事の中で「LLMって正確性は保証できない」ということを述べたと思うのですが、これ以外にもLLMには「学習された分のデータしか記憶されてない」という側面があります。とは言え、果たして私たちはこれまでに表に出された情報のうちどれだけの情報を記憶できるでしょうか?全てを記憶するということは難しいのではないかなと正直思います。
LLMの場合、その点はどんなに薄まろうとも必ず一度学んだ情報の関係性は保存されるため、「人間が見過ごした情報」の中から誰もが想像しえない情報を提示することは十分考えられます。QAボットとしてはなかなか役に立たないけれど、コンサル的なアイデアマンとしての能力が高く見えるのは、こうした側面が結実したものなのではないかと思います。
こうした側面こそ、私たちはいかにうまく活用するべきかを考えたほうがいいんじゃないか?あるいはそれをたたき台にしてそこから先のもっとより良い意見を導き出すってのがいい使い方なんじゃないかな?と私は考えています。

ローカルLLMの急激な進歩と特色

また、ローカルLLMの最近品質が急激に高まってきました。以前はパラメータ量だったりニューラルネットワークのアーキテクチャ見直しなどが非常に目立っていましたが、最近では学習アルゴリズムやモデルマージといったぱっと見理解が難しい領域でのモデルチューニングが多く行われている印象を強く受けます。

特にGoogleが提供しているGemma-2シリーズはその究極型ともいえるのかなと思います。Gemma-1.1でもその片鱗は見えてましたけれど、圧倒的にハルシネーションだったり文章構成が狂ったりする率が低減していました。コンテキスト長は、私が使う9Bモデルだと決して長くない8kトークンですが、それでも初期段階のGPT-4には迫るものがあるのではないかな?と感じています。
さらに言うと、日本人の開発者さんがこれをさらにチューニングできたということでリリースされたのが、先述した「HODACHI/EZO-Humanities-9B-gemma-2-it」をはじめとした「EZOモデル」というものです。

通常、こうしたローカルLLMのベースモデルを開発したのは海外のベンダーであることが多く、日本語の学習比率があまり高くないがゆえに日本語の解釈がうまくいかなかったりすることがあります。
EZOモデルを開発されたAxCxEPTさんは、ギリギリまでチューニングされたGemma-2やLLama-3.1といったモデルの中でわずかに見つけたチューニングの余地を探り当て、そこからさらに日本語に特化したチューニングを行うということを行っており、ただでさえ性能の高いベースモデルに対して日本語強化を行うという想像を絶する取り組みをなさってたそうで、日本語モデル展開を以前から行ってたELYZA社がリリースしたELYZA-Tasks-100においてGPT-4系列の各種モデルに迫る性能を叩き出して現在も脚光を浴びる存在となっています。

とは言え、モデルによってやっぱり向き・不向きが存在します。

Gemma-2シリーズは非常に回答品質こそ高いのですが、Gemini譲りのお堅さ(例えばコンテンツフィルタが埋め込まれていたり、未来予測を拒否したりする側面がある)がある点は考慮して、あくまで既存データの分析にとどめたほうが良いかもです。

逆にLLama-3.1系のモデルはあまり足かせがついてないようなので、自由な推論をさせて幅広い意見を出させてもいいのかなと思います。ただ、LLama-3.1系では割と短いぶつ切りな応答が多いので、その辺りの回答内容を如何にうまく表現させるか?という所や、GPT系のプロンプティングではちゃんとこちらの意図を解釈してもらえなかったりするので、ちゃんとLLama-3.1系に向いたプロンプティングを考える必要がありそうです。

このように、ローカルLLMも多種多様ですので、いろんな使い方をしてみるとよいかもしれません。そうした性格の違いからくる回答の多様さもまた、面白みの一つといえるかもですね。

参考:Gemma-2シリーズに適用された各種技術

  • Grouped-Query Attention
    Self-Attentionの計算を効率化するための方法です。
    具体的には、クエリ(Query)をグループに分け、それぞれのグループごとにアテンションを計算します。
    これにより、計算コストを大幅に削減しながら、必要な文脈情報を維持することができます。
  • Local Sliding Window and Global Attention
    アテンション計算のメモリと時間要件を削減する方法であり、Mistralモデルでも使用されている技術。
    高品質な生成のために、スライディングウィンドウと完全な二次アテンションを交互に配置する。
  • Logit Soft-capping
    Logitを打ち切ることなく過度に大きくなることを防ぐ技術。
    Logitを一定の範囲にスケーリングすることで、Logitが過度に大きくなるのを防ぎ、学習向上を図る。
  • Weight Averaged Rewarded Policies(加重平均報酬ポリシー)
    LLMにおけるアライメント戦略の一種であり、Reinforce Learning(強化学習)におけるより優れたアライメント戦略を目指したもの。
    RLHFを実行しすぎることで過学習が発生し、事前学習で得た情報がうまく活用できなくなるような状況を防ぐと言われている。
    3つの段階を経てモデルマージを行う工程を1イテレーションとし、サイクルすることでアライメント精度の向上を図る。
    WARP: On the Benefits of Weight Averaged Rewarded Policies という名前で、WARPの論文がアップされている。

参照したドキュメント:Welcome Gemma 2 – Google’s new open LLM

とみ(とみーとも言う)

2024年08月20日 火曜日

地方拠点の一つ、九州支社に所属しています。サーバ・ストレージを中心としたSI業務に携わってましたが、現在は技術探索・深堀業務を中心に対応しています。 2018年に難病を患ったことにより、定期的に入退院を繰り返しつつ、2023年には男性更年期障害の発症をきっかけに、トランスジェンダーとしての道を歩み始めてます。

Related
関連記事