AIアシスタントを使用してツールのドキュメントを読む

この進行中の Docker Labs GenAI シリーズ AI開発者ツールのエキサイティングな空間を探ります。 Dockerでは、誇大広告なしでオープンに探求できる広大な範囲があると信じています。 私たちは、探索を共有し、開発者コミュニティとリアルタイムで協力します。 開発者はGitHub Copilotのようなオートコンプリートツールを採用し、チャットを使用していますが、AIツールがソフトウェアのライフサイクル全体を通じて、より具体的なタスクやインターフェースを支援する可能性は大いにあります。 したがって、私たちの探求は広範囲に及びます。 ソフトウェアをオープンソースとしてリリースするので、私たちと一緒にプレイしたり、探索したり、ハックしたりできます。

コマンドラインで新しいツールを使用すると、イライラすることがあります。 適切なツールを見つけたと確信していても、その使い方がわからない場合があります。

エージェントにRT(F)Mを指示する

一般的なワークフローは、次のようになります。

  • ツールをインストールします。
  • ドキュメントをお読みください。
  • コマンドを実行します。
  • 繰り返す。

LLMを使用してこのフローを改善できますか?

2400x1260 Docker Labs Genai

インストールツール

Dockerは、ツールを実行するための分離された環境を提供します。 コマンドをインストールする代わりに、ツールごとに最小限の Docker イメージを作成して、ツールの使用がホスト システムに影響を与えないようにしました。 いわば、痕跡を残さないでください。

ドキュメントを読む

マニュアルページは、ツールの作成者がそのツールの使用方法に関するコンテンツを公開する方法の 1 つです。 このコンテンツには、標準の取得メカニズム( man ツール)も付属しています。 ツールでは、 --help などのコマンドラインオプションもサポートされている場合があります。 まず、ツール自体から使用情報を取得できるべきだという理想主義的な考えから始めましょう。

この実験では、ツールごとに 2 つのエントリ ポイントを作成しました。 最初のエントリポイントは明白なものです。 これは、コマンドラインプログラムに直接渡される引数のセットです。 このエントリポイントに対して生成するOpenAI互換の説明を以下に示します。 すべてのツールで同じインターフェースを使用しています。

{"name": "run_my_tool",
   "description": "Run the my_tool command.",
   "parameters":
   {"type": "object",
    "properties":
    {"args":
     {"type": "string",
      "description": "The arguments to pass to my_tool"}}},
   "container": {"image": "namespace/my_tool:latest"}}

2 番目のエントリポイントにより、エージェントは man ページを読み取ることができ、うまくいけば、最初のエントリポイントを実行する能力が向上します。 2 番目のエントリポイントは、1 つのこと (ツールの使用方法を尋ねる) のみを行うため、より単純です。

{"name": "my_tool_manual",
   "description": "Read the man page for my_tool",
   "container": {"image": "namespace/my_tool:latest", "command": ["man"]}}

コマンドを実行します

簡単な例から始めましょう。 qrencodeというツールを使用して、リンクのQRコードを生成したいと思います。イメージ生成パイプラインを使用して、このツールを qrencode の最小限のイメージにパッケージ化しました。 次に、このプロンプトをいくつか異なるLLMに渡します。ツールコールのトレーニングを受けたLLM(GPT 4、Llama 3.1、Mistralなど)を使用しています。 テストしているプロンプトを次に示します。

Generate a QR code for the content https://github.com/docker/labs-ai-tools-for-devs/blob/main/prompts/qrencode/README.md. Save the generated image to qrcode.png.
If the command fails, read the man page and try again.

このプロンプトの楽観的な見方に注意してください。 さまざまな LLM がトレーニング セットで既に何を見ているかを予測するのは難しく、多くのコマンド ライン ツールでは引数に一般的な名前が使用されているため、 man ページをコンテキストに追加する前に LLM が何を推測するかを確認するのは興味深いことです。

プロンプトの出力を次に示します。 携帯電話を手に取り、チェックしてみてください。

AIアシスタントによって生成された黒と白のqrコード。
図 1: AIアシスタントによって生成されたコンテンツQRコード。

繰り返す

LLM が何かの実行方法の説明を生成するとき、通常、ユーザーが応答を端末に切り取って貼り付けるのが簡単になるように、その出力を書式設定します。

qrencode -o qrcode.png 'my content'

ただし、LLM がツール呼び出しを生成している場合は、実行しやすいように書式設定された出力が表示されます。

[{"function": {"arguments": "{
  \"args\": \"-o qrcode.png 'my content'\"
}"
               "name": "qrencode"}
  "id": "call_Vdw2gDFMAwaEUMgxLYBTg8MB"}]

これに対応するには、Docker コンテナをスピンアップします。

会話ループの一部としてツールを実行すると、コマンドが失敗した場合でも役立ちます。 Unix では、障害を伝達する標準的な方法があります。 たとえば、 exit コードと stderr ストリームがあります。 このようにして、ツールはフィードバックループを作成し、ターミナルで反復している間に動作を修正します。 これと同じメカニズムを、LLM が関与する会話ループで使用できます。

説明のために、別の簡単な例を次に示します。 次のプロンプトで ASCIIアートを書き込む ツールを実行してみてください。

Write ascii art with the message "Docker" using the font "helvetica".  Read the man page for figlet if you detect any errors and then try again.

私たちのテストでは、これは失敗しました。 ただし、 stderr 出力ストリームの明らかな問題についても説明されていました。

Error: error: could not load font helvetica

このメッセージを会話ループに含めることで、アシスタントはさまざまなアクションを提案できます。 ここでは、LLMが異なれば結果も異なります。 たとえば、Llama 3.1 では、不足しているフォントのインストール方法について説明します。 一方、GPT 4 コマンドを再実行しましたが、それは別のフォントを試すという「エグゼクティブ」の決定を下した後に限られます。

I'm sorry, it seems the font Helvetica is not available. Let's try it with the default font.

Here is the output of the figlet command with the default font (term): 

 ____             _             
|   \    _       | | _____ _ 
| | | |/  \ / _| |/ /  \ '_|
| |_| | (_) | (__|   <  __/ |   
|____/ \___/ \___|_|\_\___|_|

私たちは、この明らかな能力を利用してさまざまなアプローチを試す方法を理解するのに非常に早い段階です。 しかし、これが、これらのツールをDockerコンテナに隔離することが役立つ別の理由です。 それは彼らの爆発半径を制限し、私たちは実験を奨励します。

業績

まず、各ツールに対して最小限の Docker イメージを生成するパイプラインを作成することから始めました。 一連のツールは、開発者向けのワークフローに役立つ出力があるかどうかに基づいて選択されました。 新しいユースケースを考えながら、新しいツールを追加し続けています。 初期設定は以下のとおりです。

gh pylint commitlint scalafix gitlint yamllint checkmake gqlint sqlint golint golangci-lint hadolint markdownlint-cli2 cargo-toml-lint ruff dockle clj-kondo selene tflint rslint yapf puppet-lint oxlint kube-linter csslint cpplint ansible-lint actionlint black checkov jfmt datefmt rustfmt cbfmt yamlfmt whatstyle rufo fnlfmt shfmt zprint jet typos docker-ls nerdctl diffoci dive kompose git-test kubectl fastly infracost sops curl fzf ffmpeg babl unzip jq graphviz pstree figlet toilet tldr qrencode clippy go-tools ripgrep awscli2 azure-cli luaformatter nixpkgs-lint hclfmt fop dnstracer undocker dockfmt fixup_yarn_lock github-runner swiftformat swiftlint nix-linter go-critic regal textlint formatjson5 commitmsgfmt

コンテキスト抽出には、いくつかの初期問題がありました。

マニュアルページがありません

私たちが選択したツールのうち、manページを持っているのは約60%にすぎません。ただし、そのような場合でも、通常、ヘルプ コンテンツを取得する方法は他にもあります。 次の手順は、使用した最終的な手順を示しています。

  • manページを実行してみてください。
  • 引数 --help を指定してツールを実行してみてください。
  • 引数 -h を指定してツールを実行してみてください。
  • --broken引数を使用してツールを実行し、stderrを読み取ってみてください。

この手順を使用すると、上記のリストのすべてのツールが最終的にドキュメントを作成しました。

長いマニュアルページ

コンテキストの長さが限られていると、一部の長いマニュアルページに影響を与えたため、冗長なマニュアルページを要約するには、標準のRAG手法を採用する必要がありました。 私たちの戦術は、コマンドライン引数の説明と、サンプルの使用方法があるセクションに焦点を当てることでした。 これらは、エージェントの出力品質に最も大きな影響を与えました。 Unix man ページの構造は、コンテンツのチャンク化を標準のセクションに頼ることができたため、チャンク化に役立ちました。

サブコマンド

ツールの小さなセットの場合、ヘルプメニューのツリーをトラバースする必要がありました。 ただし、これらはすべて比較的人気のあるツールであり、デプロイした LLM は、このコマンド構造についてすでに知っていました。 これを自分で確認するのは簡単です。 たとえば、LLM に「Git のサブコマンドは何ですか?」または「Docker のサブコマンドは何ですか?」 もしかしたら、人気のあるツールだけが、サブコマンドに分割され始めるほど大きくなるかもしれません。

概要

ツールの使用方法を決定する際に、エージェントが果たすことができる積極的な役割を考慮する必要があります。 Unix モデルでは、 man ページ、 stderr ストリーム、 exit コードなどの標準が提供されており、アシスタントにツールの学習を依頼するときにこれらの規則を利用できます。 Dockerは、配布だけでなく、安全な探索のための環境を作成する際にも役立つプロセスの分離も提供します。

AIがツールコールを正常に生成できるかどうかは、ツールが十分に文書化されているかどうかの指標にもなり得ます。

この取り組みを進めるには、 このプロジェクトの GitHub リポジトリを確認してください。

さらに詳しく