もし後輩に「生成AIがプログラムを扱えて何が嬉しいんですか」と聞かれたら(前編)

記事タイトルとURLをコピーする

出てきた当初は正直どう使うと嬉しいかが具体的にはわからなかったAgents for Amazon Bedrockのような機能の今日的な意義について、改めて考えてみるエッセイの前編となります

なお、Agents for Amazon Bedrockって何だっけ?という方は、 弊社村上のわかりやすいブログ があるので、そちらをまずは一読いただいてから本稿をお読みいただくと、より話が頭に入りやすくなるかと思います

プロローグ

1年以上前のことになると思います。 ある日、後輩がOpenAIのFunction Callingだったか、Agents for Amazon Bedrockだったかどちらかは失念してしまったのですが

機能リリースまもないくらいのタイミングに、ある後輩がその機能を使ってAWS EC2の起動・停止をチャットベースで生成AIと対話しつつ完遂する実装を見せてくれたことがありました。

「わざわざ見せにきてくれるとは、うい奴。スピード感もよし」と感心は覚えた一方、私はどうもモヤモヤ感がぬぐえず、つい

「これって従来型のプログラミングで、EC2のリストを出して、そこから好きなインスタンスを選ばせて、停止or実行を選ばせるようなCLIコマンド実装するのと比べて何が嬉しいのかな?」

と問いかけてしまったことがあります。

二人ともその場では考えつかず、後輩は「たさいさん(私のこと)、考えついたら教えてくださいよ」という調子のいいことを言っていたのを思い出します。

あれからそこそこの月日が経ち、生成AIを使わないシステム設計・構築が考えられないくらいに、着実に生成AIは仕事に浸透してきました。

業務であれこれ使ううちに、私のリテラシーもある程度は自然とつき、このお題に対して自分なりの説明がいくらかできる素地はできたように感じます。

そんな中、最近社内の別の同僚から「生成AIについて直近で可能性を感じていることについてレポートしてくれ」(大意)というお題を頂戴しました。

そこで、積年のお題である表題の問いに向き合いつつ、この直近のお題にも間接的に答えられる文章を書くかと思い立って、書き始めたのが本稿になります。

以って、今後生成AIをどう使っていくか・生成AIを組み込んでどのような開発を行なっていくか、皆さんが社内外で議論するためのよすがにもしてもらえれば大変嬉しく思います。

EC2を単に起動・停止させる程度じゃ真価はわからない

まずもって言えることは 「EC2を停止・起動できる程度のことに使っては正直真価はわからないだろう」ということです

私が当時疑問を呈したとおりで、この程度では容易に我々も書けてしまう・LLMに書いてもらえますからどうしても感動しづらい・敢えてこうした技術を学ぼうというモチベーションを起こさせない題材であると思います

参考に、以下は後者LLMにプロンプトを入力する手間を含めて1分程度で書き上げてもらったコードです(実際に機能します)

import boto3

# EC2クライアントの作成
ec2 = boto3.client('ec2')

# インスタンスのリスト取得
def list_instances():
    response = ec2.describe_instances()
    instances = []
    for reservation in response['Reservations']:
        for instance in reservation['Instances']:
            instance_id = instance['InstanceId']
            state = instance['State']['Name']
            name_tag = next((tag['Value'] for tag in instance.get('Tags', []) if tag['Key'] == 'Name'), 'N/A')
            instances.append({'InstanceId': instance_id, 'State': state, 'Name': name_tag})
    return instances

# インスタンスの操作
def manage_instances(instance_ids, action):
    if action == 'start':
        ec2.start_instances(InstanceIds=instance_ids)
        print(f"Started instances: {', '.join(instance_ids)}")
    elif action == 'stop':
        ec2.stop_instances(InstanceIds=instance_ids)
        print(f"Stopped instances: {', '.join(instance_ids)}")

# 実行フロー
if __name__ == "__main__":
    instances = list_instances()
    for i, instance in enumerate(instances, start=1):
        print(f"{i}: {instance['InstanceId']} ({instance['State']}) - Name: {instance['Name']}")

    print("Choose an action: 1) Stop, 2) Start, 3) Both")
    action_choice = input()

    if action_choice == "3":
        print("Enter the numbers of instances to stop, separated by commas:")
        stop_choices = input().split(',')
        print("Enter the numbers of instances to start, separated by commas:")
        start_choices = input().split(',')
    else:
        print("Enter the numbers of instances to manage, separated by commas:")
        choices = input().split(',')

    if action_choice == "1" or action_choice == "3":
        stop_instances = [instances[int(i)-1]['InstanceId'] for i in (stop_choices if action_choice == "3" else choices)]
        manage_instances(stop_instances, 'stop')
    if action_choice == "2" or action_choice == "3":
        start_instances = [instances[int(i)-1]['InstanceId'] for i in (start_choices if action_choice == "3" else choices)]
        manage_instances(start_instances, 'start')

もっとも、EC2の停止/操作を受け付けるというだけでも従来型のプログラミングで実現するよりいくらか良くなるであろう要素はあります

  • LLMは柔軟(セマンティック)にinputを解釈できますから、多少のtypoはよしなに解釈してくれたり「本当はこう入力したかったんじゃない?」と優しく聞き返してくれたりといったことが期待できる
    • 色々な誤入力・想定外入力に備えたコーディングをするのって案外面倒ですよね
    • 特にスマートスピーカーやIVRのような音声ベースのインタフェースを前提にするならば一層無視できないところがあります
  • RAGの手法を利用して例えば過去操作履歴を参照できるようにすれば、「前回停止したインスタンスを起動する」といったハイコンテクストな操作を受け付けるのもLLM版の方がスマートに実現できる

ただ、これらは生成AIが持っているポテンシャルのほんの一端を示すものに過ぎないと思います。

思うに、我々がその真価に気づくには、もっとスケールを大きく考えてみなくてはいけないでしょう。

たくさんのAPIを取り扱えるLLMソリューションの存在を妄想してみる

もしAWSの全APIの概要・用法を把握しているLLMのアプリがあったら・・・

もし社内業務に関連するすべてのSaaSを操作可能なAIエージェントがいてくれたら・・・

こういうレベル感のもの、つまりは ある程度 多種多様なAPIを扱えるLLMソリューション をつくろうと思った瞬間に見える風景は一変すると思うのです

例えば 「ECSでホストしているWebアプリにアクセスできなくなっちゃったんだけど、原因調べて」と投げかけるだけで

  • 調査に必要なさまざまなAPIをよしなに使いこなして
  • 関連リソースの状況を深く立ち入って調べてくれて
  • 原因と見られる事項と対処案を報告してくれて
  • 見立てと作業案を依頼者が承認した場合は実際の修正アクションまで取ってくれる

例えば 「2/28に東京に出張するための申請を組み立てて。可能であればサウナがついている宿がいい」と依頼するだけで

  • 自宅からの移動料金を計算して
  • 候補となる宿を見繕ってくれて
  • その他の申請に必要な項目もよしなに自動で埋めてくれた上で
  • 部長にSlackで承認を求めるメンションを飛ばしてくれる
  • 申請が了承され次第、宿や新幹線の予約を実施してくれて
  • 移動のカレンダー枠も抑えてくれる

どうです?仮に、ここまでのことをやってもらいうるのであれば、かなり革新的な感じがしてこないでしょうか?

現在の技術水準で「妄想」は十分「現実」にしうる

「そんなこと本当にできるのか?」と思われたかもしれませんね。 なるほど。たしかに、こういった規模感でのユースケースは巷ではまだ見聞きしない気はします。

ただ、それはまだ世の中の例が少ないだけであって、現行の技術水準でも多能なAIエージェントの実装は十分に手が届く段階にあると私は考えています。

その実装を考えるにあたって基礎の基礎となるであろう概念の一つが 「ReAct (Reasoning and Acting)」 です

ReActとは

ReActとは、LLMに複雑なタスクを解決させる際の思考・行動パターンを規定する手法です。 具体的には以下のような振る舞いを繰り返させることで目標達成を目指します

  • 現状分析・計画(Reasoning)と行動(Acting)を交互に繰り返す
    • この繰り返しをもって、ステップバイステップでタスクを進めていき、行動の結果を踏まえつつ柔軟にタスクの進め方を立案・軌道修正する
  • 各フェーズの推論過程を明示的に示す

従来の生成AIの推論は、事前に定義されたステップに縛られがちでした。

ReActでは、AI自らが途中経過を分析し、必要に応じて作業計画を動的に修正できます。 例えば、当初の想定外の障壁に遭遇した場合、即座に新しいアプローチを考案し、問題解決の方向性を柔軟に調整するといったことが期待できます。

また、こうした小刻みなタスクの進め方により、都度都度の思考プロセスが外部化されることも見逃せません。

従来LLMがあるinputをどのように解釈してoutputを行なっているかはブラックボックスになりがちでした。

対してReAct的なアプローチで構成されたLLMアプリ・エージェントは、自身の思考ステップを明示的なテキストとして生成・出力します。

そのことで単にLLMの意思決定過程について我々の理解が進むだけではなく、時にはそのクセ・誤りに対して

  • 「この知識が足りないからこういう判断になるのかな?ではソースを外部から補えるようにしよう」とか
  • 「こうこうこう考えさせるようにシステムプロンプトを改良してみよう」とか

といったように、我々人間にとって都合のいい方向性に修正するためのアプローチを考えやすくすることにも役立つことになります。

LLMのタスクプランニング・解決能力の向上

こうしたReAct等 *1 の考えに基づき実装・逐次改良されたソリューションが、最新のモデルの性能向上とも相まって「文章生成にとどまらない、かなり応用的なタスク」をこなすようになる兆しが徐々にみえつつあります。

現在この手の応用的な能力を窺い知るうえで参考になる指標として、以下のような指標があるのですが

  • SWE-bench(Software Engineering Benchmark):GitHub上のオープンソースのプロジェクトから実際のissueを抽出して、LLMに修正案を開発させて、実際にテストを通す品質のコードを生成できるかを評価する
    • テスト件数でベンチマークが細分化されており後述のVerifiedは 500 issues に対する処理能力を評価するベンチマーク
  • TAU-bench(Tool-Agent-User Benchmark):ユーザーと相互にやり取りを行いつつ必要な情報を収集・提供することができるかどうかを評価する
    • 特にある程度長期間を想定したやり取りに耐えうるかや、組織固有のポリシーを遵守しつつ対話できるかが主眼となっている

AWSのBedrock経由でも利用できるモデルであるClaude 3.5 Sonnetにおいては、SWE-bench Verifiedでのパフォーマンスが旧来のモデルと比べて 33.4% から 49.0% に向上しています

また、TAU-benchにおいても、小売分野での課題解決を想定したやり取りの評価ではパフォーマンスが 62.6% から 69.2% に、航空業界(同ベンチマークでは複雑性が比較的高いとされています)に関するものについても 36.0% から 46.0% にそれぞれ達しており順調な進歩がみられています。

www.anthropic.com

いずれも一定のスコアを達成するには高いタスクプランニング能力が不可欠なベンチマークです。

特にSWE-benchに関していうと、現実で発生しているissueに対しておよそ半分近く実用的な解決策を提示できているということは、人間の補助ツールとしてはかなり有望な水準に到達してきていることが言えるのではないかと思います。*2

なお、昨今の生成AIソリューションのコード生成能力の水準を体感するためには、開発用AIエージェントサービスである Devin なんかを使ってみると手っ取り早いかもしれません。

devin.ai

ある程度ラフな依頼に対しても、自律的にタスク計画を立案して、それを元にプログラム実装を非同期でガシガシ進めていってくれます。

現時点ではさすがに一流のエンジニアを上回る技量ではなさそうですが、それでも「人のプログラマーが劇的に要らなくなる世界」がそう遠くない時期に迫っていることをひしひしと感じさせてくれるツールです。

もし高度なタスクプランニング能力を持ったツールがプログラムを扱えるようになったら

「高度なタスク計画能力」さえあれば、LLMの元々の守備範囲である「文章をはじめとしたコンテンツ生成」の機能だけでも、両者の掛け合わせで相当な業務を効率化することができます。

先ほど例に取り上げたばかりの「コードの作成・修正」はその最たるものですね。

しかし、「計画能力」が高まってきたのであれば、それを活かすための「道具=プログラム実行能力」も与えたくなるのが人間の性分というもの。

冒頭に触れたAgents for Amazon Bedrockもいわば道具を与えるための一手段であるわけですが、今後はこの種の機能を利用した実装が増えていくことが当然に予想されます。

この節では、仮に生成AIが「プログラム実行」という武器をもった場合に、どういう振る舞いが期待できるかを、ある程度具体的に想像してもらうために(またReActの説明時に具体例を出せなかったのでその補足のために)

「架空のエージェント」についてふるまいをシミュレーションしてみたいと思います。 *3

弊社のblogをお読みいただいている方は、AWSに興味がある方がおそらくは多いでしょうから、先述のECSにホスティングしたWebアプリのトラブルシューティングケースを例にとってみます。

ReActのようなアプローチを採用しており、かつ業務上必要な全てのAWS APIにアクセス可能なLLMエージェントをうまく実装できたと仮定しましょう。

その場合、このエージェントは、ユーザーからの

「xxという名前のALBと、xxという名前のECSサービスとで構成されているnginxのWebアプリ(OCRアプリ)にアクセスできなくなった。原因を特定して」

というような、やや抽象的な依頼に対しても

以下のように筋道を立てて思考と行動(APIリクエスト)を段階的に展開していくことが期待できるでしょう。*4

Thought 1: まず、問題の全体像を把握するために、ALBとECSの基本的な状態確認が必要です。
ALBのヘルスチェック状態とECSタスクの状態を確認します。

Action 1: 
- ALBのターゲットグループのヘルスチェック状態を確認
- ECSクラスターのサービス状態とタスク数を確認

Observation 1:
- ALBのターゲットグループでヘルスチェックが失敗している
- ECSタスクは期待数通り実行中

Thought 2: ヘルスチェックの失敗が確認されました。
より詳細な原因特定のため、以下の情報を収集する必要があります:
1. ALBのアクセスログで最近のエラーパターン
2. ECSコンテナのログでnginxの状態

Action 2:
- Athenaを使用してS3のALBアクセスログを直近の30分ほど分析
- CloudWatch Logs Insightsでnginxのエラーログを確認

Observation 2:
- ALBログで大量の503エラーを確認
- nginxログで"no live upstreams while connecting to upstream"エラーを検出

Thought 3: nginx設定かアプリケーションの問題の可能性が高いです。
直近の変更履歴を確認し、問題の発生タイミングと関連付けを行います。

Action 3:
- CloudTrailでECS関連の設定変更履歴を確認
- AWS Configで構成変更履歴を確認

Observation 3:
- 30分前にECSタスク定義の更新が行われている
- メモリ設定値が何らかの理由で低く設定されていることを確認

Thought 4: 問題の根本原因が特定できました:
- タスク定義更新時にメモリ制限が誤って設定され、コンテナが頻繁にOOMKillされている
- これによりnginxプロセスが断続的に停止し、ALBのヘルスチェックが失敗している

導き出された対処方法:
1. タスク定義のメモリ制限を適切な値(前回の正常動作時の値)に戻す
2. ECSサービスを更新して新しいタスク定義を適用する

このように「実行計画が事前定義されていない状態でも、自ら計画を行い、自らその実行をしていく類のソリューション」のことを、巷ではAIエージェントやLLMエージェントと呼ぶようにもなっています。

「2025年はAIエージェントの年になる」なんていうことを書いている記事・謳っているセミナーを目にしたことがある方もいくらかいらっしゃるかもしれませんが、こうした風潮も「単なるQ&Aチャット」を超えた応用的な用法に、世の中の生成AIに対する関心も徐々に向かいつつある証左と言えるのではないかと思います。*5

小括

「生成AIがプログラムを扱えて何が嬉しいのか」

この冒頭の問いに対する答えの材料を探すべく、関連するであろうトピックについてここまで書き連ねてまいりました。

これまでの内容だけでも回答はまとめられそうではありつつも

この稿だけでは、いささか過当に夢をふくらませすぎている(抽象度が高すぎる、実際にAIエージェント的なものを開発することを考えた場合に直面するであろう障壁だったり具体的な利用候補となる技術だったりに触れてなさすぎる)感もあり、若干の消化不良感があります

そこで記事を前後二編に分けさせていただいて、後編でこの辺り↑の「地に足をつかせるための補足」を多少加えた上で、改めて問いに対する答えをまとめることにしたいと思います

追記

前後二編ではまとまりきらず、前中後編になってしまいました・・・

中編はこちら

脚注

*1:Tree of Thoughts (ToT)やIteration of Thought (IoT)等、他にも重要な概念はありますが、これらについては紙幅の都合上、別の機会に触れたいと思います

*2:さらに本ブログ時点では正式リリースされていないので具体的な言及は避けますが、近日リリース予定のOpenAIのo3に至っては現行の各社の最新モデルをはるかに凌駕する段階的な論理推論能力を発揮できると言われており、応用的な領域におけるLLMの利用への期待はいやがおうにも高まっている状態です

*3:厳密にはDevinのような開発用AIエージェントも、単なるコード生成・修正能力だけではなく、すでにCLI実行やブラウザアクセス、SlackやGithubの一定の操作能力を有しています。それがゆえに一定の性能を発揮しているツールと言ってもいいでしょう。また、同じく先ほど紹介したTAU-benchも、評価するLLMソリューションに関してコンテンツ生成能力だけではなく他のツール連携能力も備えていることを前提としているようなベンチマークだったりします。ただ、そのことまで断ると文章が長ったらしくなるので本文での説明は割愛させていただきました

*4:このシミュレーション、実はやや手抜きがあるのですが、その辺りの補足・解説は後編でさせていただきたく思います

*5:もっとも「AIエージェント」という言葉を聞いて具体的に何を想起するかは、今日の段階では人によってやや幅がある印象を受けています。

・「AIエージェントによりエンパワーメントされたワークフロー」のようなもの(大枠の処理の流れは事前定義しているが、その一部の工程・ブロックで『AIエージェント』を採用することで、処理を高度化・柔軟化したもの)も含めてAIエージェントと捉えている方
・「具体的な実行計画については大部分をLLMに委任する」類のもののみをAIエージェントと捉えている方
・はたまた、特に内部的な仕組みは意識せず「気の利いた対応をしてくれるbot」くらいの捉え方をしている方etc

直近で、このワードが商談等の話題になった場合は、まずはお互いの認識を確かめるところから始めた方が無難かもしれません

田斉 省吾 (記事一覧)

アプリケーションサービス部

2016年新卒入社。筆無精で入社以降一切ブログを書いてこなかったのですが、色々ありごく稀に書くことにしました(群馬から真心をこめてお届けします)