0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

AIエージェントと挑む! 高速データ処理アプリ POLCA-desktop 開発の舞台裏

Last updated at Posted at 2025-11-11

TL;DR

  • 複数のAIエージェントを使い分けて Polarsベースのデスクトップアプリを開発
  • Python →Rustへの移行で 起動時間が20秒 →瞬時に劇的改善
  • AIが得意な技術スタックを選ぶことが成功の鍵

はじめに

こんにちは!
私は インメモリカラムナーデータ処理技術、特に Apache Arrow や Polars に魅了され、個人的にアプリ開発に挑戦していいます。

この度、最新の技術に触れてみようと思い 最新の技術であるAIエージェントを活用し、ビッグデータ向け高速データ処理アプリ POLCA (POLars Cool Application) を開発しました。本記事では、AIエージェントによるコード生成から、アプリを完成に至るまでの、開発の裏側と試行錯誤の道のりをリアルにご紹介します。

POLCAとは?

Polarsライブラリを使った、ビッグデータ向け高速データ処理アプリです。

代表的な画面

主な機能

カテゴリ 機能
ファイル操作 CSV/Parquet形式の読み込み と 書き出し
データ操作 ソート、フィルタ、ジョイン、ユニオン、集計、計算、サンプリング  
列操作 追加、削除、リネーム
データ分析 プロファイリング、ピボットテーブル
パフォーマンス Polars エンジンによる 高速データ処理
多言語対応 日本語、英語

技術スタック

フロントエンド: React + TypeScript + AG Grid
バックエンド: Rust + Polars-Python、Rust + Polars-Rust (最終版)
フレームワーク: Electron、Tauri v1 (最終版)
IDE ツール: Visual Studio Code、GitHub Copilot

開発の旅路: 7つの試練、紆余曲折の道のり

試練1:Rustコンパイルエラーの地獄

使用AI: Vercel v0

バックエンド(Polars-Rust)でコンパイルエラーが多く発生しました。
IDE は Visual Studio Code を使用していたので、GitHub Copilot の助けを借りながら コードの修正を行なったが 結局 コンパイルエラーは終息せず 断念しました。

backend
// エラーの例
error[E0599]: no method named `pivot` found for struct `DataFrame`
error[E0308]: mismatched types
error[E0277]: trait bound not satisfied

原因: Polars-RustのAPI事例が少なく、AIの知識ベースが不足
教訓: AIは普及している技術の方が得意

Polars-Rust は諦めて、次は Polars-Pythonにしてみようと考えました。


試練2:Pythonで一発解決

使用AI: Claude Code

Polars-Pythonに切り替えたところ ...

すんなり動いた!
@app.post("/import/csv")
def import_csv(req: ImportCsv):
    df = pl.read_csv(filepath)
    tables[req.table_name] = df
    return {"message": "success"}

結果: 一発で動作
教訓: メジャーな技術スタックを選ぶことの重要性

この段階では フロントエンドとバックエンドは 別々に起動する必要があり、次は デスクトップアプリとして動作できるよう ひとつに まとめます。


試練3:起動時間20秒の悪夢

使用AI: Claude Code(フレームワークは 最初 Electron 次に Tauri)

デスクトップアプリ化したものの ...

起動時間の計測
$ time open polca-desktop.app
# バックエンド起動: 10〜20秒
# → フロントエンドでエラー: "バックエンドに接続できません"

原因: Polars-Pythonのimportに時間がかかる (Electron/Tauri とも同じ)

これだけで10秒以上...
import polars as pl

一時的な対応: フロントエンドにリトライ処理を追加

const waitForBackend = async () => {
  for (let i = 0; i < 30; i++) {
    try {
      await fetch('http://localhost:8000/');
      return true;
    } catch {
      await sleep(1000);
    }
  }
  return false;
};

接続中... nn秒 を表示

教訓: Polarsは依存ライブラリが多く、import時間が課題

polca-desktop 起動時 10〜20秒 待たされるのは ストレスなので、次は バックエンドを Polars-Rust にすることに 再度 チャレンジしました。


試練4:AIエージェントの使い分け

使用AI: MGX(MetaGPT X)

AIエージェントで Polars-Python を Rust に変換して見ました。Claude Codeで生成したPython→Rustの変換コードもコンパイルエラーが多発。
そこで別のAIエージェント「MGX」を試したところ ...

わずか数カ所の修正で動作!
pub async fn import_csv(
    state: web::Data<AppState>,
    req: web::Json<ImportCsv>,
) -> Result<HttpResponse> {
    let df = CsvReadOptions::default()
        .try_into_reader_with_file_path(filepath)?
        .finish()?;
    // ...
}

結果: ほぼそのまま動作
教訓:AIエージェントは得意分野が異なる

AI 得意領域
Vercel v0 UI/UXデザイン
Claude Code 汎用的な開発、リファクタリング 
MGX 技術変換、Rust特化

試練5:起動時間が瞬時に!

Rust版バックエンドでの起動時間が 144倍 高速化 できた!

起動時間計測
# Before (Polars-Python)
$ time open polca-desktop.app
real    0m18.234s

# After (Polars-Rust)
$ time open palca-desktop.app
real    0m0.127s

試練6:フロントエンドが消えた!?

Tauri版のリリースビルドで、フロントエンドが同梱されない謎の現象。

パッケージ内を確認
$ ls lolca-desktop.app/Contents/Resources/
# → フロントエンドのファイルがない!

Contents-Resources にはアイコンだけ ...

設定は正しいのに ...

tauri.conf.json
{
  "build": {
    "distDir": "../build",                  //  正しい
    "beforeBuildCommand": "npm run build"   //  正しい
  }
}

原因: MGX が生成した Rust コードにgenerate_context!()マクロがなかった

main.rs
// Before(エラー)
.run(tauri::generate_context!())     // この行がない!

// After(修正)
tauri::Builder::default()
    .setup(|app| { ... })
    .invoke_handler(tauri::generate_handler![...])
    .run(tauri::generate_context!())      // ✅ この行を追加
    .expect("error while running tauri application");

教訓: Tauri はビルド時 generate_context!()でフロントエンドを実行ファイルに埋め込む


試練7:謎の HTTP 404 Not Found エラー

デスクトップアプリは動作するのに 特定のリクエストだけHTTP 404 エラーになる。

GET /table/titanic?page=0&page_size=100   # → 404 Not Found

バックエンドのコードは正しいのに ...

解決策:Axumのルート定義に: を追加 + axumをバージョンダウン

Routerの設定
// Before
.route("/table/table_name", get(handlers::get_table_data))

// After
.route("/table/:table_name", get(handlers::get_table_data))
//             ^ コロン追加!
Cargo.toml
[dependencies]
axum = { version = "0.7.5" }    # バージョンを固定

教訓:ライブラリバージョンとAI生成コードの微妙な相性問題


AIエージェント開発で得た5つの教訓・知見

1. 広く普及している技術を選べ

技術 AI対応度 理由
Python ⭐⭐⭐⭐⭐ 豊富な学習データ
TypeScript ⭐⭐⭐⭐⭐ 広く使われている  
Rust ⭐⭐⭐ 事例は増加中
Polars-Rust ⭐⭐ まだ事例が少ない

2. AIエージェントを使い分けろ

3. パフォーマンスは言語選択が9割

バックエンド 起動時間 メモリ
Python (Polars) 18.234秒 123MB
Rust (Polars) 0.127秒 107MB

4. 生成コードを理解せよ

AIが生成したコードを ブラックボックスにしない。

main.rs
// このマクロが何をしているのか?
.run(tauri::generate_context!())
// → ビルド時にフロントエンドを埋め込む重要な処理

5. バージョン固定の勇気

頻繁に更新されるライブラリはバージョンを固定すべし。

Cargo.toml
[dependencies]
axum = { version = "0.7.5" }     # バージョンを固定
polars = { version = "0.33" } 

開発環境と使用ツール

開発環境

PC: MacBook Pro M1 メモリ 32GB
OS: macOS Tahoe 26.0.1
IDE: Visual Studio Code + GitHub Copilot  

使用AIエージェント

AI 用途 コスト
Vercel v0 UI設計 無料枠  
Claude Code 汎用開発 無料枠
MGX (MetaGPT X) Python → Rust変換  無料枠

技術スタック

// フロントエンド
const stack = {
  language: 'TypeScript',
  framework: 'React 18.2',
  ui: 'AG Grid 30.0 + Lucide Icons',
  state: 'React Hooks'
};

// バックエンド
const stack = {
  language: 'Rust',
  framework: 'axum 0.7.5',
  dataEngine: 'Polars 0.33'
};

// デスクトップ
const stack = {
  framework: 'Tauri 1.5', 
  bundler: 'DMG (macOS)'
};

参考:Tauri ビルドの仕組み

Pythonバックエンドの場合

Tauri は バックエンドが Rust を前提としているが、Python の場合、Sidecar 機能で Pythonコードを サブプロセスで動かす。事前に Pythonコードをバイナリ化 しておく必要があります。

# 1. Pythonをバイナリ化
pyinstaller --onefile \
    --hidden-import fastapi \
    --hidden-import polars \
    main.py

# 2. Tauriリソースに配置
cp dist/main src-tauri/binaries/

# 3. tauri.conf.jsonで指定
{
  "bundle": {
    "externalBin": ["binaries/main"]
  }
}

バイナリ化したコードは Contents-Resources 入る。

Rustバックエンドの場合

フロントエンドも一緒にコンパイルされ Contents-MacOS の実行ファイル に入る。

// main.rsで自動埋め込み
tauri::Builder::default()
    .run(tauri::generate_context!())
    // ↑ この1行でフロントエンドも一緒にコンパイル

まとめ: AIエージェント時代のエンジニアリング

開発を振り返って

紆余曲折を経て、ようやく満足できるレベルのアプリが完成しました。
7〜8年前、同様のアプリを手作業で開発していた頃と比べると、隔世の感 があります。
しかし、AIエージェントは、魔法の杖ではありません。

これからのエンジニアに必要なスキル

class ModernEngineer:
    def __init__(self):
        self.skills = {
            'prompt_engineering': 10,     # ⬆ 最重要
            'requirement_analysis': 10,   # ⬆ 重要
            'code_reading': 8,            # ⬆ 必須
            'traditional_coding': 5       # ⬇ 相対的に低下
        }
    
    def develop(self, requirement):
        # 1. 要件を正確に理解
        spec = self.analyze(requirement)
        
        # 2. AIに的確な指示
        code = ai.generate(spec)
        
        # 3. 生成コードを理解して修正
        fixed = self.review_and_fix(code)
        
        return fixed

参考資料

インスピレーション元

本プロジェクトは ESPERiC にインスパイアされました。
ESPERiCは独自の「成分分解法」を採用したインメモリカラムナーデータベースで、ビッグデータ処理の高速性が特徴です。

関連記事


おわりに

AIエージェントを活用した開発は、適切な技術選択とAIの使い分け、そして 生成コードへの理解 が成功の鍵です。
この記事が、AIエージェント開発に挑戦する方の一助となれば幸いです。

Happy Coding with AI!

最後まで お読み頂き ありがとうございました。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?