Claude Vision APIを使用した画像認識Web APIサーバー + 家計簿Web UI(Go実装、Modular Monolith設計)
Claude Vision API(Haiku 4.5)を使用してレシート画像から情報を抽出し、家計簿として管理するWebアプリケーション。Modular Monolith + Clean Architectureに基づいた設計により、高いテスタビリティと保守性を実現。
- Modular Monolith アーキテクチャ: 機能別モジュール分割による高い保守性
- Web UI: 標準の
html/templateのみを使用したシンプルなUI- レシート画像アップロード画面(ファイル選択・カメラ撮影対応)
- レシート認識結果表示画面
- 家計簿一覧画面(カテゴリ別集計付き)
- Claude Vision API: Claude Haiku 4.5による高精度な画像認識
- 用途別プロンプト最適化:
- レシート読み取り専用プロンプト(JSON形式で構造化データ抽出)
- 家計簿仕訳け専用プロンプト(カテゴリ自動判定)
- 汎用テキスト抽出プロンプト
- RESTful API: 標準の
net/httpのみを使用したシンプルな設計 - Clean Architecture設計: レイヤー分離、依存性注入(DI)による疎結合
- Prompt Caching: Claude APIのプロンプトキャッシュ機能を活用
- Redis Caching: アプリケーション層での24時間キャッシュ
- MySQL Database: レシート・家計簿データの永続化
- Docker対応: コンテナ化による環境依存の解決
- 高いテストカバレッジ: 90%以上のユニットテストカバレッジ
- 構造化ログ: log/slogによる構造化ログ出力
internal/
├── modules/
│ ├── vision/ # Vision API モジュール
│ │ ├── domain/ # AIResult エンティティ、リポジトリIF
│ │ ├── usecase/ # AI補正ユースケース
│ │ └── presentation/ # Vision API ハンドラー
│ ├── household/ # 家計簿モジュール
│ │ ├── domain/ # Receipt, ExpenseEntry エンティティ
│ │ ├── usecase/ # Receipt, Household ユースケース
│ │ └── presentation/ # Web UI ハンドラー
│ └── shared/ # 共有インフラストラクチャ
│ └── infrastructure/ # AI, Database, Cache 実装
├── presentation/ # プレゼンテーション層統合
│ ├── di/ # DIコンテナ
│ └── http/ # ルーター、ミドルウェア
└── config/ # 設定管理
┌─────────────────────────────────────────────┐
│ Presentation Layer │
│ - Web UI Handlers (html/template) │
│ - API Handlers (net/http) │
│ - Middleware (CORS, Logging, Recovery) │
│ - DI Container │
├─────────────────────────────────────────────┤
│ UseCase Layer │
│ - Vision: AI Correction UseCase │
│ - Household: Receipt, Household UseCase │
├─────────────────────────────────────────────┤
│ Domain Layer │
│ - Vision: AIResult │
│ - Household: Receipt, ExpenseEntry │
│ - Repository Interfaces │
├─────────────────────────────────────────────┤
│ Infrastructure Layer (Shared) │
│ - Claude Repository (Vision API) │
│ - BUN Repository (MySQL) │
│ - Redis Repository (Cache) │
└─────────────────────────────────────────────┘
- Docker & Docker Compose
- ANTHROPIC_API_KEY環境変数(必須)
# .envファイルを作成
cat > .env << EOF
ANTHROPIC_API_KEY=your-api-key-here
MYSQL_ROOT_PASSWORD=rootpass
EOF
# Docker Composeで起動(MySQL, Redis, APIサーバー)
docker compose up -d
# ログ確認
docker compose logs -f app
# 停止
docker compose down
# データも削除する場合
docker compose down -vブラウザで http://localhost:8080/ にアクセス
- ファイル選択ボタンから画像をアップロード(モバイルではカメラも選択可能)
- プレビュー表示後、アップロードボタンをクリック
- 自動的に結果画面にリダイレクト
http://localhost:8080/result?id=xxx
- 店舗名、購入日時、合計金額、税額を表示
- 商品明細(名前、数量、価格)を表形式で表示
- 家計簿一覧へのリンク
http://localhost:8080/household
- カテゴリ別集計(件数、合計金額)
- レシート一覧テーブル(日付降順)
- クリックでレシート詳細表示
curl http://localhost:8080/healthcurl -X POST http://localhost:8080/api/v1/vision/analyze \
-F "image=@document.png"
# レスポンス例
{
"success": true,
"text": "抽出されたテキスト...",
"tokens": {
"input_tokens": 1250,
"output_tokens": 320,
"total_tokens": 1570
}
}curl -X POST http://localhost:8080/api/v1/vision/receipt \
-F "image=@receipt.png"
# レスポンス例(JSON形式で構造化データを返す)
{
"success": true,
"text": "{\"store_name\":\"スーパーマーケット\",\"purchase_date\":\"2025-11-22 14:30\",\"total_amount\":1500,\"tax_amount\":150,\"items\":[{\"name\":\"野菜\",\"quantity\":1,\"price\":500}]}",
"tokens": {
"input_tokens": 1350,
"output_tokens": 280,
"total_tokens": 1630
}
}curl -X POST http://localhost:8080/api/v1/vision/categorize \
-H "Content-Type: application/json" \
-d '{
"receipt_info": "{\"store_name\":\"スーパーマーケット\",\"items\":[{\"name\":\"野菜\"}]}"
}'
# レスポンス例
{
"success": true,
"text": "{\"category\":\"食費\",\"confidence\":0.95,\"reason\":\"スーパーマーケットでの食品購入\"}",
"tokens": {
"input_tokens": 120,
"output_tokens": 80,
"total_tokens": 200
}
}Docker Composeで以下のサービスが起動します:
- app: Vision API Server (ポート: 8080)
- mysql: MySQL 8.0 (ポート: 3306)
- redis: Redis 7 (ポート: 6379)
# Go 1.23以上
go version
# 依存関係のインストール
go mod download# MySQL
docker run -d --name mysql \
-e MYSQL_ROOT_PASSWORD=rootpass \
-e MYSQL_DATABASE=household \
-p 3306:3306 \
mysql:8.0
# Redis
docker run -d --name redis \
-p 6379:6379 \
redis:7-alpine# 環境変数の設定
export ANTHROPIC_API_KEY=your-api-key-here
export MYSQL_ROOT_PASSWORD=rootpass
export PORT=8080
# ビルド
go build -o vision-api cmd/app/main.go
# 実行
./vision-apiconfig.yaml で設定をカスタマイズ可能:
anthropic:
api_key: ${ANTHROPIC_API_KEY}
model: claude-haiku-4-5-20251001
max_tokens: 4096
redis:
host: redis
port: 6379
password: ""
db: 0
mysql:
host: mysql
port: 3306
user: root
password: ${MYSQL_ROOT_PASSWORD}
database: householdANTHROPIC_API_KEY: Claude APIキー(必須)MYSQL_ROOT_PASSWORD: MySQLルートパスワード(デフォルト: rootpass)PORT: サーバーポート(デフォルト: 8080)
.
├── cmd/
│ └── app/
│ ├── main.go # エントリーポイント
│ └── main_test.go # Seamパターンによるテスト
├── internal/
│ ├── modules/ # Modular Monolith モジュール
│ │ ├── vision/ # Vision API モジュール
│ │ │ ├── domain/ # AIResult エンティティ
│ │ │ ├── usecase/ # AI補正ユースケース
│ │ │ └── presentation/ # Vision API ハンドラー
│ │ ├── household/ # 家計簿モジュール
│ │ │ ├── domain/ # Receipt, ExpenseEntry エンティティ
│ │ │ ├── usecase/ # Receipt, Household ユースケース
│ │ │ └── presentation/ # Web UI ハンドラー
│ │ └── shared/ # 共有インフラストラクチャ
│ │ └── infrastructure/ # AI, Database, Cache 実装
│ ├── presentation/ # プレゼンテーション層統合
│ │ ├── di/ # DIコンテナ
│ │ └── http/ # ルーター、ミドルウェア
│ └── config/ # 設定管理
├── web/ # Web UI リソース
│ ├── templates/ # html/template
│ │ ├── layout/ # ベースレイアウト
│ │ └── pages/ # ページテンプレート
│ └── static/ # 静的ファイル
│ └── css/ # スタイルシート
├── scripts/
│ └── init.sql # MySQL初期化スクリプト
├── testdata/ # テストデータ
├── Dockerfile # Docker設定
├── compose.yml # Docker Compose設定
├── Makefile # ビルドタスク
├── config.yaml # デフォルト設定
├── go.mod
├── go.sum
└── README.md
# すべてのテストを実行
go test ./...
# カバレッジレポート
go test -cover ./...
# 詳細なカバレッジ
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# TestContainers使用(Docker必須)
# MySQL, Redisコンテナが自動起動・再利用されます
go test ./internal/infrastructure/database/...
go test ./internal/infrastructure/cache/...# Lint実行
golangci-lint run ./...
# または Makefileを使用
make lintmake help # ヘルプ表示
make docker-build # Dockerイメージビルド(--no-cache)
make docker-run # Docker実行
make test # ローカルテスト
make test-coverage # カバレッジレポート
make lint # Lint実行
make clean # クリーンアップ- config: 90.9%
- modules/vision/domain: 100.0%
- modules/vision/usecase: 100.0%
- modules/household/domain/entity: 100.0%
- modules/household/usecase: 94.4%
- presentation/http/middleware: 100.0%
全体: 90%以上達成(ユニットテスト)
- 言語: Go 1.23+
- アーキテクチャ: Clean Architecture
- AI: Anthropic Claude API (Haiku 4.5)
- データベース: MySQL 8.0 (BUN ORM)
- キャッシュ: Redis 7
- ログ: log/slog (構造化ログ)
- テスト: TestContainers (MySQL, Redis)
- 設定: YAML (gopkg.in/yaml.v3)
- コンテナ: Docker & Docker Compose
# ログ確認
docker compose logs
# コンテナ再起動
docker compose down
docker compose up -d
# ボリューム削除して再起動
docker compose down -v
docker compose up -d# .envファイルを確認
cat .env
# 環境変数を設定
export ANTHROPIC_API_KEY=your-api-key-here
# Docker Composeで再起動
docker compose down
docker compose up -d# MySQLコンテナの状態確認
docker compose ps mysql
# MySQLログ確認
docker compose logs mysql
# 手動接続テスト
docker exec -it vision-mysql mysql -u root -p# Redisコンテナの状態確認
docker compose ps redis
# Redisログ確認
docker compose logs redis
# 手動接続テスト
docker exec -it vision-redis redis-cli pingTestContainersはDockerが必要です:
# Dockerが起動しているか確認
docker ps
# TestContainers用の環境変数(オプション)
export TESTCONTAINERS_RYUK_DISABLED=trueプルリクエストを歓迎します!
- このリポジトリをフォーク
- フィーチャーブランチを作成 (
git checkout -b feature/amazing-feature) - 変更をコミット (
git commit -m 'feat: add amazing feature') - ブランチにプッシュ (
git push origin feature/amazing-feature) - プルリクエストを作成
<type>: <subject>
<body>
<footer>
Type:
feat: 新機能fix: バグ修正docs: ドキュメントstyle: フォーマットrefactor: リファクタリングtest: テストchore: その他
MIT License
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Clean Architecture
- Effective Go
- Anthropic Claude API
- BUN ORM
- Redis
- TestContainers Go
- log/slog
- Docker
最終更新: 2025-11-24
バージョン: 3.0.0 (Modular Monolith + Web UI)
作成者: Yuji Okamoto