AIエンジニアの探求

計算論的神経科学で博士号取得後、AIエンジニアとして活動中。LLMの活用や脳とAIの関係などについて記事を書きます。

読んだ本の備忘録①「世界一流エンジニアの思考法」

今年から読んだ本については、備忘録として感想などをまとめようと思う。1冊目は牛尾剛の「世界一流エンジニアの思考法」。

https://amzn.asia/d/2pUFq4Z

この本では著者自身のMicrosoft Azureチームでの経験をもとに、エンジニアとしての効率的な仕事の方法論やマインドセットが紹介されている。読み進める中で、自分が既に実践している点や新たに取り入れたい点、そして自分の考えと異なる視点など、多くの気付きを得た。

共感したポイント

まず、実践していて改めて納得感を感じた点は以下。

  • Be Lazy:無駄な仕事はしない。
  • 優先度を設定する際、重要でないタスクは思い切って切り捨てる。
  • ミーティングにおいては基本的にその場で全て解決し、宿題を持ち帰らない。
  • メンバーは皆1つの個人商店だと思ってマネジメントする、管理ではなく力を最大限発揮できるよう支援するのが役割という考え方

これらのアプローチは、プロフェッショナルとして効率的に仕事を進める上で重要だと思う。

実践してみたいこと

新たに試してみたいと思ったのは以下の点。

  • 学びのアウトプット:ブログなどを通じて、学んだことを共有する。
  • 1日4時間程度、チャットやmtgをしない自分のための作業時間を設ける。
  • マルチタスクを避けて一つのタスクに集中する。

異なる視点

一方で、本書には自分の考えと異なる部分もあった。「言語仕様などをじっくりと理解して、自分の手でコントロールできる領域を増やすようにする(何もみないで書けるコードを増やす)」という点である。これはcopilotやcursorなどの最新の生成AIツールの進化を考慮するとそこまでこだわらなくて良いのではと思っている。むしろ「薄く理解している」範囲を広げ、明確な目標設定に重点を置くべきではないかと感じた。

まとめ

「世界一流エンジニアの思考法」は、現代エンジニアにとって多くの洞察を与えてくれる一冊。自分の仕事の進め方を見直し、新しいアプローチを模索する機会を提供してくれた。また、それだけに留まらずこの本を読んだ後だと仕事をするのが楽しみになった。

OpenAIのfunction callingでタスクの自動管理に挑戦

ChatGPTの新機能であるfunction callingが話題になっています。

このfunction callingを使えばChatGPTが自然言語の入力から関数への引数を自動で設定してくれるようになるということで、先日簡単に試してみました。

このツイートでは自然言語でタスクを設定するとよしなにタスクの内容、開始日、終了日を定めてくれることを確認しました。これにより、例えばGASを叩くことでガントチャートなどにタスクを登録できるようになります。

タスクの設定は様々な形式で行うことができ、例えば以下のようなパターンに対して正しく引数を定義できました。

  • 6/12から7/3まで参考文献調査をする
  • 6/14から要件定義を行う。締切は6月21日
  • ストーリーラインの作成。7月上旬から始めて7月中旬までに完了させる

「これは便利そうだ」と思ったものの、同時に「結構使い所が難しいな」という印象を持ちました。というのも、ガントチャートにタスクを登録する際は素直にタスクの内容、開始日、終了日を定められたフォーマットで(人間が)記入すれば良く、わざわざ自然言語で登録したい場面がなかなか思い浮かばなかったためです。

しかし、人が登録するのではなくシステムが自動で登録するようなシチュエーションではかなり重宝しそうです。 そういった、function callingに関する需要と供給がマッチしそうな場面がないか考えた結果、「slackからタスクの自動登録」はかなりポテンシャルがあるのでは・・?と思い至りました。

slackのメッセージからのタスクの自動登録

slack上では、日々様々なメッセージが飛び交っており、その中でタスクの依頼を受けるケースも少なくありません。

slackメッセージの一例(データはダミーです)

その中で、「依頼してもらったタスクを見逃す/忘れてしまう」ケースが往々にしてあると思います。 そこでタスクを依頼してもらった時に自動でガントチャート(なりバックログなり)に登録する機能があれば便利そうです。 また、タスクの依頼方法は人によってまちまちなので、function callingの「様々な入力形式を受け付けて、正しい引数に変換してくれる」機能の本領が発揮されそうです。

登録すべきタスクの判定

上述したようにslack上のメッセージは全てタスクの依頼というわけではないので、まず「登録すべきタスクかどうか」を判定する必要があります。 基本的な考え方としては「お願いします」「ご確認いただけると幸いです」などのような依頼文になっているかで判断する形で良いと思いますが、例えば

すみません、前のmtgが伸びていて遅れそうなので、先にmtg始めていただけると助かります。

などのように依頼文ではあるもののタスクとして登録するのがふさわしくないメッセージもあります。

この判定を行うために、以下のようなCoT(Chain of Thought) promptingを活用しました(初期的な検証に利用したものなので、改善の余地は大いにあるものと思われます)。

## 背景
slack上でのやり取りから、slack上で依頼された事項を見逃してしまったり忘れてしまうという課題を解決するために、タスクとしてガントチャートに登録することで一元的に管理しようとしています。
しかしslack上での送られるメッセージが全てタスク化すべき依頼事項というわけではないので、まずメッセージがタスク化すべき依頼事項(=ガントチャートに登録すべきタスク)かどうかを判定する必要があります。

## 指示
slack上で送られたメッセージが与えられるので、ガントチャートに登録すべきタスクかどうかを判定してください。ガントチャートに登録すべきタスクでない場合は、「タスクではない」と出力してください。ガントチャートに登録すべきタスクの場合は、
・タスクの内容
・開始日
・終了予定日
を出力してください。ただし、開始日は特に指定がない場合は送信日を開始日とみなしてください。また、終了予定日が分からない場合は出力しなくて良いです。

## 制約
- タスクの具体的な内容が抽象的であっても、問題ありません。「タスクの内容」として出力してください
- 依頼文の形であっても、習慣の変更や「今この瞬間に」実施すべきことについてはガントチャートに登録する必要はないです

## 例
- slack message:
送信日: 2023/6/25
@Kohei Ichikawa 追加検証していた実験についてアップデートしたので、お手隙の際にご確認いただけると幸いです! 
https://tripdancer0916.hatenablog.com/entry/llamaindex_agent
- 出力:
「ご確認いただけると幸いです!」という依頼文の形であるため、何らかのタスクが依頼されている可能性が高い。また記事のリンクが貼られていることから、このリンクの記事のレビューをタスクとして実施することが望ましいと考えられる。よって、
・タスクの内容: https://tripdancer0916.hatenablog.com/entry/llamaindex_agent の記事のレビュー
・開始日: 2023/6/25

- slack message:
送信日: 2023/4/8
りんごをオレンジに置き換えることで画像認識タスクの精度が3%上がったそう。参考になるかもです
- 出力:
このメッセージは参考情報としてシェアしているものであり、特に何か依頼内容が含まれているわけではない。よって、
タスクではない

(例が続く)

これにより、入力されるメッセージに対して以下のようにタスクの判定が行われることを確認しました(以下はCoTの例として与えていないサンプルに対する結果です)。

例1

  • slack message: 送信日: 2023/4/8 PR作成しました!レビューお願いします!
  • 出力: メッセージに「レビューお願いします」という依頼文があり、タスクが依頼されていると考えられます。よって、

・タスクの内容: PRのレビュー

・開始日: 2023/4/8

例2

  • slack message: 送信日: 2023/5/13 充電器を貸していただいても良いでしょうか?
  • 出力: このメッセージは充電器の貸し借りについての依頼であり、タスクとしてガントチャートに登録するような内容ではありません。よって、 タスクではない

例3

  • slack message: 送信日: 2023/6/4 next action: ストーリーラインの作成(6/11まで)
  • 出力: 「next action: ストーリーラインの作成(6/11まで)」という文があることから、依頼が含まれています。また、「6/11まで」という締切が指定されています。よって、

・タスクの内容: ストーリーラインの作成

・開始日: 2023/6/4

・終了予定日: 2023/6/11

このように、様々な形式のメッセージに対して正しく登録すべきタスクの判定ができていることを確認できました。

外部関数に与える引数への変換

出力結果を見るとタスクの内容、開始日、終了予定日が抽出されているので登録すべき情報は出揃いました。しかしCoTで出力させた推論プロセスも出力されてしまっているので、出力する情報を絞る必要があります。

そこでfunction callingの出番です。

冒頭のツイートにある関数の引数に関するプロンプトを再活用します(ただし差分として、nullを許容するようにしました)。

functions = [
    {
        'name': 'register_task',
        'description': 'タスクをガントチャートに登録する',
        'parameters': {
            'type': 'object',
            'properties': {
                'task': {
                    'type': 'string',
                    'description': '実施するタスク名。ただし、タスクではない場合や判断できない場合nullとする。例: 画像認識手法サーベイ、アブストラクト執筆、モデルファインチューニング',
                },
                'start_date': {
                    'type': 'string',
                    'description': '実施するタスクの開始日。半角でyyyymmdd形式とする。年の指定がない場合、デフォルトは2023年。ただし、タスクではない場合や判断できない場合nullとする。例: 20230619, 19950908',
                },
                'end_date': {
                    'type': 'string',
                    'description': '実施するタスクの終了予定日。半角でyyyymmdd形式とする。年の指定がない場合、デフォルトは2023年。また、指定しなくてもよい。指定しない場合nullとする。例: 20230619, 19950908',
                },
            },
            'required': ['task', 'start_date', 'end_date'],
        },
    }
]

そして入力として、先ほどのタスク判定関数の返り値を与えます。 結果は以下のようになりました。

例1

{
"task": "PRのレビュー",
"start_date": "20230408",
"end_date": null
}

例2

関数呼び出しなし

例3

{
  "task": "ストーリーラインの作成",
  "start_date": "20230604",
  "end_date": "20230611"
}

これにより、いい感じにslackのメッセージからタスクだけを抽出してガントチャートに登録することができそうです。

今回はfunction callingの検証がメイン目的でしたが、需要がありそうなら実際にslackとspread sheetを連携させてタスク自動管理を実行するところまで挑戦してみたいと思います。

まとめ

  • function callingの有効な使い所として、「slackのメッセージからのタスクの自動登録」が良さそうと考え、検証してみました。
  • 「メッセージからタスクかどうか・その内容の判定を実施→得られた結果をガントチャートに登録できる形に自動フォーマッティング」という一連の流れの中で、後半部分におけるfunction callingの有効性を確かめることができました。
    • 前半の判定部分もやってみるとなかなか奥が深そうだったので、掘り下げてみても面白そうです。
  • 一般的な示唆として、「Chain of Thoughtで得られた結果をいい感じにフォーマットする」際にfunction callingが便利そうであることが分かりました。

AutoGPTを使ってみた

この記事は?

AutoGPTというGPT-4を活用してゴールを与えるだけで自動的にタスクを完了させることを試みたプログラムが注目を集めています。

このAutoGPTを簡単なユースケースで使ってみたので、具体的な動作の様子や(あくまで個人の所感としての)使い方のコツを書いてみました。

なお、AutoGPT関連の記事には抽象度の高い「こういうことができる」という情報や「動かすための手順」は載っていることが多いものの、「実際に動かした時にどのような結果が得られるか」が載っている記事が少ないと感じたため、そのような情報を求めている方にとっては有益な記事になっているのではと思います。

また、上でも書いたように実行方法は他の記事などで紹介されているのでここでは省略します。私は公式ドキュメントに従ってdockerを利用しました。

ユースケース - 簡単なコードの作成と実行

私自身のざっくりとした理解として、「AutoGPTはChatGPTにGoogle検索やプログラムの実行といった手足をつけたもの」というものがあるのでせっかくなら「手足を上手く使いこなす能力」をみたいと思いました。

色々なゴール設定を試してみたのですがなかなか上手くいかず、たどり着いたのが「正弦波をmatplotlibで描画して保存する」というゴールでした。

なお、名前・役割・ゴールは以下の通りです。

Name:  MatplotlibGPT
Role:  an AI assistant that specializes in creating high-quality visualizations using the Matplotlib library.
Goals:
-  Generate a sin function plot using Matplotlib that accurately represents the data and is visually appealing.
-  Customize the plot to meet your specific needs, including adjusting the color scheme, adding labels and titles, and modifying the axis limits.
-  Save the plot in a variety of file formats, including PNG, PDF, and SVG, to ensure compatibility with your preferred software and devices.
-  Provide guidance and troubleshooting support if any issues arise during the visualization process.
-  Continuously learn and adapt to new trends and techniques in data visualization to ensure that your plots are always up-to-date and effective.

これを実行してみると、大体以下のような流れでタスクが実行されていきました(この流れでは人間は介入せず、AutoGPTが提案するnext actionを全て承認していました)。

  • sin_plot.pyというファイルを実行しようとする
  • そのようなファイルは存在しないことに気づき、新しく作成する
  • 作成したsin_plot.pyを実行する
  • matplotlibのライブラリがないことに気づく
  • matplotlibをインストールするたのスクリプトを作成する
  • 作成したスクリプトを実行する
  • もう一度sin_plot.pyを実行する(この時画像の保存先が間違っており、保存されない)
  • 画像が保存されたかを確かめるためにフォルダ内を調べる
  • 画像が保存されてないことに気づく
  • もう一度sin_plot.pyを実行する
  • 画像が保存されたかを確かめるためにフォルダ内を調べる
  • 画像が保存されてないことに気づく
  • もう一度sin_plot.pyを実行する
  • ...

途中までいい感じだったのですが、最後は無限ループに陥ってしまいました。 ちなみに途中までの試行錯誤プロセスはさすがGPT-4という感じで、「よく自分もこういう感じに開発するなあ」と思いながら見ていました笑

また、この時sin_plot.pyは以下のようになっており、

  • 画像を保存する前にplt.show()がついている

ことで正しく保存されなくなってしまっているようです。

# Import Matplotlib
import matplotlib.pyplot as plt
import numpy as np
import os

# Generate data
x = np.linspace(0, 2*np.pi, 100)
y = np.sin(x)

# Create plot
fig, ax = plt.subplots()
ax.plot(x, y)
ax.set_xlabel('x')
ax.set_ylabel('y')
ax.set_title('Sin Function Plot')
plt.show()
fig.savefig('sin_plot.png')
fig.savefig('sin_plot.pdf')
fig.savefig('sin_plot.svg')

フィードバックを与えることによる介入

AutoGPTでは、AIが提案するnext actionに対してフィードバックを与えることが可能です。

具体的には、以下のようにnext actionが提案されるのでInput:のところに要望などを書くことができます。

NEXT ACTION:  COMMAND = execute_python_file ARGUMENTS = {'filename': '/app/autogpt/auto_gpt_workspace/sin_plot.py'}
  Enter 'y' to authorise command, 'y -N' to run N continuous commands, 's' to run self-feedback commands'n' to exit program, or enter feedback for ...
  Asking user via keyboard...
Input:

この提案を承諾しても無限ループから脱出できないので、「画像が上手く保存されていないようです」と伝えてみました。

すると保存先がfig.savefig('plots/sin_plot.png')になるという、的外れな変更が適用されてしまいました。

仕方ないので、Input:plt.show() may not be necessary.と直接的に指示を出すと、「ファイル読み込み操作」のあと以下のプランが提案されて、正しくスクリプトが修正されました。

PLAN:
-  Use the 'read_file' command to read the 'sin_plot.py' script.
-  Modify the script to remove the 'plt.show()' command.
-  Use the 'write_to_file' command to save the modified script.
-  Use the 'execute_python_file' command to run the modified script and generate the plot.
-  Check that the plot is generated correctly and is visually appealing.
-  Modify the code as needed to customize the plot.

最終的に得られたグラフは以下になります。

所感

まず第一に、思ったよりも使いこなすのが大変という印象でした。

「ゴールを与えるだけ」だと無限ループしたり頓珍漢な方向に進んでしまうので、適切にフィードバックを与えて面倒を見る必要があります。 ChatGPTのようにインタラクティブに使うツールと考えた方が良さそうな感じです。

一方、「実際にプログラムを実行できる」というのはやはり新しい体験で楽しく、「ChatGPTに書いてもらったコードを自分で実行する」のとはレイヤーが違う作業をしている感覚がありました。

上手くやればAutoGPTをフル活用した開発フローが作れそうな気がします。

今後もAutoGPTを使っていき、より難易度の高いタスクを実行できないか試していきたいと思います。