🦔

テストを作成し、passするまでコードを自動修正する AI Agent「Micro Agent」を動かす

2025/01/07に公開

「Micro Agent」という面白そうなサービスを見つけたのでまとめてみました。
Micro Agentはテストを自動で作成し、それをpassするまでコードを自動で修正し続けてくれるAI Agentです。

以下にソースが公開されているのでぜひ見てください。

https://github.com/BuilderIO/micro-agent

Micro Agentは何をするのか?

Just run micro-agent, give it a prompt, and it'll generate a test and then iterate on code until all test cases pass.
(訳)
micro-agent を実行し、プロンプトを与えるだけで、テストを生成し、すべてのテストケースに合格するまでコードを反復的に改善します。

このようにAgentがテストを作成し、全てのテストケースをpassするまでコードを修正し続けます。

オールインワンで開発するAIコード生成ツールやLLMとの対話では、やはりどこかでコンパイルエラーが発生してうまくいかない、、、といったケースは経験があると思います。Micro Agentは全てにフォーカスするのではなく、狭い範囲であっても確実に動くコードを生成することを目的としています。


https://github.com/BuilderIO/micro-agent

処理の流れ

  1. 関数の説明: 自然言語により、関数の説明を作成します
  2. AIがテストを生成: プロンプトに基づいて、関数の予想される動作を指定するユニットテストを作成します
  3. AIがコードを生成: テストに合格すると考えられるコードをLLMが生成します
  4. テスト&修正の反復: 作成したコードがテストに合格するか検証し、passするまでコードを修正し続けます

実際に動かしてみる

やはり動かしてみないことには理解できないので、とりあえず動かしてみます。

※node.js v18以降が必要です。

1. インストール

$ npm install -g @builder.io/micro-agent

2. APIキーの設定

今回はOpenAIのAPIキーを設定します。

$ micro-agent config set OPENAI_KEY=<your token>
$ micro-agent config set MODEL=gpt-4o

3. プロジェクトを作成

micro-agentというディレクトリを作成しておきます。

$ mkdir micro-agent
$ cd micro-agent

micro-agentコマンドを実行することで、プロジェクトの初期設定が完了します。

$ micro-agent

4. 実行

file-to-edit.tsというファイルをメインにして、TODOアプリケーションのコードを作成してもらいます。コマンドを実行すると対話型インターフェースとなるので、「todo application」と入力しました。

$ micro-agent ./file-to-edit.ts

全てのテストが通ってコードが生成されました!

ちなみに以下ようなコードが生成され、やり直しは1回発生しました。
今回はtodoアプリの作成なのでそこまで複雑ではありませんが、どこまで複雑にしたらテストがなかなか通らないのかは気になります。
(このくらいのコードならどのLLMでも一発出しで出来そうなので...笑)

$ tree -I node_modules
.
├── file-to-edit.test.ts
├── file-to-edit.ts
├── package-lock.json
├── package.json
└── tsconfig.json
file-to-edit.ts
type Todo = {
  id: number;
  text: string;
  completed: boolean;
};

let todos: Todo[] = [];

export function addTodo(todo: Todo): void {
  if (todo.text.trim() !== '') {
    todos.push(todo);
  }
}

export function removeTodo(id: number): void {
  todos = todos.filter(todo => todo.id !== id);
}

export function getTodos(): Todo[] {
  return todos;
}

export function toggleTodo(id: number): void {
  todos = todos.map(todo =>
    todo.id === id ? { ...todo, completed: !todo.completed } : todo
  );
}
file-to-edit.test.ts
import { describe, it, expect } from 'vitest';
import { addTodo, removeTodo, getTodos, toggleTodo } from './file-to-edit';

describe('Todo Application', () => {
  it('should add a new todo item', () => {
    const todos = getTodos();
    const newTodo = { id: 1, text: 'Learn Vitest', completed: false };
    addTodo(newTodo);
    expect(todos).toContainEqual(newTodo);
  });

  it('should remove a todo item by id', () => {
    const newTodo = { id: 2, text: 'Write tests', completed: false };
    addTodo(newTodo);
    removeTodo(2);
    const todos = getTodos();
    expect(todos).not.toContainEqual(newTodo);
  });

  it('should toggle the completion status of a todo item', () => {
    const newTodo = { id: 3, text: 'Review code', completed: false };
    addTodo(newTodo);
    toggleTodo(3);
    const todos = getTodos();
    expect(todos.find(todo => todo.id === 3)?.completed).toBe(true);
  });

  it('should return all todos', () => {
    const todos = getTodos();
    expect(Array.isArray(todos)).toBe(true);
  });

  it('should handle removing a non-existent todo gracefully', () => {
    const initialTodos = getTodos().length;
    removeTodo(999);
    const todos = getTodos();
    expect(todos.length).toBe(initialTodos);
  });

  it('should handle toggling a non-existent todo gracefully', () => {
    const initialTodos = getTodos();
    toggleTodo(999);
    const todos = getTodos();
    expect(todos).toEqual(initialTodos);
  });

  it('should not add a todo with an empty text', () => {
    const initialTodos = getTodos().length;
    addTodo({ id: 4, text: '', completed: false });
    const todos = getTodos();
    expect(todos.length).toBe(initialTodos);
  });
});

以下、自分の実行時に撮り忘れたので公式ドキュメントから引用した動画を添付しておきます。。


Unit test matching より引用

まとめ

とりあえず動いたことは確認できましたが、これが実用的かどうかはもう少し検証が必要です。
まだ使いこなせてはいませんが、具体的なユースケースがあれば今後記事に追加していこうと思います。

Discussion