AIエージェントがあっても失敗した話

アイデアを思い付いたらパッとメモを取っておいて、AIエージェントのrate limitに空きができたら、実装プランを作らせて実装させる、みたいなことを今年頭からずっとやっている。その中にはenvrcctlみたいな、なかなか便利・セキュアな実績もあるし、この自宅鯖のVibeOps化も上手くいった例なのだけど、もちろんたくさん失敗もしてる。成功・失敗を問わず、ローカルのレポジトリとして色々残っているのだけれど、中でも見通しが甘かった例を挙げて他山の石となるべく書き捨てておく。

マルチエージェントの失敗

GitHub Copilot SDKというのがあって、これを使うとAIエージェントを自分で実装できる。できるのだが、どのエージェントにどのtoolをallowするかを実装するのが非常に難しくセキュアに実装できる見通しが立たなかったことと、マルチエージェントを協調動作させるのが非常に難しくて一度断念した。前者はAST(抽象構文木)として、あるコマンドでもサブコマンドによってallow/denyを分ける、みたいな制御がかなりキツい。後者は単一のエージェントであれば特に難しいことはない。ところが、複数のエージェントで責務分離させる際に、セマンティックに責務境界を設定するのが非常に難しい。かといって、deterministic(決定論的)に境界を置くと、かなり取りこぼしが発生することを発見した。

pg_metal_scanの失敗

もう一つ、しばらく粘ったけれど無理だったのが、pg_metal_scan(仮称)。海外さんのPG-Stromよろしく、Apple SiliconのUnified Memoryを使えば、Metalを使って高速にPostgreSQLのscanが実装できるのでは?と考えた。実はエディタのZedのmacOS版がMetalをRustで叩いており、スクロールが超快適だったりするのもヒントになっている。さて、PostgreSQLのエクステンション部分はCで、Metalを利用する部分はSwiftで実装したところ、100万行のデータでMetalを利用する方が2.75倍「遅い」。並列化するとかビットマスクを使うとか性能を向上させる試みをやり尽くして(他にもあるのかも知れないが)、それでも2.75倍。

原因は主にCとSwift間での結果の受け渡しがオーバーヘッドになり、Metalによる超並列スキャンの利点を潰してしまう。見通しとして、数十億行から数百億行ぐらい無いとMetalで勝てない。違う言い方をすると、それだけマルチコアCPUは高速化しているとも言える。

あと、これで実感したこととして、PostgreSQLにカラムナーストレージが無いのが痛い。Cassandraの例をひくまでもなく、最近のDBで言えばLanceDBがカラムナーを採用していて、Metalを利用するか否かと関係なく現在のPostgreSQLにはこういう処理は難しいなと。

AIエージェントがあれば何でも出来るわけでは無い。