イントロダクション
恥ずかしながら、RAGという仕組みを最近まで知りませんでした。
自然言語処理を研究していたはずですが、ここ何年かキャッチアップしておらず知らなかったんですね。
fasttextすらも知らなかったぐらいなので、なんだか世間から遅れてしまった化石のような感じなり恥ずかしいハメに。
ということで、GPTなんか使って実装して確認してみたい・・・と思ったんですけどあまり金をかけたくない。
そこで、RTX4070を装備したマシンがあるのでローカルLLMとやらでもできるんじゃね?
と思って「ELYZA-japanese-Llama-2-7b」というものを利用して実装しようと考えたわけです。
Gemini先輩にきいて、知ったのですが(笑)日本語にも強くて無料で使えるものってことで検索しました。
パイセンに聞くとLangChainっていう便利なライブラリもあるようなのでこれを活用することにしました。
ベクトルデータを保存するDBがあるってことしらずに、numpyでダンプ保存してロードしてたのですが
chromadbっていう便利なものがあるそうなのでそちらも使いました。
なんだよ、早く行ってよ~って思いましたが知らない自分が悪いのです。
周りに知ってる人がいないのも辛いところ(笑)
いざテスト
from framework.llm_lapper import llm_lapper
def run_rag_system():
"""RAGシステムを実行するメイン関数"""
# データベースのセットアップ
docs_directory = "Docs"
# LLMの初期化
model_path = "models/ELYZA-japanese-Llama-2-7b-instruct-q4_K_M.gguf"
try:
rag_lib = llm_lapper(model_path=model_path)
except Exception as e:
print(f"LLMの初期化中にエラーが発生しました: {e}")
return
rag_lib.train_text_files(docs_directory=docs_directory)
# メインループ
while True:
user_input = input("質問を入力してください(終了するには 'exit' と入力):")
if user_input.lower() == 'exit':
break
try:
# 関連ドキュメントの検索 (Retrieval)
# 複数の結果を取得するようにn_resultsを3に設定
result_text = rag_lib.query(query_text=user_input, n_results=3, threshold=0.6)
print(result_text)
except Exception as e:
print("エラーが発生しました:", e)
# スクリプト実行
if __name__ == "__main__":
run_rag_system()
こんな感じでテストコード書いて実験
いきなりソースコードがあってあれだけど、さっくり動かしてみました。
RAGを動かす上でGeminiパイセンっていうでっかいLLMの助けを借り、Clineでgrokパイセンも借り
粗削りなコード作ってもらった後に、人間がシコシコと丁寧にバリ取りというか整えてできあがり
って感じでできました。
簡単な仕組みとしてはRAGは拡張辞書みたいなものと考えたほうがいいです。
LLMに学習させていない情報を問い合わせ時にアタッチして答えを生成して貰うってイメージです。
結局、その質問文に対してのデータ検索は自力でロジックを実装する必要があるところが
やっぱりなってところです。
実行して思ったのは、今チャットボット作るんだったらこれでいいじゃんって思ったんです。
社内チャットボットとか全然いいっすね。
今までは自力でカンバセーションツリーを作ってゴチャゴチャしてやってた数年前が懐かしい。
いや拷問でした。
frameworkってのは私が作ったライブラリなので世間一般には御座いませんので誤解なきよう(;'∀')
欲しい人がいれば公開するかもしれません。
感想というか注意点
適当にテキストファイルをぶっこんでベクトル化して質問文いれても最初の検索で大体スコアが悪いこと。
当たり前ですが、テキストファイル全体を学習させてその中に含まれる一部分がマッチしても
質問文は短いのでマッチさせるベクトル情報が少ないお陰でスコアが足りなくなるという点。
このあたりは何らかの工夫が必要ですね。
特定部分のみマッチさせて取り出すってのも有効かもしれません。
勿論、テキストファイルだけではなく、イメージデータやwordやエクセルなどのofficeデータも
テキストやイメージ抽出して検出するってこともできます。(ベクトル化してそれを検索するだけですので。)
勿論工夫が必要ですが、以前よりは全然楽ですね。