日本語文のベクトル化と、ベクトルDB Chromaへの登録・検索をローカル環境で実行する

はじめに

このごろ多様なベクトルデータベースが開発されていますが、これまで扱ったことも基本的なことも知らないままでした。

そこで日本語の処理を念頭にして調査のうえ、実際に手を動かして扱いを確認しました。

この記事は、高い性能を示した日本語文埋め込みモデル(cl-nagoya/sup-simcse-ja-base)を用いて日本語文をベクトル化し、Chromaデータベースに登録して検索を行うまでの一連の作業メモです。

調査

日本語文のベクトル化について

日本語文をベクトル化することで、類似文の検索や自然言語処理タスクに利用できます。多くのモデルが利用可能ですが、本記事ではローカル環境で動作する「cl-nagoya/sup-simcse-ja-base」を選びました。これは、APIを介さずにローカルで動作するため、データプライバシーの観点からも有利です。

参考: Japanese Simple-SimCSE

文章のチャンク化について

文章をベクトル化する前に、適切なチャンクに分割する必要があります。今回は適当にLLMのトークン処理設定を目安に最大384文字でチャンク化しました。

参考: Q&Aチャットボット高品質化への道

日本語文の区切りについて

今回は単純に改行区切りで処理をしました。

場合によっては、文章の区切りを自動的に判別する必要があります。GiNZAやja-sentence-segmenterを使用することで、より精度の高いチャンク化が可能でしょう。

参考: 日本語の文章をいい感じに文区切りするライブラリを作った


日本語文章の準備

今回は青空文庫のデータを使用します。以下のコードで、作家一人分のデータを取得し、前処理を行います。

前処理の具体的な手順は、参考の記事を見てください。

参考: Pythonで青空文庫データを自然言語処理向けにさくっと一括テキスト整形+前処理

なお、記事中にあるsvnを使用してのダウンロードはうまくいきませんでした。 そのため https://download-directory.github.io/ を利用しました。


Chromaへの登録

以下は、Chromaに日本語文を登録するためのコード例です。基本的な手順は公式のドキュメントの通りです。

import chromadb
from chromadb.utils import embedding_functions

# データを保存するためのPersistentClientを作成
chroma_client = chromadb.PersistentClient(path="./chroma")

# Sentence Transformerのモデルを指定して、embedding functionを作成
sentence_transformer_ef = embedding_functions.SentenceTransformerEmbeddingFunction(model_name="cl-nagoya/sup-simcse-ja-base")

collection = chroma_client.create_collection(
    name='my_collection',
    embedding_function=sentence_transformer_ef
)

# 日本語文を追加
texts = ["吾輩は猫である。名前はまだ無い。", "どこで生れたかとんと見当がつかぬ。"]
collection.add(
    documents=texts,
    metadatas=[{ title="吾輩は猫である", chunk="1"}, { title="吾輩は猫である", chunk="2"}],
    ids=["id1", "id2"]
)

検索

今回は「宮沢賢治」の作品データをベクトル化しました。以下のクエリテキストに似た文章が含まれるチャンクを検索しました。

クエリ

クエリテキストは賢治が篤く信仰した法華経の一説です。

results = collection.query(
    query_texts=["我れ深く汝等を敬う、敢て軽慢せず、所以は何ん、汝等皆菩薩の道を行じて、当に作仏することを得べし"],
    n_results=3
)
print(results)

結果

{'ids': [['id_2782', 'id_2462', 'id_878']], 'distances': [[130.5767822265625, 138.81564331054688, 183.30587768554688]], 'metadatas': [[{'title': '不軽菩薩\n', 'verse': 1}, {'title': '疾中\n', 'verse': 13}, {'title': 'ビジテリアン大祭\n', 'verse': 46}]], 'embeddings': None, 'documents': [['あらめの衣身にまとひ\n城より城をへめぐりつ\n上慢四衆の人ごとに\n菩薩は礼をなしたまふ\n(省略)', 'われ死して真空に帰するや\nふたゝびわれと感ずるや\n(省略)', '「マットン博士の神学はクリスト教神学である。且つその摂理の解釈に於て少しく遺憾の点のあったことは全く前論士の如くである。然しながら茲に集られたビジテリアン諸氏中約一割の仏教徒のあることを私は知っている。私も又実は仏教徒である。(省略)']], 'uris': None, 'data': None}

クエリテキストに似た文章が含まれるチャンクが結果に返ってきているようです。

ベクトル化文の足し引き

word2vecで有名な「王」−「男」+「女」=「王妃」の足し引きと同じように、ベクトルを足し引きして検索できます。

from sentence_transformers import SentenceTransformer
import numpy as np

model = SentenceTransformer("cl-nagoya/sup-simcse-ja-base")

# 足し引きする文をベクトル化
embedded = model.encode(["我れ深く汝等を敬う、敢て軽慢せず、所以は何ん、汝等皆菩薩の道を行じて、当に作仏することを得べし"])
embedded2 = model.encode(["仏教"])

# numPyで計算
embedding = np.array(embedded) - np.array(embedded2)

# query_embeddingsパラメーターにセットして検索
results = collection.query(query_embeddings=embedding)
print(results)

結果:

{'ids': [['id_1537', 'id_2284', 'id_1519']], 'distances': [[391.4697265625, 404.6991882324219, 413.8621520996094]], 'metadatas': [[{'title': '二十六夜\n', 'verse': 29}, {'title': '二十六夜\n', 'verse': 29}, {'title': '二十六夜\n', 'verse': 11}]], 'embeddings': None, 'documents': [['悪業を以ての故に、更に又諸の悪業を作ると、これは誠に短いながら、強いお語ぢゃ 。先刻人間に恨みを返すとの議があった節、申した如くぢゃ、一の悪業によって一の悪果を見る。(省略)']]}

コード

指定したフォルダ内のテキストファイルを全て登録するスクリプトと、クエリ用のスクリプトです。

gist

ローカル環境でAI翻訳 (NLLB200 Model)

はじめに

Meta AI製のモデルNLLB-200*1を使って、ローカルで翻訳をできるようにした。

Gradioを利用した簡易UIでブラウザーから翻訳できます。

簡易Web UIのウィンドウ

性能

速度はAMD Ryzen 9 5900HX、メモリ32GBで、以下の文章の翻訳に1分くらいです。

Alice was beginning to get very tired of sitting by her sister on the bank, and of having nothing to do: once or twice she had peeped into the book her sister was reading, but it had no pictures or conversations in it, “and what is the use of a book,” thought Alice “without pictures or conversations?”

So she was considering in her own mind (as well as she could, for the hot day made her feel very sleepy and stupid), whether the pleasure of making a daisy-chain would be worth the trouble of getting up and picking the daisies, when suddenly a White Rabbit with pink eyes ran close by her.

The Project Gutenberg eBook of Alice’s Adventures in Wonderland, by Lewis Carroll

翻訳結果

アリスは,銀行で彼女の妹の隣に座って,何もしないことにとても疲れて始めていた:一度か二度彼女は彼女の妹が読んでいた本に覗いて,しかしそれは,その中に写真や会話がなかった,そして,それは何の本の使用ですか,アリスは考えました,写真や会話なしで? 彼女は,彼女の心に考えていたので, (彼女ができたように,暑い日は彼女が非常に眠くて愚かと感じた),ダージーチェーンを作る喜びが立ち上がって,ダージーを拾うのトラブルに価値があるかどうか,突然ピンクの目を持つホワイトラビットが彼女の近くで走ったとき.

まぁ、何となく意味が取れる程度ですね。

実装

ローカル環境でAI翻訳 (NLLB200 Model)

使い方

install.shの手順のあとpython NLLB-200_app.pyして、起動したらブラウザー127.0.0.1:7860*2開きます。

参考

economylife.net

LLMをWindowsローカルマシンで実行し、AMD RX6600Mを使う。(LM Studio, KoboldCpp-rocm)

はじめに

AMD RX6600M GPUを搭載したWindowsマシンで、テキスト生成用途にLLM実行環境を試したときのメモです。

LM Studio、Ollama、KoboldCpp-rocm、AnythingLLMの各ソフトウェアの使用感、GPU動作について紹介します。

結論として、この中ではLM StudioKoboldCpp-rocmAMD RX6600Mを利用して動きました。

モデルについて

LM Studio、KoboldCpp-rocmについては、GGUF形式にしたモデルを読み込みます。

huggingface.co

こちらからMeta-Llama-3-8B-Instruct-Q4_K_Mを読み込ませて使用したところ、一瞬PCが重く感じる場面もありましたが動作しました。

なお自分が触った範囲では、MetaのLlama 3が最も頭が良さそうな回答をしてくれました。(ただし通常の回答は英語)

使用感と利点・欠点

1. LM Studio

LM Studioは、モデルの検索から実行、対話までを一貫して行えるUIを持っています。サーバーとしてバックエンドで使用することも可能です。

これだけで実行に必要な全てが揃い、手間がかかりません。

AMDのBlogでも紹介されています: How to run a Large Language Model (LLM) on your AM... - AMD Community

利点

  • 単体で完結する
  • 一貫したUIで操作が簡単
  • 細かい設定の変更も可能

欠点

  • チャットUI使用時の細かいログが見当たらない
  • AMD RX6600MはOpenCLを使って動く

lmstudio.ai

2. Ollama

OllamaはCLIベースで動作するLLMローカル実行ソフトです。GUIは別途用意する必要があります。多くの実行環境に組み込まれたり、サーバーに使われているようです。

利点

  • モデルのダウンロードと実行が簡単
  • 使用実績が多い

欠点

  • GUIがないため、初心者には敷居が高い
  • AMD RX6600Mで動作しない(ROCmライブラリ未対応)

なお、バージョン0.2.23で動作します。

ollama.com

3. KoboldCpp-rocm

KoboldCpp-rocmは、紹介する中で唯一AMD RX6600Mを使って動きました。細かい設定が可能で、また特徴的な使い方があります。

KoboldCppのROCmライブラリ対応版です。

利点

  • AMD RX6600Mを利用可能
  • コンテキストやシナリオなどの多様な設定が可能

欠点

  • ドキュメントが少ない
  • UIや用語、動作を理解する必要がある
導入と設定

起動すると設定画面が出ます。

KoboldCppの設定画面

デフォルトから変更したのは以下の通りです。

  • Low VRAMにチェック
  • GPU Layersを32
  • Modelを選択

LowVRAMのチェックを外すと、回答中にAccess Violationで落ちることあります。Context Sizeを小さくすればある程度防げますが、こちらにチェックをしたほうが安定します。

速度は遅くなるようですが、そもそも初回の回答に数十秒(ContextとプロンプトToken数による)、それ以降も10 token/sくらいなので体感としてはあまりわかりませんでした。(それでもCPU動作より速い)

Launchボタンを押すと起動してブラウザーのウィンドウが開きます。

Kobold Liteの画面

Settingsを開き、FormatをInstruct Mode、 Instruct Tag PresetをLlama3 Chatにします。

Kobold LiteのSettings

Contextから毎プロンプトごとに送るMemoryを設定できます。

Kobold LiteのContext設定

あとはメッセージを送れば対話できます。

なお、MemoryやSessionの設定・用語を見るとわかるとおり、Koboldはキャラクターや世界観を保ったままストーリー生成やRPGのセッションを行う目的が強いようです。

Kobold LiteのSession

4. Anything LLM

Anything LLMは、アップした文書を参照させて対話することが特徴です。LM Studioと同様にシンプルなUIです。

バックエンドとしてOllama, LM Studio, KoboldCppやクラウド上のAPI接続など他のシステムが必要です。

AMDのBlogでも紹介されています: How to enable RAG (Retrieval Augmented Generation)... - AMD Community

利点

  • シンプルなUIで簡単にセットアップ可能
  • 文書参照機能
  • LM Studio, KoboldのAPIで動作するのでRX6600Mを利用できる

欠点

  • 細かなモデルごとのプロンプト調整などが難しい
  • UIは一貫しているが、細かい設定はなく長い回答が分割されたりする

useanything.com

まとめ

Windowsローカル環境でAMD RX6600Mを利用したいならLM StudioかKoboldCpp-ROCmを使う。

文書参照をしたいならAnything LLMを使う。

なおLM Studioが一番簡単ではありますがKoboldCppは多様な機能を持っているので、小説生成・シナリオ作成などの用途ではKoboldCppが適しているのではないかと思います。

シンデレラガールズ総選挙結果データをしゃぶりつくすツールを作った

f:id:AOI-CAT:20210718154427p:plain
総選挙結果閲覧ツール

総選挙結果閲覧ツール(別のサイトに移動します)

使い方・説明

ランキング一覧

各選挙の結果を5位ずつ表示します。総選挙結果発表時点で担当声優がいるアイドルはアイコンが付いています。

表示回を選択することで、表示する総選挙結果を変えられます。

Downボタンで次の5順位(冒頭画像の場合は6位~10位)に切り替えます。Upボタンは前の5位(6位~10位を表示している時は1位~5位)に切り替えます。

Resetボタンを押すと、1位~5位の表示に戻します。

なお、過去に2位になっているアイドルは3人をのぞいて1位になっており、なっていないアイドルは、「第2回のアナスタシア」「第4回の前川みく」「第10回の一ノ瀬志希」だけです。

総合ポイント順位

f:id:AOI-CAT:20210718154440p:plain
累積ポイント順位

1位を50pt, 2位を49pt, ...として、選択回までの累計ポイントをランキングにしたグラフです。

圧倒的1位の高垣楓さんと、不動2位の緒方智絵里、それを追う輿水幸子北条加蓮という形が見て取れます。

アイドルのボイス有無割合・属性別アイドル数の割合

f:id:AOI-CAT:20210718154531p:plain
今回の割合表と、各回の割合グラフ

上の表は、選択した回のボイス有りアイドル数と、属性別ランキングアイドル数の表です。

1行目はトップ10のみに注目した表で、2行目は全体の数字です。

下の折れ線グラフは、ボイス付きアイドルと各属性別アイドルのランキング数です。縦軸がランキング数で、横軸が各選挙(左から1回、2回、…)です。

なお、第10回は初めてランク入りしたアイドル全員がボイス付きとなりました。

トップ10各ランクの得票率

f:id:AOI-CAT:20210718154554p:plain
トップ10各ランキングの得票率

各総選挙トップ10の、ランク別得票率です。各回10位までの投票数合計と各順位の票数の割合です。

ポプマスの3人を選ぶツール

2021年3月16日時点の登場アイドルをランダムに3人選んで表示します。

CHANGE!!!ボタンを押すと入れ替えます。 チェックボックスが付いているタイトルのアイドルを選びます。

「タイトル重複をしない」にチェックを入れると、同じタイトルのアイドルは一人までになります。

765はミリオンでもあるけど、765PRO ALLSTARSと765PRO MILLION ALLSTARSとミリオンスターズと39プロジェクトの違いは、知ってる人でもわからなくなるので、わかりやすさ重視でこの表記になりました。

駒形友梨1st Liveの話(今さら脳直Ver)

3rdミニアルバム「a Day」発売記念ミニライブ、無料配信あるよ。

駒形友梨[スケジュール] / TEICHIKU ENTERTAINMENT


f:id:AOI-CAT:20200812162429j:plain

2019年2月10日 Komagata yuri 1st Live ~starting in the 〔CORE〕~ 昼公演に行った日のメモを発掘しました。あまりにも脳から直接出力したみたいでおもしろかったので、その日の楽しかった気持ちをおいておきます。

開幕

ステージの暗がりから現れた駒形さん、衣装かわいい*1

緊張しているような集中しているような闘ってるみたいな、まっすぐな歌声で2曲。アルバムと同じ始まり*2

3曲目でアルバムから曲順を変えて*3、しっとりとした曲が続く。

伸び伸びと歌い上げる姿に笑顔が見える。

みんな予習してるんでしょ、一緒に前奏歌ってとM-4. It's Heaven。もちろん太めのコーラスになる。
この客席にマイクを向けてる時の笑顔はこっちも笑顔になる。

アコースティックパート

ここはシングル「トマレノススメ」から。アルバム中心のセットで、どうシングルを入れるのかなぁと思ってたけど、これは良い。

フォークソング部で、アコースティックには馴染みがあると語る。

続いてシングルのカップリング「Lonely Blueが終わる頃には」。

歌いながら目をつぶり、少しだけ上を見上げてすらりと伸びる首もと、その姿は、駒形友梨のもっとも美しい姿ではないだろうか。

アコギでやるのは(鷲崎さんや学園祭学園ではあるけど)ピアノは初めじゃないかな、と。

後半パート

あまり腕を振り上げるような曲は無いけど、明るい曲もあるからクラップでお願いと、M-7. Talk 2 Night。

このあたりから、歌が好き、歌うのが楽しいという、笑顔がいっぱい。かわいい。

続いてM-8. クロックワイズ。
この曲、軽やかに歌い上げるけど、ムチャクチャ難しいことはわかる。そんなことは感じさせないけど。

M-9. はじめからきっと、これはアルバムでなくて「トマレノススメ」収録曲だけど、初回版に入ってないやつ!*4

そして、筆無精なのに作詞できるかと思ったけど、書いてみて良かったというM-10. 時の葉。

アンコール

アンコール1曲目は 「identity my ultimatum」 Sho from MY FIRST STORY feat. 駒形友梨/ウエノルカ(眩暈SIREN) ゲーム「WOR OF BRAINS」より。
ゴリゴリのメタル曲、強い。

そして「SWHINE!! キラキラ☆プリキュアアラモード」は、プリキュアのお姉さん*5だったことを思い出させる一曲。

次もプリキュアから「Lu La La☆Lumiere」、関連最後のレコーディングだったそう。神々しい曲と語ったとおり、神々しく歌い上げていた。 作曲はミリオンライブ!「永遠の花」ジェミニと同じ三好啓太さん、天才の所業。そこに豪華なことに大森祥子さんの詞。

最後はトマレノススメ。ここがスタートラインという一曲。まさにここからがスタートなんだな。

次のライブ

2020年5月31日に2ndライブが予定されていましたが、中止となってしまいました。

こちらは2ndミニアルバム「Indigo」のときにライブも2ndあるかな!と思ったけどそれはなくて、3rdミニアルバム「a Day」発売になって満を持しての2ndライブ。期待は大きかったのですが、しょうがありませんね。また次を楽しみにしています。

冒頭に書いたとおり、発売記念イベントでミニライブが配信(無料だけどチケットは購入が必要)されるので、お時間ある方はいかがでしょうか。

なお、1stライブの日はそのまま「上坂すみれのノーフューチャーダイアリー2019」に向かい、移動の最中にメモをしたためたのでした。

f:id:AOI-CAT:20190210174855j:plain


上坂すみれ ノーフューチャーバカンス

写真についてはM-4. よっぱらっぴ☆ から


*1:駒形友梨さんは、かわいいよりも美人だっていわれるタイプですが、この日のお衣装は見た瞬間かわいい!でした。

*2:M-1. starting in the haze, M-2. メイズ

*3:M-3. ソノヒ、アルバムではM-6

*4:このことに今さら気付いて配信で購入しました。

*5:歌い方がまさしく「歌のお姉さん」になる

100均グッズで壁掛け写真・ポスタークリップをDIY

f:id:AOI-CAT:20200519195559j:plain
DIYした壁掛けクリップでディスプレイ

デカジャケットや生写真、特典アイテムがとかく集まりがちな生活を送っています。

せっかくだからイイ感じにディスプレイしたくて、100均で買える材料でお手軽に「クラフト調壁掛けクリップ」を作りました。

材料は3つ(計300円)、手順も3つで簡単だったので、作り方をメモしておきます。

材料

材料

  • ペーパーストロー(クラフト)
  • ワックスひも
  • ウッドピンチ

ひもは、ピンチの中心に通せる太さのものにしましょう。

ひもを引っかけて使うので、無ければフックなどを買っておきましょう。

作り方

その1

f:id:AOI-CAT:20200518184847j:plain
ピンチにひもを通します

ピンチは生写真なら3枚がギリギリだったので、多くても3つにしました。

その2

f:id:AOI-CAT:20200518193554j:plain
ストローにひもを通します

ここは、あまり緩くても移動してしまうし、きついと動かしづらいので調整が必要です。写真のものは結び目をつけて隙間を確保した上で、ひもが真っ直ぐに張るようにして結びました。(作り方 その3の写真)

その3

f:id:AOI-CAT:20200518201343j:plain
ひもを上で結んで完成です

クリップを掛けるために通す2本目のひもは、ストローの長さの3倍ちょっとは確保するとちょうど良いと思います。

結ぶときは長さを調整できる結び方にすると便利です。

さいごに

あとは壁のフックに引っかけるだけです。最近は、少し凹凸のある壁でも貼って剥がせるタイプのフックがあるのでフック設置の自由度が上がっています。これも3個セットで100均にあったので買ってきて、今回使いました。

お気に入りの写真やジャケットが飾ってあるとQOLが上がりますね。

なお写真にあるメガジャケットは、Amazon.co.jp限定版(値段は同じ、というか通常版も割引なし)で買える。

THE IDOLM@STER SHINY COLORSの絵についての評判はご存じかと思いますがジャケットに至っても同様で、この大きさで手もとに置いて飽かずに眺められます、通販はヨドバシを使いたいけどメガジャケットがあるからAmazonにしてしまう程度に。


【Amazon.co.jp限定】THE IDOLM@STER SHINY COLORS GR@DATE WING 02 (デカジャケット付) 限定版