まだプログラマーですが何か?

プログラマーネタ中心。たまに作成したウェブサービス関連の話も https://twitter.com/dotnsf

2025/01

ブロードコム社による VMWare のライセンス変更の影響もあって、なんとなく「仮想環境として VMWare を選びにくい」心理になっているのは自分だけじゃないと思ってます。事実、自分は昨年のプロジェクトにおける検証環境として仮想環境が必要だったのですが、自社も扱っている VMWare を選ぶことに躊躇して、結局使いませんでした。。

問題は「VMWare を使わないとして、じゃあ何を使う?」です。もちろん VMWare の便利さ(複数サーバーで1つの環境を構築できるのはリソース管理の視点で便利ですよね)も理解しているし、「使う側の慣れ(別の環境だと慣れるまでが不安)」の問題もあるので、なんでもいいというわけにはいかないことは理解しています。

そこまで理解した上で、自分は昨年1年間を通じて Oracle の VirtualBox を使う機会が数度ありました。もともと個人所有の(PC-DOS や OS/2 資産を残しておくための)仮想環境として使っていたこともあったのですが、単に「VM を起動するだけ」の使い方しかしていませんでした(ネットワーク周りなどは全然・・)。そんな自分も業務を通じて1年間使ってきたこともあり、ある程度理解が深まったと思うので、今年はそのアウトプットを行っていこうと思います:
2025012101


まず最初は「VirtualBox 内で VPC(Virtual Private Cloud) っぽい環境を作る」手順を数度に分けて紹介していこうと考えています。VPN などで外部からアクセスできるような所までは想定しませんが、原則的にはインターネット接続のない閉じたネットワークを作って、その上で複数の VM を動かしたり、インターネット接続のためのルータを作った上でデフォルトゲートウェイとして指定することでアウトバウント・インターネット接続を実現する、といった内容を紹介していく予定です。

というわけで、今回は VirtualBox でインターネット接続のないネットワークを作って、その中で VM を動かすまでの手順を紹介します。


【VirtualBox で外部とは繋がらないネットワークに VM を配置する】
まず VirtualBox のネットワークにはどんな種類があるのか調べてみます。適当な VM を選択して設定を開き、ネットワーク項目を確認します。有効化されているアダプターを見つけ(あるいは適当なアダプターを選んで有効化し)、割り当てボックスを開きます:
2025013101


私の環境は VirtualBox 7.0.12 なのですが、その場合はこのような選択肢が表示されました。これだけの種類のネットワークがあり、VirtualBox で指定できます:
2025013102


「NAT」や「ブリッジアダプター」は比較的わかりやすいのではないかと思ってます(ホスト PC がインターネットに繋がっていれば、どちらも外部接続可能です)。外部につながらないネットワークという意味では「内部ネットワーク」と「ホストオンリーアダプター」がありますが、後者はどちらかというと単体、他の VM との通信を行うネットワークに接続させたい場合は前者の「内部ネットワーク」を選択することになるようです。

「内部ネットワーク」を選ぶと、画面はこのようになります:
2025013103


この「名前」の値(上図では "intnet" となっている部分)が「内部ネットワークの名前」に相当するもので、デフォルト値は "intnet" です。複数の VM が同じ名前の内部ネットワークに接続されたアダプターを持っていれば、それらの VM は(同じネットワークアドレスの IP アドレスが割り当てられていれば)通信できることになります。2つ以上の異なる内部ネットワークを定義したい場合は、この "intnet" と書かれている部分を別の名前に書き換えることで「別のネットワーク」扱いになり、通信はできなくなります。

というわけで、VirtualBox で外部に繋がらないネットワーク上に VM を配置したい場合はネットワークアダプタの種類を「内部ネットワーク」に指定して VM を作ればよいことになります。

その上で VM を作成・起動し、まずは VirtualBox の OS 内でのネットワークインターフェース名を確認するため、以下のコマンドを入力します:
# nmcli device

この結果、例えばネットワークインターフェース名が eth0 であれば(CentOS や RHEL であれば)以下のような設定を実施します(赤字はコメントです):
# nmcli con add ifname eth0 con-name eth0 type ethernet eth0 をインターフェースとして追加

# nmcli con mod eth0 connection.autoconnect yes OS起動時に自動接続

# nmcli con mod eth0 ipv4.addresses 10.10.0.10/24 IPv4アドレスとネットマスク

# nmcli con mod eth0 ipv4.method manual 手動設定であることを明示

# nmcli con mod eth0 ipv4.dns 10.10.0.10 DNSサーバー

# nmcli con up eth0 ここまでの設定を有効化

これでインターネットには接続できないネットワーク 10.10.0.0/24 内に IP アドレス 10.10.0.10 で接続されたサーバーを作ることができます。

図で示すとこんな感じの VM1 に相当するサーバーを作ることができます:
2025020101


注意が必要な点として、オフライン(インターネット接続がない)なので、インストール時のネットワーク経由でのユーザー登録やサブスクリプション登録もできない、という点です。オフラインインストール方法は OS ごとに異なるはずですが、RHEL 9 の場合は過去に調べてまとめたことがあるので、(超面倒ですが)必要な方はこちらも参照ください:
RHEL 9.x のオフラインインストール


次回はこのエアギャップ(インターネット非接続)ネットワーク上に、インターネットとのデフォルトゲートウェイになるようなルータを構築する手順を紹介する予定です。こちらも図で示すとこちらの VM0 に相当するサーバーを作って、閉域ネットワークである intnet に接続したサーバー(VM1 など)がインターネット接続できるようにします:
2025020102




私自身は日本アイ・ビー・エム社員で、現在はクラウド/コンテナ廻りの技術業務を担当しています。比較的「新しめの技術」に携わっているという自己認識をしています。

一方で、レガシーな技術に興味がないわけではありません。PC-DOS や OS/2 は今でも仮想環境を残して使えるようにしています。

ただ、いわゆる「ホスト」の AS/400 (System i、i5/OS)はこれまで自分に縁のないテーマでした。「CPU やメモリ、ファイルシステムなどのハードウェアリソースは全て OS 内では仮想化されて、実体をほとんど意識することなく使える」とか、「専用のターミナルエミュレータから利用する」という説明を受けて興味は持つのですが、「これまで利用する機会も環境もなかった」というのが正直な所です。

そんな中、無料で AS/400 にアクセスできる環境があることを知り、まずは試してみました。その時の作業記録をブログとして残します。


【PUB400.COM にアカウントを作る】
www.powerbunker.com という所(会社?)が PUB400.COM というオンラインサインアップ可能なパブリック AS/400 を公開していることを知りました。

サインアップするにはウェブブラウザで https://pub400.com/ にアクセスします:
2025011702


トップページに PUB400 の説明やルールなどが記載されています。無償でコミュニティ向けに提供いただいている IBM i 7.5 サーバー環境なので、無茶なことはせず、丁寧に使いましょう。

画面を下までスクロールすると左下に "Sign Up Now!" と書かれたエリアが見つかります。サインアップはここをクリックします:
2025011703


リンク先ページを下までスクロールするとユーザー登録情報を入力するフォームが表示されます。名、姓、メールアドレス(2回)、希望ユーザー名を入力し、最後にユーザー登録する上での取り決めに関する内容に同意するチェックボックスにチェックを入れて Submit します。

なお、登録可能なメールアドレスの種類について、outlook や gmail 、hotmail といったフリーメールだと確認メールが届かない問題がある、と書かれている模様です(詳しくは不明)。この辺り注意してメールアドレスを指定してください:
2025011704


正しく PUB400 からの確認メールが受信できた場合、以下のようなメールが届くはずです(経験的にはすぐではなく、少し時間が経って届きました)。確認のため、メール内に書かれたリンク(赤枠)部をクリックします:
2025011705


ここまでの作業が全て正しく処理されるとユーザーが作成され、更に少し待つと PUB400 から以下のようなユーザープロファイル(赤枠部は初期パスワード)を報告するメールが届きます:
2025011706


これで PUB400 内の AS/400 にアカウントを作ることができました。


【5250 エミュレータをインストールする】
アカウントが作れたので早速ログインを・・・と考えてしまうのですが、AS/400 はログイン前にもう1ステップ必要です。それが 5250 接続するための準備です。

この PUB400 では SSH でログインする方法も提供されていて、それはそれで意味があるとは思っていますが、せっかく AS/400 のアカウントがあるなら AS/400 ネイティブな方法でログインしたいものです。それには 5250 と呼ばれるターミナル(現実的にはターミナルのエミュレーター)が必要です。

過去に AS/400 にアクセスしたことがある人であれば、IBM PCOMM などの 5250 エミュレーターを所有しているかもしれませんが、そこまで一般的ではないと思うので、ここではオープンソースの 5250 エミュレーター製品である tn5250 をビルドして使う方法を紹介します。

私自身は普段 Windows を使っています。Windows ユーザーの場合は WSL2 の Ubuntu を有効にするなどして Linux が使える環境を用意してください。Mac ユーザーや Linux ユーザー(ラズパイ含む)は同様に利用できると思います(が、以下で紹介する手順は Ubuntu など Debian ベースの Linux を想定したものになっている点にご注意を)。

まずは Ubuntu 環境にビルドに必要なツール類をまとめてインストールしておきます。ターミナルを開いて以下を実行します:
$ sudo apt install autoconf automake libtool


tn5250 を利用するにはソースコードからビルドする必要があります。ターミナル内で以下の手順を順次実行します:
$ git clone https://github.com/tn5250/tn5250

$ cd tn5250

$ ./autogen.sh

$ ./configure

$ make

$ sudo make install


ターミナルを一度終了して、再度起動することで tn5250 が使えるようになります。


【5250 エミュレータで PUB400 の AS/400 にアクセスする】
実際に PUB400 の AS/400 にアクセスするには以下のコマンドを実行します:
$ tn5250 pub400.com

すると tn5250 が起動して PUB400 に接続します。AS/400(正確には IBM i 7.5)のログイン画面が表示されているので、PUB400 にサインアップした時のユーザー名と初期パスワードでログインします。ちなみにユーザー名のフィールドからパスワードのフィールドに移るには TAB キーを使います(初回のみログイン直後にパスワードを更新する必要があります):
2025011801


ログインが成功すると AS/400 のメインメニュー画面が表示されます。が、ここから何を選ぶと何ができるのか、実はよくわかっていません。。これからこの環境で勉強します:
2025011602


ターミナル内で実行している tn5250 を終了するには Ctrl + Q です。これで元の(WSL などの)ターミナルに戻れます。

なお上でも少し触れましたが、PUB400 は SSH でログインすることも可能です。ホスト名は pub400.com 、ただしポート番号は 22 ではなく 2222 を指定して接続する必要があります。ユーザー名とパスワードは 5250 接続時と共通です:
2025011802


接続できるとプロンプトが表示されます。一般的な Linux 環境と比較して使えないコマンドも結構ありますが、UNIX/Linux に慣れた人であればある程度使いやすいのではないかと思います:
2025011803


この環境には Node.js v18 も導入されていました。Node.js のプログラミングはこの環境でできそうです:
2025011804


SSH は慣れているぶん使いやすいけど、せっかくの 5250 接続環境なのでネイティブな AS/400 の勉強もできる環境として使わせていただきます。RPG のプログラミングなどはできそうなので、生成 AI で RPG のコードを作ってもらって、この環境で実行、みたいな使い方もできるかな。

Techcrunch の記事によると、3D スキャンデータの販売を行っている Triplegangers というサイトが ChatGPT のサービスを公開している OpenAI のウェブクローラーのクローリング(スクレイピング)が原因で DDoS 攻撃を受けているかのような状態になり、サイトダウンを引き起こしていた可能性がある、と発表されていました:
https://techcrunch.com/2025/01/10/how-openais-bot-crushed-this-seven-person-companys-web-site-like-a-ddos-attack/

記事によると原因となったスクレイピングボットはサイト全体から数十万枚にも及ぶ画像データを全てダウンロードしようとしていた形跡があり、その結果サイトがダウンしてしまった、らしいです。ウェブアプリケーション/ウェブサービスを運用する立場としても他人事ではなく、怖いニュースです。。。

この件に関しては、Triplegangers 側は「事前承諾なしにサイトデータのスクレイピングを禁じる」旨を記載していたようです。が、Techcrunch は「ウェブ上の記載のみで robots.txt の設定は不充分だった」とも指摘している一方、「そもそも robots.txt も(紳士協定が守られる保証はないので)絶対ではない」とも指摘していて、絶対的な回避方法や情報が提供されているわけではありませんでした。

たしかに robots.txt はウェブクローラーに対して「参照していいページ/しないでほしいページ」を指定する方法ではあるのですが、あくまで紳士協定であって、その協定というかルールを守らないクローラーがないとは言いきれません。特に最近は LLM の学習データをウェブから集めようと試みる人が少なくないことが想像できるので、普通のウェブサイトがいつの間にか学習データ提供元になっていたり、今回のような大量のスクレイピング実行されたり(※今回記事になった例ではスクレイピング時に数百もの異なる IP アドレスが使われていたらしく、悪意がなくても悪質なスクレイピングであったと感じています)するとサイトダウンを引き起こしかねないこともあって、小規模な個人サイトであっても気になってしまうものでした。現に生成 AI 検索エンジンの1つである Perplexity のクローラーは過去に robots.txt を無視していたと指摘されている前科もあって、いつ他人事でなくなるかもわかりません。

そこで「robots.txt の指示を守らないクローラーがやってくる前提で、クローラーボットによるインデックシング/スクレイピングをウェブアプリケーションで拒否する」方法を考え、サンプルを作って公開してみました。


【サンプル】
Node.js で作ったサンプルはこちらです:
https://github.com/dotnsf/block-llm-bots

"git clone" などでダウンロードすると、app.jsblock_llm_bots.js という2つの JavaScript ファイルがあることが分かります。アプリケーションとしてクローラーを拒否するモジュールは後者で、前者はそれを組み込んだサンプルとなっています。以下は app.js のコードです:
(app.js)
//. app.js
var express = require( 'express' ),
    app = express();

app.use( express.Router() );

//. LLM クローラーボットブロックを有効にする
app.use( require( './block_llm_bots' ) );

//. .env 内に記載された UserAgent からのリクエストだとこの処理は実行されない
app.get( '/', function( req, res ){
  res.contentType( 'application/json; charset=utf-8' );
  res.write( JSON.stringify( { status: true }, null, 2 ) );
  res.end();
});

var port = process.env.PORT || 8080;
app.listen( port );
console.log( "server starting on " + port + " ..." );

黒字部分がオリジナルのウェブアプリケーションで、赤字部分がそのウェブアプリケーションにクローラー拒否のモジュールを組み込んでいる1行です(緑字はコメント部です)。block_llm_bots.js が同じディレクトリ上にあれば、この1行だけでクローラーブロックが有効になります。

ブロック対象とするクローラーの(UserAgent の)種類を環境変数 BLOCK_BOTS に(複数の場合はカンマ区切りで)指定します。サンプルでは .env ファイル内で以下のように指定されています:
# ブロックしたいボットの UserAgent をコンマ区切りで羅列する
BLOCK_BOTS=PerplexityBot,GPTBot,ChatGPT-User,OAI-SearchBot,Google-Extended

この例では "PerplexityBot,GPTBot,ChatGPT-User,OAI-SearchBot,Google-Extended" と指定されています。この指定で Perplexity(PerplexityBot), OpenAI(GPTBot, ChatGPT-User, OAI-SearchBot), Google(Google-Extended) の3か所の LLM クローラーからのアクセスを拒否しています。

このサンプル(app.js)を使って試しに動作確認してみましょう。Node.js が導入された環境でこのファイル一式をダウンロードし、依存ライブラリをインストールします:
$ npm install

そして(必要に応じて .env ファイルを編集して拒否するクローラーの種類を変更した上で)アプリケーションを起動します:
$ npm start

特に指定しない場合、アプリケーションは 8080 番ポートで HTTP リクエストを待ち受ける状態になります(変更する場合は環境変数 PORT で指定します)。

この状態で(別ウィンドウなどから)curl を使ってアプリケーションにアクセスしてみます:
> curl "http://localhost:8080/"
2025011202


{ "status": true } というアプリケーションの「本来の期待通りの」挙動結果が返ってきました。

では次に OpenAI のクローラーをエミュレートして、User-Agent ヘッダに "GPTBot" を指定してアクセスしてみます:
> curl -H "User-Agent: GPTBot" "http://localhost:8080/"
2025011203


想定通りに GPTBot からのアクセスが遮断された結果、今度は何も表示されませんでした。

この時、サーバー側のコンソールを見ると、"GPTBot" からのアクセスの際にはブロックされた旨が表示されているはずです。期待通りの(特定のボットからのアクセスを遮断するような)挙動が実現できていることが確認できました:

2025011204


このサンプルのように block_llm_bot.js を組み込むか、または同様の拡張をアプリケーションに行うなどして(robots.txt を無視してくるようなクローラーに対しても)スクレイピングを禁止する機能が実現できそうです。自作サービスにも組み込んでおこっと。


とはいえ、本当に悪質な連中だと UserAgent すらも偽装してくるのかなあ、、そういうのはどうするべきなんだろう?


新しい SNS が国内外で色々出てきてますが、その中でも API が充実していて、定期実行 bot とかも(無料会員のまま)使えるのが BlueSky です。最近になってこの BlueSky でも X や facebook のようなシェアボタンを作れることを知りました:
2025010801


方法は以下のエンドポイントとパラメータを指定するだけです:
https://bsky.app/intent/compose?text=(シェアメッセージや URL)

応用として「ボタンをクリックしたら新しいウィンドウが開いて、その画面内でメッセージを編集してシェア」させたい場合は、ボタンのクリックイベントハンドラを以下のように書けば OK です:
<a title="このページを BlueSky でシェア" href="https://bsky.app/intent/compose?text=https://dotnsf.blog.jp/" target="_blank" onclick="window.open(this.href, 'Bskywindow', 'width=650,height=450,menubar=no,toolbar=no,scrollbars=yes'); return false;">
  BlueSky でシェア
</a>

実際に入力するとこんな感じ(↓)になります:

BlueSky でシェア


唐突ですが、拙作の「お絵描き SNS 」である mydoodles も使ってみてください。よろしくお願いします。



前回の続きです:

0:準備編
1:Jupyter Notebook 編
2:LangChain 編 (今回はここ)


最終回の今回は前回までに用意した環境や情報を使って、LangChain と呼ばれる LLM アプリケーション開発フレームワークを watsonx.ai の LLM で実装する方法を紹介します。 なお、ここで紹介した内容とその結果は 2024/12/31 時点でのものである点に留意ください。


【LangChain とは? エージェントとは?】
LangChain とは LLM を使った大規模アプリケーションの作成を簡易化するために用意されたオープンソースのオーケストレーション・フレームワークの1つです。

LLM はその名前(Large Language Model)が指し示すように大規模な言語データによってトレーニングされたモデルで、一般的な文脈の問い合わせには慣れていますが、(トレーニングデータに含まれていない)特定分野に関する情報や最新データに関する文脈への問い合わせは苦手としています。

LangChain はそのような LLM が比較的苦手とするコンテキストに対する問い合わせを補完するものです。様々な機能を持つ AI コンポーネントを「チェーン」と呼ばれる形でつなぎ合わせて最終的な答を導きだす機能を有しています。

そして、この LangChain は多くの場合で「エージェント」と呼ばれる機能とセットで使われます。「エージェント」はその名前が示すように「LLM 実行時に渡されたコンポーネントを用いて、『次にどのようなアクションを取ればよいかを判断し、選択し、実行して、目的を完了するまで繰り返す」という役割を担っています。

例えば次のような問い合わせを行いたいとします:
 「千葉県で一番高い山の高さの平方根の値はいくつですか?」

この問い合わせは(単体の)LLM だけではかなり難題に分類されるものだと想像できます。まず「千葉県で一番高い山(の高さ)」は LLM 作成時のトレーニングデータに含まれていれば答えられるかもしれませんが、含まれていなかった場合は答えられないし、場合によってはここでハルシネーションを起こしてしまいかねない質問です。 またその数値が分かったとして「平方根の値」を求める方法もトレーニング時に含まれていないと計算もできないはずです。そこまで都合よく LLM がトレーニングされているとは限らないわけで、LLM だけで正しい答を導くのは難しいはずなのです。

一方、この答を人間的な考え方で導こうとすると、多くの場合は
(1)まず千葉県で一番高い山を特定し(検索する)、 
(2)その山の高さを求め、
(3)最後にその高さの数値の平方根を計算(数値計算)する

という順序で考えて調べていくことで正解にたどり着こうとするのではないかと思います。

LangChain のエージェントはまさにこの「正解にたどり着くための順序を考える」部分を実施するライブラリです。「検索と数値計算を使って『千葉県で1番高い山の高さの平方根の値はいくつですか?』という問題の正解にたどりつくにはどうすればよいか?」を考え、(1)から(3)の順に実行する、というライブラリです。 

今回はこの LangChain のエージェント機能を watsonx.ai で使う例を紹介します。


【Jupyter Notebook で watsonx.ai の LangChain とエージェント機能を利用する】
前回同様に IBM Cloud 環境に用意した Jupyter Notebook 機能にアクセスし、編集状態にします。

まず最初に、これは私自身が色々試した範囲内での体感的な感想ではあるのですが、この LangChain やエージェントを実行する段階においては LLM として llama ベースのものを使うのが期待通りの結果になることが多い印象があります。というわけで、先頭セルの内容を編集し、利用する LLM を "meta-llama/llama-3-2-11b-vision-instruct" と変更します※:
2024123117

MODEL_ID の値を "ibm/granite-8b-japanese" から "meta-llama/llama-3-2-11b-vision-instruct" に変更します


なお、この状態で(MODEL_ID の値を変えた状態で)前回のコードを使ってこの質問を LLM にそのまま問い合わせた時の結果はこちらです。質問の意味を理解できていないかのような回答が最大トークンぶん繰り返されていたような結果になりました。やはり素の LLM には難問のようでした:
2025010300



改めて、次に前回までに作成した内容の下に1つセルを追加し、以下の内容を記載します(ここでは1行だけです):
pip install google-search-results

この1行は、この下のセルで初回に紹介したウェブ検索 API である SerpAPI を使うのですが、そのためのライブラリをインストールするコマンドです。

続けて更にセルを追加し、以下の内容を記載します。まずは最初のセルで初期化した変数 SERPAPI_API_KEY を使って、この値を環境変数化しています。そして前回作成した言語モデル custom_llm に対して、「ウェブ検索と数値演算を併用」してプロンプトに対する答を自律的に考えて求めるよう指示しています(具体的な検索方法や計算アルゴリズムは一切指示していない点に注目してください):
# LangChain Agent で watsonx.ai を使った問い合わせ
from langchain.agents import AgentType, initialize_agent
from langchain_community.agent_toolkits.load_tools import load_tools

import os
os.environ["SERPAPI_API_KEY"] = SERPAPI_API_KEY

# 2つ上で定義した custom_llm を使う
# custom_llm = WatsonxLLM(model=model)

# LLM(watsonx.ai)と serpapi(ウェブ検索)と llm-math(数値演算)を使って問い合わせの答を求める
tools = load_tools( ["serpapi", "llm-math" ], llm = custom_llm )
agent = initialize_agent( tools, custom_llm, agent = AgentType.ZERO_SHOT_REACT_DESCRIPTION, verbose = True, handle_parsing_errors = True )

r = agent.invoke( "千葉県で一番高い山の高さの平方根の値はいくつですか?" )
print( r )

2024123118
(↑この2つのセルとその内容を追加します)


ここで追加した内容は前回までに実装した custom_llm というモデルと、ウェブ検索ライブラリ("serpapi")と、数値計算ライブラリ("llm-math")を使って、「千葉県で一番高い山の高さの平方根の値はいくつですか?」という問い合わせを行う内容が記載されています。内容を見て分かるとおり、具体的にどのような思考順序で答えるべきか、といった情報はコード内には一切書かれておらず、そのあたりがエージェントに任されて、ただ問い合わせ内容だけが記載されていることがわかると思います。

では実際にこのコードを実行します。変数定義からやり直す必要があるので前回作った一番上のセルから順にセルを実行していきます(新たに指定した言語モデルで custom_llm 変数がインスタンス化されます)。

前回最後に実行したセルまで実行できたら、次は今回入力した新しい部分を実行します。まずは "pip install google-search-results" だけの行を実行します。以下のような "google-search-results" ライブラリがインストールされていく様子が出力されていきます:
2024123113


では最後のセルも実行します。実行すると元の質問文の内容をどのように解釈して、どのような順序で回答を求めていくかの様子も含めて出力されていくのがわかります:
2024123115


この質問に答えるには、まず千葉県で最も高い山を調べる必要があり、(ここで SerpAPI の検索 API を使って)それが愛宕山の 408m であることがわかり、その上でこの値の平方根を(llm-math という数値演算ライブラリを使って)求めて、、という経過を経ていることがわかりますね。


2024123116


最後は出力が途中で切れてしまいましたが、上図の青枠部分を見ると問い合わせに対する回答である 20.396.. という数字を得ることができています。こういった「どのようなライブラリや API を使う準備ができているのかを理解した上で、最終的に求められている答を求めるためのアプローチ方法から LLM が調べていく、、というより人間的な方法で問い合わせに対する回答を得ることができました。これがLLM の(LangChain の)エージェント機能と呼ばれるものです。

watsonx.ai でも無事に LangChain やエージェント機能を利用できることが確認できました。






このページのトップヘ