開発者向けの Docker AI ツールを使用して、より良いコード修正のためのコンテキストを提供する

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

Docker Labs では、LLM が開発者ワークフローのさまざまな部分をつなぎ、ツールとプロセスの間のギャップを埋める方法を模索してきました。 重要な洞察は、LLMは、適切なコンテキストがある場合にコードの問題を修正することに優れているということです。 このコンテキストを提供するために、リンティング違反とトップレベルのコードブロックの構造を使用してコードベースをマッピングするプロセスを開発しました。 

これらの要素を組み合わせることで、LLMにコードの包括的なビューを構築するように教え、問題をより効果的に修正できるようにします。 コンテナ化を活用することで、これらのツールの統合がはるかに簡単になります。

2400x1260 Docker Labs Genai

以前は、リンティングのプロセスが少しバラバラに感じられました。 エラーが発生し、 Pylintを実行すると、時々不可解なメッセージが表示され、問題を理解するためにPylintのマニュアルを参照することを余儀なくされました。 OpenAIがChatGPTをリリースしたとき、プロセスはわずかに改善されました。 Pylint を実行し、エラー メッセージを把握しなかった場合は、コードと違反を GPT にコピーして、より適切な説明を得ることができました。 時々、コードを修正するように依頼してから、ソリューションを手動でエディターに貼り付け直します。

ただし、このアプローチでは、コードのコピー、アプリケーション間の切り替え、修正の統合など、いくつかの手動手順が必要でした。 このプロセスをどのように改善できるでしょうか?

Docker の AI Tools for Devs プロンプト ランナーは、Pylint のようなツールをコンテナ化を通じて LLM のワークフローに直接統合できるアーキテクチャです。 Pylintをコンテナ化し、LLMがPylintと対話するために使用できるプロンプトを作成することで、LLMが必要なツールとコンテキストにアクセスしてコードの問題を修正できるシステムを開発しました。

認知アーキテクチャの理解

LLMが効果的に支援するためには、情報にアクセスして処理するための構造化された方法が必要です。 このセットアップでは、LLM は Docker プロンプト ランナーを使用して、コンテナ化されたツールやコードベースと対話します。 プロジェクトのコンテキストは、プロジェクトに対して実行される Pylint や Tree-sitter などのツールを使用して抽出されます。 このコンテキストは保存および管理され、LLM は必要なときにアクセスできます。

コードベース、リンティングツール、および以前のプロンプトのコンテキストにアクセスできることで、LLMは問題がどこにあるのか、それが何であるかを理解し、それらを修正するための適切なコードフラグメントを持つことができます。 この設定は、問題を見つけてLLMに供給する手動プロセスを、自動的でより魅力的なものに置き換えます。

ワークフローの効率化

今では、ワークフロー内で、コードの品質や違反についてアシスタントに直接尋ねることができます。 LLMを搭載したアシスタントは、Dockerプロンプトランナーを介して、コンテナ化されたPylintツールと私のコードのデータベースにすぐにアクセスできます。 この統合により、LLMは開発中に直接私を支援するツールを使用できるようになり、プログラミングエクスペリエンスがより効率的になります。

このアプローチは、ツールとの関わり方を再考するのに役立ちます。 コードを問題にマッピングするツールで会話型インターフェイスを実現することで、より直感的な開発エクスペリエンスの可能性を模索しています。 手動で問題を見つけてAIに渡すのではなく、ツール自体との関係を、問題を自動的に検出し、コンテキストを理解し、解決策を提供できる会話型パートナーに変えることができます。

プロンプトの順を追って説明する

私たちのプロジェクトは、LLMが実行する必要のあるタスクをガイドする一連のプロンプトを中心に構成されています。 これらのプロンプトは Git リポジトリに格納され、バージョン管理、追跡、および共有できます。 これらはプロジェクトのバックボーンを形成し、LLMがツールやコードベースと効果的に対話できるようにします。 このプロセス全体は、DockerとGitリポジトリに保存されている一連のプロンプトを使用して自動化されます。 各プロンプトはワークフローの特定のタスクに対応しており、Dockerコンテナはツールとスクリプトを実行するための一貫した環境を確保します。

ワークフローのステップ

私たちが直面した差し迫った実存的な課題は、この問題のクラスがLLMのコンテキストを圧倒する多くの機会を持っているということでした。 ソースコードファイルを読みたいですか? 読むのに十分な大きさでなければなりません。 複数のファイルで作業する必要がありますか? 現実的な制限は、一度に 3 つから 4 つのファイルです。 これを解決するために、LLMに独自のワークフローを自動化するように指示できます。ツールを使用して、各ステップはDockerコンテナ内で実行されます。

繰り返しになりますが、このワークフローの各ステップは Docker コンテナで実行されるため、ツールとスクリプトを実行するための一貫性のある分離された環境が確保されます。 最初の4つのステップでは、エージェントが違反を修正するための適切なコンテキストを抽出できるように準備します。 エージェントが必要なコンテキストを取得したら、LLM はステップ 5でコードの問題を効果的に修正できます。

1。 Pylint を使用して違反レポートを生成します。

Pylint を実行して違反レポートを作成します。

2。 SQLite データベースを作成します。

違反データとコードスニペットを格納するようにデータベーススキーマを設定します。

3。 INSERT ステートメントを生成して実行します。

  • 違反を、それらが表す範囲から切り離します。
  • スクリプトを使用して、レポートのすべての違反と範囲を SQL 挿入ステートメントに変換します。
  • データベースに対してステートメントを実行して、必要なデータをデータベースに取り込みます。

4。 データベース内のインデックス コード:

  • Tree-sitter を使用してプロジェクトの抽象構文木 (AST) を生成します (図 1)。
シンタックスツリーのスクリーンショット、ファイルの表示、例の詳細な見方。 ピュッ。 解析。
図 1: 抽象構文ツリーの生成。
  • すべての第 2 レベルのノードを検索します (図 2)。 Python の文法では、第 2 レベルのノードはモジュール内のステートメントです。
例を広げて見てください。 ピュッ。 強調表示されたステートメントで解析されます。
図 2: データベースのコンテンツを抽出します。
  • これらの最上位範囲をデータベースにインデックス付けします。
  • 新しいテーブルを設定して、これらの最上位範囲にソース コードを保存します。

5。 コンテキストに基づいて違反を修正します。

エージェントが必要なコンテキストを収集してインデックスを作成したら、プロンプトを使用して LLM にデータベースをクエリし、コードの問題を修正するように指示します (図 3)。

指示の図は、例えば、ファイルで発生する「違反」を修正します。 行 1"のPyは、それが発生する関数に関する情報とともに。
図 3: 違反を修正するための指示。

1から4までの各ステップは、LLMが適切なコンテキストを使用して違反を効果的に修正できるステップ5の基礎を構築します。構造化された準備により、LLM はコードの問題に対処するために必要なすべての情報を確実に取得できます。

LLM 修正のコンテキストの調整

私たちのシステムがどのようにコード修正を改善するかを理解するために、Pylintによってフラグが立てられた特定の違反について考えてみましょう。 コードファイルのblock_listed_name.py行60に違反があるというメッセージを受け取ったとします。

{
  "type": "convention",
  "module": "block_listed_name",
  "obj": "do_front",
  "line": 60,
  "column": 4,
  "endLine": 60,
  "endColumn": 7,
  "path": "cloned_repo/naming_conventions/block_listed_name.py",
  "symbol": "disallowed-name",
  "message": "Disallowed name \"foo\"",
  "message-id": "C0104"
}

この Pylint 違反から、変数 foo が許可されていない名前であることがわかります。 ただし、この情報の断片だけに基づいてLLMにこの問題を修正するように依頼しようとすると、応答はそれほど効果的ではありません。 なぜでしょうか。 LLMには、周囲のコンテキスト、つまりこの違反が発生する機能の全体像が欠けています。

ここで、コードベースのインデックス作成が重要になります

コードベースをマッピングしたので、今度は LLM にインデックスをクエリし、関数を含む do_front 周囲のコードを取得するように依頼できます。 LLMは、データベーススキーマに関する知識のおかげで、SQLクエリを生成することさえできます。 完全な関数定義を取得すると、LLM は問題をより完全に把握できます。

def do_front(front_filename, back_filename):
   """
   Front strategy: loop over front image,
   detect blue pixels there,
   substitute in pixels from back.
   Return changed front image.
   """
   foo = SimpleImage(front_filename)
   back = SimpleImage(back_filename)
   for y in range(foo.height):xc
       for x in range(foo.width):
           pixel = foo.get_pixel(x, y)
           # Detect blue pixels in front and replace with back pixels
           if pixel[2] > 2 * max(pixel[0], pixel[1]):
               back_pixel = back.get_pixel(x, y)
               foo.set_pixel(x, y, back_pixel)
   return foo

LLM が関数全体を確認できるようになったので、より意味のある修正を提案できます。 インデックス付きコードベースをクエリし、修正を実行した後に提案される内容は次のとおりです。

def do_front(front_filename, back_filename):
 """
    Front strategy: loop over front image,
 detect blue pixels there,
    substitute in pixels from back.
    Return changed front image.
    """
    front_image = SimpleImage(front)
    back_image = SimpleImage(back_filename)
    for y in range(front_image.height):
        for x in range(front_image.width            pixel = front_image.get_pixel(x y)
            # Detect blue pixels in front and replace with back pixels
            if pixel[2 >  * max(pixel[0 pixel[1]):
                back_pixel = back_image.get_pixel(x,)
                front_image.set_pixel(x,, back_pixel)
    return front_image

ここでは、変数 foo がより説明的な front_imageものに置き換えられ、コードがより読みやすく理解しやすくなっています。 重要なステップは、LLM に 1 行や違反メッセージだけでなく、正しい詳細レベル (最上位の範囲) を提供することでした。 適切なコンテキストがあれば、LLM のコード修正能力ははるかに効果的になり、最終的には開発プロセスが合理化されます。

これらの情報はすべて、設定したプロンプトを通じて LLM 自体によって取得され、インデックスが作成されることに注意してください。 この一連のプロンプトを通じて、アシスタントがコードベースを包括的に理解するところまで到達しました。 

この段階では、修正を求めるだけでなく、「60naming_conventions/block_listed_name.py行目の違反は何ですか?」などの質問をすると、アシスタントは次のように応答します。

On line 60 of naming_conventions/block_listed_name.py, there's a violation: Disallowed name 'foo'. The variable name 'foo' is discouraged because it doesn't convey meaningful information about its purpose.

ここでは Pylint に焦点を当ててきましたが、このアプローチは、コードを問題にマップする多くのツールと対話する新しい対話型方法を示しています。 Docker プロンプトランナーなどのアーキテクチャを通じて LLM をコンテナ化されたツールと統合することで、開発ワークフローのさまざまな側面を強化できます。

ツールの統合、LLMの認知機能の準備、シームレスなワークフローを組み合わせることで、開発エクスペリエンスを大幅に向上させることができることがわかりました。 この統合により、LLM は開発中に直接役立つツールを使用できるようになり、ここでは Pylint が焦点となっていますが、これはコードを問題にマップする多くのツールと対話する新しい対話型の方法も示しています。

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

Docker での取り組みの詳細については、 ニュースレターを購読してください。

さらに詳しく