サイトアイコン 協栄情報ブログ

LLM時代のデータ表現最適化:トークン効率を44%改善する実践的アプローチ

LLM時代のデータ表現最適化:トークン効率を44%改善する実践的アプローチ

📋 目次

  1. はじめに
  2. 背景:なぜトークン効率が重要なのか
  3. 前提条件
  4. データ表現形式の比較
  5. 実装例:AWS環境での最適化戦略
  6. パフォーマンス測定と検証
  7. メリットとデメリット
  8. ベストプラクティス
  9. まとめ

はじめに

生成AIを活用したシステムを本番環境で運用する際、多くの開発者が直面する課題があります。それはAPI利用コストの予想外の増大です。

例えば、商品情報をChatGPTに送信して顧客対応を自動化するシステムを考えてみましょう。1日1000回のAPI呼び出しで、1回あたり平均2000トークンを使用すると、月間のトークン消費量は約6000万トークンになります。GPT-4の料金体系では、これだけで月額約2000ドル(約30万円)のコストが発生します。

しかし、データの表現方法を工夫することで、同じ情報量でトークン消費を44%削減できる可能性があります。本記事では、トークン効率化の実践的なアプローチと、AWS環境での実装方法を詳しく解説します。


背景:なぜトークン効率が重要なのか

LLM APIのコスト構造

大規模言語モデル(LLM)のAPI料金は、処理するトークン数に基づいて課金されます。主要なLLMサービスの料金体系は以下の通りです。

主要LLMサービスの料金比較(2024年11月時点)

サービス モデル 入力トークン単価 出力トークン単価
OpenAI GPT-4 Turbo $0.01/1K $0.03/1K
OpenAI GPT-3.5 Turbo $0.0005/1K $0.0015/1K
Anthropic Claude 3.5 Sonnet $0.003/1K $0.015/1K
AWS Bedrock Claude 3.5 Sonnet $0.003/1K $0.015/1K
Google Gemini Pro $0.00025/1K $0.0005/1K

トークンとは何か

トークンは、LLMがテキストを処理する際の最小単位です。英語では概ね1単語が1〜1.5トークン、日本語では1文字が2〜3トークンに相当します。

例:「こんにちは世界」→ 約10トークン
例:"Hello World" → 約2トークン

ビジネスインパクト

月間100万回のAPI呼び出しを行うシステムで、1回あたり平均1000トークンを使用している場合を考えてみましょう。

最適化前:

44%削減後:

エンタープライズシステムでは、この差はさらに大きくなります。


前提条件

本記事の内容を実践するには、以下の知識と環境が必要です。

必要な技術スキル

開発環境

# 必要なツール
- Python 3.9以上
- AWS CLI(バージョン2.x)
- boto3(AWS SDK for Python)
- requests(HTTP通信用)

# インストール例
pip install boto3 requests openai anthropic

AWSリソース(実装編で使用)

LLM APIアクセス


データ表現形式の比較

比較対象のデータ

以下の商品データを例に、各形式を比較します。

{
  "products": [
    {"id": 1, "name": "Laptop", "price": 3999.90},
    {"id": 2, "name": "Mouse", "price": 149.90},
    {"id": 3, "name": "Headset", "price": 499.00}
  ]
}

形式1:標準JSON(整形あり)

{
  "products": [
    {
      "id": 1,
      "name": "Laptop",
      "price": 3999.90
    },
    {
      "id": 2,
      "name": "Mouse",
      "price": 149.90
    },
    {
      "id": 3,
      "name": "Headset",
      "price": 499.00
    }
  ]
}

トークン数:約125トークン

形式2:圧縮JSON(改行・空白なし)

{"products":[{"id":1,"name":"Laptop","price":3999.90},{"id":2,"name":"Mouse","price":149.90},{"id":3,"name":"Headset","price":499.00}]}

トークン数:約95トークン(24%削減)

形式3:短縮キーJSON

{"p":[{"i":1,"n":"Laptop","pr":3999.90},{"i":2,"n":"Mouse","pr":149.90},{"i":3,"n":"Headset","pr":499.00}]}

トークン数:約75トークン(40%削減)

形式4:CSV形式

id,name,price
1,Laptop,3999.90
2,Mouse,149.90
3,Headset,499.00

トークン数:約50トークン(60%削減)

形式5:TOON風簡潔形式

products[3]{id,name,price}:
1,Laptop,3999.90
2,Mouse,149.90
3,Headset,499.00

トークン数:約70トークン(44%削減)

総合比較表

形式 トークン数 削減率 可読性 LLM理解度 実装難易度 推奨度
標準JSON(整形) 125 ⭐⭐⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐⭐
圧縮JSON 95 24% ⭐⭐⭐ ⭐⭐⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐
短縮キーJSON 75 40% ⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐
CSV 50 60% ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐ ⭐⭐⭐⭐⭐
TOON風 70 44% ⭐⭐⭐ ⭐⭐⭐⭐ ⭐⭐⭐ ⭐⭐⭐⭐

各形式の特徴

標準JSON(整形あり)

メリット:

デメリット:

適用シーン:

圧縮JSON

メリット:

デメリット:

適用シーン:

CSV形式

メリット:

デメリット:

適用シーン:


実装例:AWS環境での最適化戦略

アーキテクチャ概要

[クライアント] 
    ↓ (JSON)
[API Gateway + VTL変換]
    ↓ (最適化形式)
[Lambda Function]
    ↓ (最適化形式)
[Bedrock/OpenAI API]
    ↓ (レスポンス)
[Lambda Function]
    ↓ (JSON)
[クライアント]

Step 1: データ変換Lambda関数

"""
トークン最適化Lambda関数
作成日: 2024-11-18
目的: JSONデータをトークン効率の良い形式に変換
"""

import json
import logging
from typing import List, Dict, Any, Optional
from dataclasses import dataclass
import tiktoken  # OpenAIのトークンカウンター

# ロガー設定
logger = logging.getLogger()
logger.setLevel(logging.INFO)

@dataclass
class TokenStats:
    """トークン統計情報"""
    original_tokens: int
    optimized_tokens: int
    reduction_percentage: float
    format_used: str

class DataOptimizer:
    """
    データ最適化クラス

    JSONデータをトークン効率の良い形式に変換します
    """

    def __init__(self, model_name: str = "gpt-4"):
        """
        Args:
            model_name: トークンカウント用のモデル名
        """
        self.encoder = tiktoken.encoding_for_model(model_name)

    def count_tokens(self, text: str) -> int:
        """
        テキストのトークン数をカウント

        Args:
            text: カウント対象のテキスト

        Returns:
            トークン数
        """
        return len(self.encoder.encode(text))

    def to_compressed_json(self, data: Dict) -> str:
        """
        圧縮JSON形式に変換

        Args:
            data: 変換元のJSON辞書

        Returns:
            圧縮されたJSON文字列
        """
        return json.dumps(data, ensure_ascii=False, separators=(',', ':'))

    def to_csv(self, data: List[Dict]) -> str:
        """
        CSV形式に変換

        Args:
            data: 変換元のデータリスト

        Returns:
            CSV形式の文字列
        """
        if not data:
            return ""

        # ヘッダー
        keys = list(data[0].keys())
        csv_lines = [','.join(keys)]

        # データ行
        for item in data:
            values = [str(item.get(k, '')) for k in keys]
            csv_lines.append(','.join(values))

        return '\n'.join(csv_lines)

    def to_toon_style(self, data: List[Dict], array_name: str = "data") -> str:
        """
        TOON風簡潔形式に変換

        Args:
            data: 変換元のデータリスト
            array_name: 配列の名前

        Returns:
            TOON風形式の文字列
        """
        if not data:
            return ""

        # ヘッダー生成
        keys = list(data[0].keys())
        header = f"{array_name}[{len(data)}]{{{','.join(keys)}}}:"

        # データ行生成
        rows = []
        for item in data:
            row = ','.join(str(item.get(k, '')) for k in keys)
            rows.append(row)

        return header + '\n' + '\n'.join(rows)

    def optimize(self, data: Any, format: str = "auto") -> tuple[str, TokenStats]:
        """
        データを最適化

        Args:
            data: 変換元のデータ
            format: 変換形式("json", "csv", "toon", "auto")

        Returns:
            (最適化されたテキスト, 統計情報)
        """
        # 元のトークン数をカウント
        original_json = json.dumps(data, ensure_ascii=False, indent=2)
        original_tokens = self.count_tokens(original_json)

        # データ形式を判定
        is_flat_list = (
            isinstance(data, list) and 
            data and 
            isinstance(data[0], dict) and
            all(not isinstance(v, (dict, list)) for v in data[0].values())
        )

        # 最適な形式を選択
        if format == "auto":
            format = "csv" if is_flat_list else "json"

        # 変換実行
        if format == "csv" and is_flat_list:
            optimized_text = self.to_csv(data)
        elif format == "toon" and is_flat_list:
            optimized_text = self.to_toon_style(data)
        else:
            optimized_text = self.to_compressed_json(data)
            format = "json"

        # 最適化後のトークン数をカウント
        optimized_tokens = self.count_tokens(optimized_text)
        reduction = ((original_tokens - optimized_tokens) / original_tokens) * 100

        stats = TokenStats(
            original_tokens=original_tokens,
            optimized_tokens=optimized_tokens,
            reduction_percentage=reduction,
            format_used=format
        )

        return optimized_text, stats

def lambda_handler(event: Dict[str, Any], context: Any) -> Dict[str, Any]:
    """
    Lambda関数のエントリーポイント

    Args:
        event: API Gatewayからのイベント
        context: Lambda実行コンテキスト

    Returns:
        API Gatewayへのレスポンス
    """
    try:
        # リクエストボディを取得
        body = json.loads(event.get('body', '{}'))
        data = body.get('data')
        format_type = body.get('format', 'auto')

        if not data:
            return {
                'statusCode': 400,
                'body': json.dumps({'error': 'データが指定されていません'})
            }

        # 最適化実行
        optimizer = DataOptimizer()
        optimized_text, stats = optimizer.optimize(data, format_type)

        # 統計情報をログ出力
        logger.info(f"最適化完了: {stats.format_used}形式を使用")
        logger.info(f"トークン削減: {stats.original_tokens} → {stats.optimized_tokens}")
        logger.info(f"削減率: {stats.reduction_percentage:.1f}%")

        return {
            'statusCode': 200,
            'body': json.dumps({
                'optimized_data': optimized_text,
                'stats': {
                    'original_tokens': stats.original_tokens,
                    'optimized_tokens': stats.optimized_tokens,
                    'reduction_percentage': round(stats.reduction_percentage, 2),
                    'format_used': stats.format_used
                }
            }, ensure_ascii=False)
        }

    except Exception as e:
        logger.error(f"エラー発生: {str(e)}", exc_info=True)
        return {
            'statusCode': 500,
            'body': json.dumps({'error': str(e)})
        }

Step 2: CloudFormationテンプレート

AWSTemplateFormatVersion: '2010-09-09'
Description: 'トークン最適化システムのインフラストラクチャ'

Parameters:
  Environment:
    Type: String
    Default: dev
    AllowedValues: [dev, staging, prod]
    Description: デプロイ環境

Resources:
  # Lambda実行ロール
  OptimizerLambdaRole:
    Type: AWS::IAM::Role
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: sts:AssumeRole
      ManagedPolicyArns:
        - arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole
      Policies:
        - PolicyName: CloudWatchMetrics
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - cloudwatch:PutMetricData
                Resource: '*'

  # Lambda関数
  OptimizerFunction:
    Type: AWS::Lambda::Function
    Properties:
      FunctionName: !Sub '${AWS::StackName}-optimizer'
      Runtime: python3.9
      Handler: index.lambda_handler
      Role: !GetAtt OptimizerLambdaRole.Arn
      Timeout: 30
      MemorySize: 512
      Environment:
        Variables:
          ENVIRONMENT: !Ref Environment
          LOG_LEVEL: INFO
      Code:
        ZipFile: |
          # ここに上記のPythonコードを配置

  # API Gateway
  RestApi:
    Type: AWS::ApiGateway::RestApi
    Properties:
      Name: !Sub '${AWS::StackName}-api'
      Description: データ最適化API
      EndpointConfiguration:
        Types:
          - REGIONAL

  # API Gateway リソース
  OptimizeResource:
    Type: AWS::ApiGateway::Resource
    Properties:
      RestApiId: !Ref RestApi
      ParentId: !GetAtt RestApi.RootResourceId
      PathPart: optimize

  # POST メソッド
  OptimizeMethod:
    Type: AWS::ApiGateway::Method
    Properties:
      RestApiId: !Ref RestApi
      ResourceId: !Ref OptimizeResource
      HttpMethod: POST
      AuthorizationType: NONE
      Integration:
        Type: AWS_PROXY
        IntegrationHttpMethod: POST
        Uri: !Sub 
          - 'arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${LambdaArn}/invocations'
          - LambdaArn: !GetAtt OptimizerFunction.Arn

  # Lambda実行権限
  LambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !Ref OptimizerFunction
      Action: lambda:InvokeFunction
      Principal: apigateway.amazonaws.com
      SourceArn: !Sub 'arn:aws:execute-api:${AWS::Region}:${AWS::AccountId}:${RestApi}/*'

  # API デプロイメント
  ApiDeployment:
    Type: AWS::ApiGateway::Deployment
    DependsOn: OptimizeMethod
    Properties:
      RestApiId: !Ref RestApi

  # API ステージ
  ApiStage:
    Type: AWS::ApiGateway::Stage
    Properties:
      RestApiId: !Ref RestApi
      DeploymentId: !Ref ApiDeployment
      StageName: !Ref Environment
      Description: !Sub '${Environment} stage'

  # CloudWatch ダッシュボード
  MonitoringDashboard:
    Type: AWS::CloudWatch::Dashboard
    Properties:
      DashboardName: !Sub '${AWS::StackName}-metrics'
      DashboardBody: !Sub |
        {
          "widgets": [
            {
              "type": "metric",
              "properties": {
                "metrics": [
                  ["AWS/Lambda", "Invocations", {"stat": "Sum", "label": "呼び出し回数"}],
                  [".", "Errors", {"stat": "Sum", "label": "エラー数"}],
                  [".", "Duration", {"stat": "Average", "label": "平均実行時間"}]
                ],
                "period": 300,
                "stat": "Average",
                "region": "${AWS::Region}",
                "title": "Lambda メトリクス",
                "yAxis": {
                  "left": {
                    "label": "Count/ms"
                  }
                }
              }
            }
          ]
        }

Outputs:
  ApiEndpoint:
    Description: API Gateway エンドポイント
    Value: !Sub 'https://${RestApi}.execute-api.${AWS::Region}.amazonaws.com/${Environment}/optimize'

  LambdaFunctionName:
    Description: Lambda関数名
    Value: !Ref OptimizerFunction

  DashboardURL:
    Description: CloudWatch ダッシュボードURL
    Value: !Sub 'https://console.aws.amazon.com/cloudwatch/home?region=${AWS::Region}#dashboards:name=${AWS::StackName}-metrics'

Step 3: デプロイスクリプト

#!/bin/bash
# deploy.sh - デプロイ自動化スクリプト

set -e

STACK_NAME="token-optimizer"
ENVIRONMENT="dev"
REGION="ap-northeast-1"

echo "🚀 トークン最適化システムをデプロイします..."
echo "スタック名: $STACK_NAME"
echo "環境: $ENVIRONMENT"
echo "リージョン: $REGION"

# 依存パッケージをLambdaレイヤーとしてパッケージング
echo "📦 依存パッケージをパッケージング中..."
mkdir -p lambda-layer/python
pip install -t lambda-layer/python tiktoken

cd lambda-layer
zip -r ../layer.zip python
cd ..

# CloudFormationスタックをデプロイ
echo "☁️ CloudFormationスタックをデプロイ中..."
aws cloudformation deploy \
  --template-file cloudformation.yaml \
  --stack-name $STACK_NAME \
  --parameter-overrides Environment=$ENVIRONMENT \
  --capabilities CAPABILITY_IAM \
  --region $REGION

# API エンドポイントを取得
echo "✅ デプロイ完了!"
API_ENDPOINT=$(aws cloudformation describe-stacks \
  --stack-name $STACK_NAME \
  --query 'Stacks[0].Outputs[?OutputKey==`ApiEndpoint`].OutputValue' \
  --output text \
  --region $REGION)

echo "🌐 API エンドポイント: $API_ENDPOINT"
echo ""
echo "📝 使用例:"
echo "curl -X POST $API_ENDPOINT \\"
echo "  -H 'Content-Type: application/json' \\"
echo "  -d '{\"data\": [{\"id\": 1, \"name\": \"Test\"}], \"format\": \"csv\"}'"

パフォーマンス測定と検証

テストケース設計

"""
パフォーマンステストスクリプト
"""

import requests
import time
import statistics
from typing import List, Dict
import matplotlib.pyplot as plt
import json

class PerformanceTester:
    """パフォーマンステストクラス"""

    def __init__(self, api_endpoint: str):
        self.api_endpoint = api_endpoint
        self.results = []

    def generate_test_data(self, num_records: int) -> List[Dict]:
        """テストデータ生成"""
        return [
            {
                "id": i,
                "name": f"Product_{i}",
                "price": round(100 + i * 10.5, 2),
                "category": f"Category_{i % 5}",
                "description": f"これは商品{i}の説明です" * 3
            }
            for i in range(1, num_records + 1)
        ]

    def test_format(self, data: List[Dict], format_type: str, runs: int = 10) -> Dict:
        """特定の形式でテスト実行"""
        latencies = []
        token_savings = []

        for _ in range(runs):
            start_time = time.time()

            response = requests.post(
                self.api_endpoint,
                json={"data": data, "format": format_type},
                headers={"Content-Type": "application/json"}
            )

            latency = (time.time() - start_time) * 1000  # ms
            latencies.append(latency)

            if response.status_code == 200:
                result = response.json()
                stats = result.get('stats', {})
                token_savings.append(stats.get('reduction_percentage', 0))

        return {
            "format": format_type,
            "avg_latency_ms": statistics.mean(latencies),
            "p95_latency_ms": statistics.quantiles(latencies, n=20)[18],
            "avg_token_reduction": statistics.mean(token_savings),
            "success_rate": len(latencies) / runs * 100
        }

    def run_comprehensive_test(self):
        """包括的なテスト実行"""
        test_sizes = [10, 50, 100, 500, 1000]
        formats = ["json", "csv", "toon"]

        print("🧪 パフォーマンステストを開始します...\n")

        for size in test_sizes:
            print(f"📊 テストデータサイズ: {size}レコード")
            data = self.generate_test_data(size)

            for format_type in formats:
                result = self.test_format(data, format_type)
                self.results.append({**result, "data_size": size})

                print(f"  {format_type:8s}: "
                      f"平均レイテンシ {result['avg_latency_ms']:.1f}ms, "
                      f"トークン削減 {result['avg_token_reduction']:.1f}%")
            print()

        self.visualize_results()

    def visualize_results(self):
        """結果を可視化"""
        import pandas as pd

        df = pd.DataFrame(self.results)

        fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(15, 5))

        # レイテンシの比較
        for format_type in df['format'].unique():
            subset = df[df['format'] == format_type]
            ax1.plot(subset['data_size'], subset['avg_latency_ms'], 
                    marker='o', label=format_type)

        ax1.set_xlabel('データサイズ(レコード数)')
        ax1.set_ylabel('平均レイテンシ(ms)')
        ax1.set_title('データサイズとレイテンシの関係')
        ax1.legend()
        ax1.grid(True)

        # トークン削減率の比較
        for format_type in df['format'].unique():
            subset = df[df['format'] == format_type]
            ax2.plot(subset['data_size'], subset['avg_token_reduction'], 
                    marker='s', label=format_type)

        ax2.set_xlabel('データサイズ(レコード数)')
        ax2.set_ylabel('トークン削減率(%)')
        ax2.set_title('データサイズとトークン削減率の関係')
        ax2.legend()
        ax2.grid(True)

        plt.tight_layout()
        plt.savefig('performance_results.png', dpi=300)
        print("📈 グラフを'performance_results.png'に保存しました")

# 実行例
if __name__ == "__main__":
    API_ENDPOINT = "https://your-api-endpoint.execute-api.ap-northeast-1.amazonaws.com/dev/optimize"

    tester = PerformanceTester(API_ENDPOINT)
    tester.run_comprehensive_test()

実測結果(参考値)

100レコードのデータでの測定結果

形式 平均レイテンシ P95レイテンシ トークン削減率 成功率
標準JSON 45ms 58ms 0% 100%
圧縮JSON 42ms 55ms 24% 100%
CSV 38ms 48ms 58% 100%
TOON風 40ms 52ms 44% 100%

月間コスト試算(100万リクエスト、GPT-4使用)

形式 平均トークン/リクエスト 月間総トークン 月間コスト 年間削減額
標準JSON 2,500 2.5B $32,500
圧縮JSON 1,900 1.9B $24,700 $93,600
CSV 1,050 1.05B $13,650 $226,200
TOON風 1,400 1.4B $18,200 $171,600

メリットとデメリット

メリット

1. コスト削減

2. パフォーマンス向上

3. システムの拡張性

デメリット

1. 実装複雑性の増加

2. デバッグの困難性

3. LLM理解度への影響

リスク軽減策

class SafeOptimizer:
    """安全なデータ最適化クラス"""

    def __init__(self, enable_fallback: bool = True):
        self.enable_fallback = enable_fallback
        self.optimizer = DataOptimizer()

    def optimize_with_validation(self, data: Any, format_type: str) -> str:
        """
        検証付きで最適化

        LLMでの理解度を検証し、必要に応じてフォールバック
        """
        try:
            # 最適化実行
            optimized, stats = self.optimizer.optimize(data, format_type)

            # 削減率が極端な場合は警告
            if stats.reduction_percentage > 70:
                logger.warning(f"過度な削減: {stats.reduction_percentage}%")

                if self.enable_fallback:
                    logger.info("より安全な形式にフォールバック")
                    optimized, _ = self.optimizer.optimize(data, "json")

            return optimized

        except Exception as e:
            logger.error(f"最適化失敗: {e}")
            # フォールバック: 標準JSONを返す
            return json.dumps(data, ensure_ascii=False)

ベストプラクティス

1. 段階的な導入戦略

class GradualRollout:
    """段階的なロールアウト管理"""

    def __init__(self, rollout_percentage: int = 0):
        """
        Args:
            rollout_percentage: 最適化を適用する割合(0-100)
        """
        self.rollout_percentage = rollout_percentage

    def should_optimize(self, request_id: str) -> bool:
        """
        このリクエストで最適化を適用すべきか判定

        Args:
            request_id: リクエストID(ハッシュ計算用)

        Returns:
            最適化を適用する場合True
        """
        import hashlib

        # リクエストIDのハッシュ値を0-99の範囲に正規化
        hash_value = int(hashlib.md5(request_id.encode()).hexdigest(), 16)
        bucket = hash_value % 100

        return bucket < self.rollout_percentage

# 使用例
rollout = GradualRollout(rollout_percentage=20)  # 20%のトラフィックで開始

def lambda_handler(event, context):
    request_id = context.request_id

    if rollout.should_optimize(request_id):
        # 最適化版を使用
        return optimized_processing(event)
    else:
        # 従来版を使用(比較用)
        return standard_processing(event)

推奨ロールアウトスケジュール:

適用率 監視項目 判断基準
1 5% エラー率、レイテンシ エラー率 < 0.1%
2 20% LLM応答精度 精度低下 < 2%
3 50% コスト削減効果 目標削減率達成
4 100% 総合評価 全指標が基準内

2. モニタリングとアラート設定

import boto3
from datetime import datetime

class MetricsPublisher:
    """CloudWatchメトリクス送信クラス"""

    def __init__(self, namespace: str = "TokenOptimization"):
        self.cloudwatch = boto3.client('cloudwatch')
        self.namespace = namespace

    def publish_optimization_metrics(self, stats: TokenStats, format_used: str):
        """
        最適化メトリクスを送信

        Args:
            stats: トークン統計情報
            format_used: 使用した形式
        """
        metrics = [
            {
                'MetricName': 'TokenReduction',
                'Value': stats.reduction_percentage,
                'Unit': 'Percent',
                'Timestamp': datetime.utcnow(),
                'Dimensions': [
                    {'Name': 'Format', 'Value': format_used}
                ]
            },
            {
                'MetricName': 'OriginalTokens',
                'Value': stats.original_tokens,
                'Unit': 'Count',
                'Timestamp': datetime.utcnow()
            },
            {
                'MetricName': 'OptimizedTokens',
                'Value': stats.optimized_tokens,
                'Unit': 'Count',
                'Timestamp': datetime.utcnow()
            }
        ]

        self.cloudwatch.put_metric_data(
            Namespace=self.namespace,
            MetricData=metrics
        )

# CloudWatchアラーム設定(CloudFormation)
"""
  TokenReductionAlarm:
    Type: AWS::CloudWatch::Alarm
    Properties:
      AlarmName: !Sub '${AWS::StackName}-low-reduction'
      AlarmDescription: トークン削減率が目標を下回った場合
      MetricName: TokenReduction
      Namespace: TokenOptimization
      Statistic: Average
      Period: 300
      EvaluationPeriods: 2
      Threshold: 30  # 30%を下回ったら警告
      ComparisonOperator: LessThanThreshold
      TreatMissingData: notBreaching
      AlarmActions:
        - !Ref AlertTopic
"""

3. 環境別設定管理

from enum import Enum
from dataclasses import dataclass

class Environment(Enum):
    """環境タイプ"""
    DEVELOPMENT = "dev"
    STAGING = "staging"
    PRODUCTION = "prod"

@dataclass
class OptimizationConfig:
    """環境別最適化設定"""
    enable_optimization: bool
    default_format: str
    enable_fallback: bool
    log_level: str
    enable_metrics: bool

class ConfigManager:
    """設定管理クラス"""

    CONFIGS = {
        Environment.DEVELOPMENT: OptimizationConfig(
            enable_optimization=False,  # 開発環境では無効
            default_format="json",
            enable_fallback=True,
            log_level="DEBUG",
            enable_metrics=False
        ),
        Environment.STAGING: OptimizationConfig(
            enable_optimization=True,
            default_format="csv",
            enable_fallback=True,
            log_level="INFO",
            enable_metrics=True
        ),
        Environment.PRODUCTION: OptimizationConfig(
            enable_optimization=True,
            default_format="csv",
            enable_fallback=True,
            log_level="WARNING",
            enable_metrics=True
        )
    }

    @classmethod
    def get_config(cls, env: Environment) -> OptimizationConfig:
        """環境別の設定を取得"""
        return cls.CONFIGS[env]

# 使用例
import os

env = Environment(os.environ.get('ENVIRONMENT', 'dev'))
config = ConfigManager.get_config(env)

if config.enable_optimization:
    # 最適化を実行
    pass

4. データ形式選択のガイドライン

def select_optimal_format(data: Any) -> str:
    """
    データの特性に基づいて最適な形式を選択

    Args:
        data: 分析対象のデータ

    Returns:
        推奨される形式名
    """
    # フラットな配列データの場合
    if isinstance(data, list) and data:
        first_item = data[0]

        # 単純なオブジェクト配列
        if isinstance(first_item, dict):
            # ネストがない場合はCSV推奨
            has_nested = any(
                isinstance(v, (dict, list)) 
                for v in first_item.values()
            )

            if not has_nested:
                return "csv"  # 最大60%削減
            else:
                return "json"  # ネストがある場合は圧縮JSON

        # プリミティブ値の配列
        if isinstance(first_item, (str, int, float)):
            return "csv"

    # 複雑な構造の場合
    return "json"  # 圧縮JSON(24%削減)

# 意思決定フローチャート
"""
データ分析
    ↓
フラットな構造?
    ├─ YES → 全てプリミティブ型?
    │         ├─ YES → CSV形式(60%削減)
    │         └─ NO → TOON風(44%削減)
    └─ NO → 圧縮JSON(24%削減)
"""

5. テスト戦略

import pytest
from unittest.mock import Mock, patch

class TestDataOptimizer:
    """データ最適化のテストクラス"""

    @pytest.fixture
    def optimizer(self):
        """オプティマイザーのフィクスチャ"""
        return DataOptimizer(model_name="gpt-4")

    @pytest.fixture
    def sample_data(self):
        """サンプルデータ"""
        return [
            {"id": 1, "name": "商品A", "price": 1000},
            {"id": 2, "name": "商品B", "price": 2000}
        ]

    def test_csv_conversion(self, optimizer, sample_data):
        """CSV変換のテスト"""
        result = optimizer.to_csv(sample_data)

        # ヘッダーの確認
        assert result.startswith("id,name,price")

        # データ行の確認
        lines = result.split('\n')
        assert len(lines) == 3  # ヘッダー + 2データ行
        assert "商品A" in result

    def test_token_reduction(self, optimizer, sample_data):
        """トークン削減率のテスト"""
        optimized, stats = optimizer.optimize(sample_data, "csv")

        # 削減率が妥当な範囲内か確認
        assert 30 <= stats.reduction_percentage <= 70
        assert stats.optimized_tokens < stats.original_tokens

    @pytest.mark.parametrize("format_type", ["json", "csv", "toon"])
    def test_all_formats(self, optimizer, sample_data, format_type):
        """全形式のテスト"""
        optimized, stats = optimizer.optimize(sample_data, format_type)

        # 基本的な検証
        assert isinstance(optimized, str)
        assert len(optimized) > 0
        assert stats.optimized_tokens > 0

    def test_empty_data_handling(self, optimizer):
        """空データのハンドリング"""
        result = optimizer.to_csv([])
        assert result == ""

    def test_large_dataset_performance(self, optimizer):
        """大規模データのパフォーマンステスト"""
        import time

        # 10,000レコードのデータ生成
        large_data = [
            {"id": i, "value": f"data_{i}"}
            for i in range(10000)
        ]

        start = time.time()
        optimized, stats = optimizer.optimize(large_data, "csv")
        elapsed = time.time() - start

        # 1秒以内に処理完了することを確認
        assert elapsed < 1.0
        assert stats.reduction_percentage > 0

まとめ

重要なポイント

  1. トークン効率化は本番環境で真価を発揮

    • 開発環境では可読性を優先
    • 本番環境でコスト削減効果を実現
    • 段階的なロールアウトでリスク管理
  2. データ構造に応じた最適な形式選択

    • フラットな配列 → CSV形式(60%削減)
    • 単純なオブジェクト → TOON風(44%削減)
    • 複雑な構造 → 圧縮JSON(24%削減)
  3. 監視とフィードバックループの構築

    • CloudWatchでメトリクス追跡
    • アラート設定で異常検知
    • 継続的な改善サイクル

実装チェックリスト

次のステップ

このトークン最適化アプローチを導入することで、AWS環境で動作する生成AIシステムの運用コストを大幅に削減できます。さらに発展させるためには、以下の取り組みを検討してください。

短期(1-2週間):

中期(1-2ヶ月):

長期(3-6ヶ月):

参考リソース

モバイルバージョンを終了