見出し画像

非エンジニアによるコードを使わないLangChain メモ

なぜ書いたのか


2024 年 5 月現在、AI 界隈の技術的進化が筆舌に尽くしがたいほど早い。情報を追うのに必死だ。そんな中、某所で薦めてもらった田村 悠さん著「LangChain 完全入門」を読んでみた。

せっかく本を読んだので、定着のためにアウトプットしたいと思う。

自分はプログラミングを勉強したことはあるが(古くは Basicマガジンや MSX マガジンの写経などもよくしてた)、何かを作ろうと思って作ったことは無く、いわゆる非エンジニアだ。
AI 界隈ではノーコードツールが流行っていて、非エンジニアの方でもものすごい勢いでアプリを開発しているように見える。
LangChain という言葉はそんな非エンジニアの方々も気になっているワードのはずだ。そう、LangChain という響きがカッコよくて耳に残っているはずだ。
巷には技術的な記事は溢れかえっている。せっかくなら少しだけでもオリジナリティを、ということで、コードを一切出さない非エンジニア目線で LangChain についてのメモを書いてみる。ほぼ備忘録。

※こちらの本は2023年10月に出版されていますが、AI 界隈はスピードが早すぎて、ライブラリに破壊的更新があったらしく、すでにコードは動かないものが多かったです。(著者の Github から動作する環境に出来ます)
自分も途中で諦めて、概念の理解にとどめました。こちらの note で今の環境で動くようにコードを直してる方がいましたのでどうぞ!

LangChain とは


LangChain とは、LLM(大規模言語モデル)を活用したアプリケーションを作成するための各種ツールやモジュールを提供するフレームワーク。

もう少しわかりやすく言うと、
LangChainは、『LLM を使ったアプリを作るための便利な道具 6 点セット』。
その便利道具 6 点とは、

  1. Model I/O

  2. Retrieval

  3. Memory

  4. Chains

  5. Agents

  6. Callbacks

という 6 つのモジュールのこと。
6つのモジュールをそれぞれ見ていく。

1.  基本モジュール「Model I/O」

Model I/O は LangChain で最も基本的なモジュールで、言語モデルを呼び出す機能を持つ。

Language Models, Prompts, Output Parsers の3つのサブモジュールから構成される。

Language Models ・・・どの言語モデルでも統一されたインターフェースで使えるようにする。これがないと、Open AI の時は Open AI 用の、Anthropic の時は Anthropic 用の命令と使い分けないといけない。

Prompts ・・・テンプレートを扱いやすくする。

Output Parser・・・言語モデルからの出力を構造化したりする。データとして扱いやすくするために、例えば日時の出力を「2020−09−22 00:00:00」と言った形式に固定したり出来る。

2. RAG の R 「Retrieval」

出ました Retrieval。
LLM を社内業務で使うときによく聞く 「RAG」 = Retrieval Augmented Generation の「R」 。
LLM は大変博識だが、一般的に公開されていない情報について答えることは出来ない。
そこを以下のような RAG という仕組みを使ってカバーする。

1)ユーザからの質問を受け取る
2)用意してある文書から回答に必要な部分を探す
3)文書の関連する部分と質問を組み合わせてプロンプトを作成する
4)作成したプロンプトで言語モデルに回答を作ってもらう

具体的に例示すると、
1)ユーザから「はまーさんが好きなものはなんですか?」という問いを受け取る。
2)指定された文書から「はまーさんが好きなものはゲームです」という文書を見つける。
3)2)で得られた文書から、以下のようなプロンプトを作る。

はまーさんが好きなものはなんですか?という問いに対して以下の文を参考に回答してください。
======
『はまーさんが好きなものはゲームです。』

4)「はまーさんが好きなものはゲームです。」と回答をもらう
というような流れ。

なので、答えられて当たり前というか、圧倒的に2)が大事ということがわかる。
どうやってその文章探すねん!と思うけど、テキストをベクトル化して似たものを探す、という方法。
テキストのベクトル化とは、言葉や文章の”意味”を数値化(配列化)するみたいな感じで、 Open AI の ada というテキスト化モデルでは 1536次元の配列をもったベクトルに変換する。
次元と聞くと2次元や3次元をイメージしてしまい、人間の頭じゃ想像不可能やんけ、と思ってしまうが、単純に属性情報が1536個ある、みたいなイメージ。

そしてベクトル化した同士のテキストは近いかどうかで意味が似ているかどうかを判定出来る。人間とゴリラとバナナだったら、人間とゴリラが近い、みたいな。ベクトルの数値的にも近い。その「意味の近さ」を測る計算方法を「コサイン類似度」と言い、1に近いほど似ている。
もとの質問と、指定された文書からコサイン類似度が1に近いものを探す、というのが上記の2)となる。

2)では、「指定された文書」と書いているが、長い文章では LLM で扱えるサイズを超えている場合があるので、その場合は適切な長さに分ける必要がある。この適切に分けたものを「チャンク」と言う。このチャンクの切り方とかメタデータの込め方とかノウハウがあるのかなぁと思っている。

というか、この場合 LLM は最後の回答文を作文しているだけで、ベクトル化と検索の仕組みがキモということになる。

※でももう、LLM の進化でコンテクストウィンドウが拡張されたら全文つっこめるようになって RAG は要らなくなってくるのか?まぁでもトークン節約で必要か、、。

3. 一問一答で終わらせない 「Memory」

Memory は会話の履歴を保存するモジュール。
これまで紹介してきた機能は、すべて単発。1回のキャッチボールが前提。
この機能があって初めて、履歴を含めた会話が成り立つ。
例えば、ある質問に答えてもらったあとに、その回答を英訳して、と言ったことが出来るのもこの Memory のおかげ。

しかし、ここでふと思った。え、履歴って全部送ってるの?と。会話単位のセッションの履歴を保持してて、サーバー側でもってるんじゃないの?
普段使いの Chat GPT ならまだしも、API 使ってたらトークン数がえらいことになるやないか、と。
また、長過ぎる履歴は要約しているという工夫を初めて知った。コンテキストウィンドウを超えると削除されると思っていたけど、履歴を要約してるんだね。だからすごく詳細なことは忘れてるんだなということがわかった。

4. 複数処理をまとめる 「Chains」

複数の処理をまとめることが出来るモジュール。。
例)LLMRequestChain・・・1)与えられたURLへアクセスし、2)情報を取得する
というような。
上の LLMRequestChain で Web から取得した情報を要約して、さらにその情報を別の Chains を使って処理する、といったことも可能。
Chains をまとめる Chains。つよい。

なるほど、GPTs を一つの Chains みたいなものと考えると GPTs から他のGPTsをメンションできるようなものってことかな?なんかこの LLMRequestChain は Chains っていうより Agents な気がするが、、。

また、Chains は目的別に大量に用意されているとのこと。 計算を間違えないように、Python コードを書かせる LLMMathChain、ハルシネーションを防ぐために、結果を別の言語モデルに投げる LLMCheckerChain 等。

5. 自律的に行動する 「Agents」

外部に干渉しつつ自律的に行動できる Agents モジュール。

Tool と Agents に分かれる。

Tool は文字通り道具で、インターネット上に公開された Web や API から情報を取ってくる Requests、PC 内のファイル操作をする File System Tools、Web 検索をする SerpAPI などがある。

Agents の方は、ユーザーからタスクを受け取ったあと、自律的に Tool を選んで実行し、ちゃんと指示されたタスクが達成出来ているか検証する(!)とのこと。有能すぎる。
こういう手法を ReACT というらしい。プロンプトエンジニアリングでよく耳にする。

改めて冷静に考えると、自然言語で、「〇〇を調べてXXに書き込んで」、という命令をコンピュータが解釈して、Requests というツールと File System Tools を使って勝手に実行する、ってすごいことだ。自然言語プログラミングは、やりたいことを解釈してくれる、という点で従来のプログラミングとは一線を画すと思った。これまでのプログラムは意図は組んでくれなかったからね。知ったかだけど。

ちなみに Tool は自作可能。Toolkit と呼ばれる特定のユースケースに特化した Tool をまとめたものもある。(GmailToolkit など)
しかし、Tool を与え過ぎたら暴走したときに怖いなと思った。(本の中でも使わないのは毎回削除してた)

6. ログ出力する 「Callbacks」

Callbacks は、イベント発生時に特定の処理を実行する機能。他のモジュールと組み合わせが前提。
主にログの出力などに使われるが、特定のアプリケーションと連携し、状況を確認したり出来る。
Callbacks は初期化タイミングと実行タイミングで設定出来る。

ということで、LangChain 6 つのモジュールについて見ていった。

最後に


全体を通して、よく聞く RAG の仕組みがわかったのと、最終的には単なる会話から一歩進んだ AI エージェントを作るための Agents が大事だな、という感想。書籍はコードをわかりやすく追えてわかりやすく、良著でした!

しかし、やはり読み終えた今時点でも LangChain を用いたコーディングで開発なんて出来る気がしない。Dify などのノーコードツールでなら何かしら作れそうなのでトライしたい。そのとき、これは LangChain のこのモジュールがもとになってるな、等意識できそう。

以上、読んでいただいた方ありがとうございました!
今後も何かしらアウトプットしていきたいと思っています。
Dify か、Create か、「その仕事、AI エージェントがやっておきました。」のまとめとかかなぁ。

この記事が気に入ったらサポートをしてみませんか?