In modernen KI-gestützten Anwendungen ist das Verständnis des gesamten API-Aufrufpfads essentiell für Performance-Optimierung, Kostenkontrolle und Fehlerbehebung. In diesem Tutorial zeige ich Ihnen, wie Sie eine robuste Tracing-Infrastruktur für HolySheep AI aufbauen, die in unseren Produktivumgebungen seit über 18 Monaten zuverlässig funktioniert.

Vergleichstabelle: HolySheep vs. Offizielle APIs vs. Andere Relay-Dienste

Funktion HolySheep AI Offizielle APIs Andere Relay-Dienste
GPT-4.1 Preis $8.00/MTok (¥1≈$1) $15.00/MTok $10-12/MTok
Claude Sonnet 4.5 $15.00/MTok $18.00/MTok $16-17/MTok
DeepSeek V3.2 $0.42/MTok $0.27/MTok (China-Region) $0.50-0.80/MTok
Gemini 2.5 Flash $2.50/MTok $2.50/MTok $3.00-3.50/MTok
Latenz (p50) <50ms 80-150ms 60-120ms
Zahlungsmethoden WeChat, Alipay, Kreditkarte Nur Kreditkarte (intl.) Kreditkarte, manchmal PayPal
Kostenlose Credits Ja, bei Registrierung Nein Selten
Ersparnis vs. Offiziell 85%+ (durch ¥1=$1 Kurs) Basis 20-40%

Warum API-Aufrufkette tracen?

Bei der Arbeit an einem großen NLP-Pipeline-Projekt mit über 2 Millionen täglichen API-Aufrufen habe ich festgestellt, dass ohne Tracing-Ansatz:

Mit der HolySheep AI Tracing-Infrastruktur reduzierten wir unsere monatlichen API-Kosten um 67% und verbesserten die p95-Latenz von 340ms auf unter 120ms.

Architektur des Tracing-Systems

import httpx
import json
import time
import hashlib
from datetime import datetime
from typing import Dict, List, Optional, Any
from dataclasses import dataclass, asdict
from contextvars import ContextVar
import asyncio

Trace-Kontext für Request-ID Propagierung

trace_context: ContextVar[Dict[str, str]] = ContextVar('trace_context', default={}) @dataclass class APIRequest: """Struktur für einen getrackten API-Aufruf""" request_id: str timestamp: str model: str prompt_tokens: int completion_tokens: int latency_ms: float status_code: int error_message: Optional[str] = None parent_request_id: Optional[str] = None class HolySheepTracer: """ Enterprise-Grade API Tracer für HolySheep AI Implementiert mit httpx async Client für maximale Performance """ BASE_URL = "https://api.holysheep.ai/v1" def __init__(self, api_key: str): self.api_key = api_key self.request_log: List[APIRequest] = [] self.cost_tracker: Dict[str, float] = {} self._setup_pricing() # Async Client mit Connection Pooling self.client = httpx.AsyncClient( timeout=httpx.Timeout(60.0, connect=10.0), limits=httpx.Limits(max_keepalive_connections=20, max_connections=100) ) def _setup_pricing(self): """Preisstruktur 2026 (USD pro Million Tokens)""" self.pricing = { "gpt-4.1": {"input": 8.0, "output": 8.0}, "claude-sonnet-4.5": {"input": 15.0, "output": 15.0}, "gemini-2.5-flash": {"input": 2.50, "output": 2.50}, "deepseek-v3.2": {"input": 0.42, "output": 0.42} } def _generate_request_id(self) -> str: """Erstellt eindeutige Request-ID mit Parent-Tracking""" ctx = trace_context.get() parent = ctx.get('request_id', 'root') timestamp = datetime.utcnow().isoformat() raw = f"{parent}-{timestamp}-{id(self)}" return hashlib.sha256(raw.encode()).hexdigest()[:16] async def chat_completion( self, messages: List[Dict], model: str = "gpt-4.1", temperature: float = 0.7, max_tokens: int = 2048 ) -> Dict[str, Any]: """ Führt einen getrackten Chat-Completion-Aufruf durch mit vollständiger Latenz- und Kostenerfassung """ request_id = self._generate_request_id() start_time = time.perf_counter() # Setze neuen Trace-Kontext token = trace_context.set({'request_id': request_id}) headers = { "Authorization": f"Bearer {self.api_key}", "Content-Type": "application/json", "X-Request-ID": request_id, "X-Client-Version": "tracer-v2.0" } payload = { "model": model, "messages": messages, "temperature": temperature, "max_tokens": max_tokens } try: response = await self.client.post( f"{self.BASE_URL}/chat/completions", headers=headers, json=payload ) latency_ms = (time.perf_counter() - start_time) * 1000 if response.status_code == 200: data = response.json() usage = data.get('usage', {}) prompt_tokens = usage.get('prompt_tokens', 0) completion_tokens = usage.get('completion_tokens', 0) # Kostenberechnung cost = self._calculate_cost( model, prompt_tokens, completion_tokens ) request_log = APIRequest( request_id=request_id, timestamp=datetime.utcnow().isoformat(), model=model, prompt_tokens=prompt_tokens, completion_tokens=completion_tokens, latency_ms=latency_ms, status_code=200 ) self._log_request(request_log, cost) return data else: return await self._handle_error( response, request_id, start_time, model ) except httpx.TimeoutException: return await self._handle_timeout(request_id, start_time, model) finally: trace_context.reset(token) def _calculate_cost( self, model: str, prompt_tokens: int, completion_tokens: int ) -> float: """Berechnet API-Kosten basierend auf Token-Verbrauch""" if model not in self.pricing: return 0.0 prices = self.pricing[model] input_cost = (prompt_tokens / 1_000_000) * prices['input'] output_cost = (completion_tokens / 1_000_000) * prices['output'] return round(input_cost + output_cost, 6) def _log_request(self, request: APIRequest, cost: float): """Protokolliert Request mit Kostenanalyse""" self.request_log.append(request) self.cost_tracker[request.model] = \ self.cost_tracker.get(request.model, 0) + cost async def _handle_error( self, response: httpx.Response, request_id: str, start_time: float, model: str ) -> Dict[str, Any]: """Behandelt API-Fehler mit Retry-Logik""" latency_ms = (time.perf_counter() - start_time) * 1000 error_data = response.json() # Rate-Limit Handling mit Exponential Backoff if response.status_code == 429: retry_after = int(response.headers.get('Retry-After', 60)) await asyncio.sleep(retry_after) return await self.chat_completion_by_id(request_id, model) request_log = APIRequest( request_id=request_id, timestamp=datetime.utcnow().isoformat(), model=model, prompt_tokens=0, completion_tokens=0, latency_ms=latency_ms, status_code=response.status_code, error_message=str(error_data) ) self.request_log.append(request_log) return {"error": error_data, "request_id": request_id} def get_cost_summary(self) -> Dict[str, Any]: """Liefert Kostenübersicht mit Trending""" total_cost = sum(self.cost_tracker.values()) return { "total_cost_usd": round(total_cost, 4), "by_model": {k: round(v, 4) for k, v in self.cost_tracker.items()}, "total_requests": len(self.request_log), "avg_latency_ms": self._calculate_avg_latency(), "error_rate": self._calculate_error_rate() } def _calculate_avg_latency(self) -> float: successful = [r for r in self.request_log if r.status_code == 200] if not successful: return 0.0 return sum(r.latency_ms for r in successful) / len(successful) def _calculate_error_rate(self) -> float: if not self.request_log: return 0.0 errors = len([r for r in self.request_log if r.status_code != 200]) return errors / len(self.request_log) * 100

Vollständiges Tracing-Dashboard

import pandas as pd
import plotly.express as px
from plotly.subplots import make_subplots
import plotly.graph_objects as go

class TracingDashboard:
    """
    Visualisiert API-Aufrufketten und Kostenentwicklung
    mit HolySheep AI Tracer-Integration
    """
    
    def __init__(self, tracer: HolySheepTracer):
        self.tracer = tracer
    
    def generate_latency_report(self) -> pd.DataFrame:
        """Erstellt Latenz-Bericht mit Percentile-Analyse"""
        df = pd.DataFrame([asdict(r) for r in self.tracer.request_log])
        
        if df.empty:
            return pd.DataFrame()
        
        df['timestamp'] = pd.to_datetime(df['timestamp'])
        
        # Berechne Perzentile
        latency_stats = df.groupby('model')['latency_ms'].agg([
            ('p50', lambda x: x.quantile(0.50)),
            ('p95', lambda x: x.quantile(0.95)),
            ('p99', lambda x: x.quantile(0.99)),
            ('mean', 'mean'),
            ('count', 'count')
        ]).round(2)
        
        return latency_stats
    
    def plot_cost_timeline(self, granularity: str = 'hour') -> go.Figure:
        """Visualisiert Kostenentwicklung über Zeit"""
        df = pd.DataFrame([asdict(r) for r in self.tracer.request_log])
        
        if df.empty:
            return go.Figure()
        
        df['timestamp'] = pd.to_datetime(df['timestamp'])
        df['cost'] = df.apply(
            lambda x: self.tracer._calculate_cost(
                x['model'], 
                x['prompt_tokens'], 
                x['completion_tokens']
            ), 
            axis=1
        )
        
        if granularity == 'hour':
            df_grouped = df.groupby(df['timestamp'].dt.floor('H')).agg({
                'cost': 'sum',
                'request_id': 'count'
            }).reset_index()
            df_grouped.columns = ['timestamp', 'cost_usd', 'request_count']
        else:
            df_grouped = df.groupby(df['timestamp'].dt.date).agg({
                'cost': 'sum',
                'request_id': 'count'
            }).reset_index()
            df_grouped.columns = ['timestamp', 'cost_usd', 'request_count']
        
        fig = make_subplots(
            rows=2, cols=1,
            subplot_titles=['Kostenentwicklung (USD)', 'Request-Volumen'],
            vertical_spacing=0.15
        )
        
        fig.add_trace(
            go.Scatter(
                x=df_grouped['timestamp'],
                y=df_grouped['cost_usd'],
                mode='lines+markers',
                name='Kosten',
                line=dict(color='#2ecc71', width=2)
            ),
            row=1, col=1
        )
        
        fig.add_trace(
            go.Bar(
                x=df_grouped['timestamp'],
                y=df_grouped['request_count'],
                name='Requests',
                marker_color='#3498db'
            ),
            row=2, col=1
        )
        
        fig.update_layout(
            height=600,
            showlegend=True,
            title_text="HolySheep AI - Kosten & Performance Dashboard"
        )
        
        return fig
    
    def export_trace_chain(self, output_file: str = 'trace_export.json'):
        """
        Exportiert vollständige Trace-Kette für Debugging
        mit hierarchischer Request-Baumstruktur
        """
        trace_data = {
            'export_timestamp': datetime.utcnow().isoformat(),
            'cost_summary': self.tracer.get_cost_summary(),
            'latency_report': self.generate_latency_report().to_dict(),
            'requests': [asdict(r) for r in self.tracer.request_log]
        }
        
        with open(output_file, 'w') as f:
            json.dump(trace_data, f, indent=2, default=str)
        
        return output_file

Beispiel: Dashboard erstellen und Berichte generieren

async def main(): tracer = HolySheepTracer(api_key="YOUR_HOLYSHEEP_API_KEY") # Test-Aufrufe mit verschiedenen Modellen test_models = [ {"model": "deepseek-v3.2", "messages": [{"role": "user", "content": "Erkläre APIs"}]}, {"model": "gemini-2.5-flash", "messages": [{"role": "user", "content": "Was ist Tracing?"}]}, {"model": "gpt-4.1", "messages": [{"role": "user", "content": "Optimiere diesen Code"}]}, ] for test in test_models: await tracer.chat_completion(**test) # Dashboard generieren dashboard = TracingDashboard(tracer) # Latenz-Report anzeigen latency_df = dashboard.generate_latency_report() print("=== Latenz-Perzentile (in ms) ===") print(latency_df) # Kostenübersicht cost_summary = tracer.get_cost_summary() print("\n=== Kostenübersicht ===") print(f"Gesamtkosten: ${cost_summary['total_cost_usd']}") print(f"Durchschnittliche Latenz: {cost_summary['avg_latency_ms']:.2f}ms") print(f"Fehlerrate: {cost_summary['error_rate']:.2f}%") # Export für Debugging dashboard.export_trace_chain('holy_sheep_trace.json') await tracer.client.aclose() if __name__ == "__main__": asyncio.run(main())

Multi-Model Orchestration mit Tracing

/**
 * TypeScript Implementation für Frontend-Integration
 * mit vollständiger Request-ID Propagierung
 */

interface TracedRequest {
  requestId: string;
  parentRequestId?: string;
  model: string;
  startTime: number;
  latency?: number;
  tokens?: { prompt: number; completion: number };
  cost?: number;
  status: 'pending' | 'success' | 'error';
  error?: string;
}

class HolySheepAPIClient {
  private baseUrl = 'https://api.holysheep.ai/v1';
  private requestQueue: Map = new Map();
  private activeRequests: number = 0;
  private maxConcurrent: number = 10;
  
  // Preisstruktur 2026 (USD pro Million Tokens)
  private pricing: Record = {
    'gpt-4.1': { input: 8.0, output: 8.0 },
    'claude-sonnet-4.5': { input: 15.0, output: 15.0 },
    'gemini-2.5-flash': { input: 2.50, output: 2.50 },
    'deepseek-v3.2': { input: 0.42, output: 0.42 }
  };

  constructor(private apiKey: string) {
    this.startMetricsCollector();
  }

  private generateRequestId(): string {
    return req_${Date.now()}_${Math.random().toString(36).substr(2, 9)};
  }

  private calculateCost(model: string, promptTokens: number, completionTokens: number): number {
    const prices = this.pricing[model];
    if (!prices) return 0;
    
    const inputCost = (promptTokens / 1_000_000) * prices.input;
    const outputCost = (completionTokens / 1_000_000) * prices.output;
    
    return inputCost + outputCost;
  }

  async chatCompletion(
    messages: Array<{ role: string; content: string }>,
    model: string = 'gpt-4.1',
    parentRequestId?: string
  ): Promise {
    const requestId = this.generateRequestId();
    
    const tracedRequest: TracedRequest = {
      requestId,
      parentRequestId,
      model,
      startTime: performance.now(),
      status: 'pending'
    };
    
    this.requestQueue.set(requestId, tracedRequest);
    this.activeRequests++;
    
    try {
      // Rate Limiting Check
      if (this.activeRequests >= this.maxConcurrent) {
        await this.waitForCapacity();
      }

      const response = await fetch(${this.baseUrl}/chat/completions, {
        method: 'POST',
        headers: {
          'Authorization': Bearer ${this.apiKey},
          'Content-Type': 'application/json',
          'X-Request-ID': requestId
        },
        body: JSON.stringify({
          model,
          messages,
          max_tokens: 2048,
          temperature: 0.7
        })
      });

      tracedRequest.latency = performance.now() - tracedRequest.startTime;
      
      if (response.ok) {
        const data = await response.json();
        const usage = data.usage || {};
        
        tracedRequest.tokens = {
          prompt: usage.prompt_tokens || 0,
          completion: usage.completion_tokens || 0
        };
        tracedRequest.cost = this.calculateCost(
          model,
          tracedRequest.tokens.prompt,
          tracedRequest.tokens.completion
        );
        tracedRequest.status = 'success';
        
        return data;
      } else {
        const error = await response.json();
        tracedRequest.status = 'error';
        tracedRequest.error = JSON.stringify(error);
        throw new Error(API Error: ${response.status} - ${JSON.stringify(error)});
      }
    } catch (error) {
      tracedRequest.status = 'error';
      tracedRequest.error = error instanceof Error ? error.message : String(error);
      throw error;
    } finally {
      this.activeRequests--;
    }
  }

  private async waitForCapacity(): Promise {
    return new Promise(resolve => {
      const checkInterval = setInterval(() => {
        if (this.activeRequests < this.maxConcurrent) {
          clearInterval(checkInterval);
          resolve();
        }
      }, 100);
    });
  }

  getMetrics(): {
    totalRequests: number;
    successRate: number;
    avgLatency: number;
    totalCost: number;
    byModel: Record;
  } {
    const requests = Array.from(this.requestQueue.values());
    const successful = requests.filter(r => r.status === 'success');
    
    const byModel: Record = {};
    
    for (const req of successful) {
      if (!byModel[req.model]) {
        byModel[req.model] = { count: 0, cost: 0, latencies: [] };
      }
      byModel[req.model].count++;
      byModel[req.model].cost += req.cost || 0;
      byModel[req.model].latencies.push(req.latency || 0);
    }

    const modelStats: Record = {};
    for (const [model, stats] of Object.entries(byModel)) {
      modelStats[model] = {
        count: stats.count,
        cost: Math.round(stats.cost * 10000) / 10000,
        avgLatency: Math.round(
          stats.latencies.reduce((a, b) => a + b, 0) / stats.latencies.length
        )
      };
    }

    return {
      totalRequests: requests.length,
      successRate: requests.length > 0 
        ? Math.round((successful.length / requests.length) * 10000) / 100 
        : 0,
      avgLatency: successful.length > 0
        ? Math.round(successful.reduce((a, r) => a + (r.latency || 0), 0) / successful.length)
        : 0,
      totalCost: Math.round(successful.reduce((a, r) => a + (r.cost || 0), 0) * 10000) / 10000,
      byModel: modelStats
    };
  }

  private startMetricsCollector(): void {
    setInterval(() => {
      const metrics = this.getMetrics();
      console.log('[HolySheep Metrics]', JSON.stringify(metrics, null, 2));
    }, 60000); // Alle 60 Sekunden
  }
}

// Verwendung
const client = new HolySheepAPIClient('YOUR_HOLYSHEEP_API_KEY');

// Beispiel: Multi-Model Pipeline mit Parent-Tracking
async function runDocumentProcessingPipeline(document: string) {
  const rootRequestId = client.generateRequestId();
  
  // Schritt 1: Textklassifikation (schnelles Modell)
  const classification = await client.chatCompletion(
    [{ role: 'user', content: Klassifiziere: ${document} }],
    'deepseek-v3.2',
    rootRequestId
  );
  
  // Schritt 2: Detailanalyse (starkes Modell)
  const analysis = await client.chatCompletion(
    [{ role: 'user', content: Analysiere detailliert: ${document} }],
    'gpt-4.1',
    classification.id
  );
  
  // Finale Zusammenfassung
  const summary = await client.chatCompletion(
    [{ role: 'user', content: Fasse zusammen basierend auf: ${analysis.choices[0].message.content} }],
    'gemini-2.5-flash',
    analysis.id
  );
  
  // Finale Metriken
  console.log('Pipeline abgeschlossen:', client.getMetrics());
  
  return { classification, analysis, summary };
}

Praxiserfahrung aus Produktivumgebungen

Nachdem ich dieses Tracing-System in fünf verschiedenen Produktionsumgebungen implementiert habe, möchte ich meine wichtigsten Erkenntnisse teilen:

Häufige Fehler und Lösungen

1. Fehler: "401 Unauthorized" trotz korrektem API-Key

Ursache: Der API-Key enthält Leerzeichen oder wurde nicht korrekt übergeben. Bei Copy-Paste aus dem Dashboard gehen manchmal unsichtbare Zeichen verloren.

# FEHLERHAFT - führt zu 401
headers = {
    "Authorization": f"Bearer {api_key} ",  # Leerzeichen am Ende!
}

ODER

api_key = "sk-xxxxxx\n" # Newline-Zeichen

LÖSUNG - Korrekte Key-Validierung

import re def validate_api_key(api_key: str) -> str: """Validiert und bereinigt den API-Key""" if not api_key: raise ValueError("API-Key darf nicht leer sein") # Entferne alle Whitespace-Zeichen cleaned_key = api_key.strip() # Validiere Format (bei HolySheep: sk-...) if not re.match(r'^sk-[a-zA-Z0-9_-]{20,}$', cleaned_key): raise ValueError( f"Ungültiges API-Key Format. " f"Erwartet: sk- gefolgt von mindestens 20 alphanumerischen Zeichen. " f"Erhalten: {cleaned_key[:10]}..." ) return cleaned_key

Verwendung im Tracer

tracer = HolySheepTracer(api_key=validate_api_key("YOUR_HOLYSHEEP_API_KEY"))

2. Fehler: "429 Too Many Requests" trotz geringer Request-Zahl

Ursache: Rate-Limits werden pro Minute gezählt, nicht pro Sekunde. Burst-Traffic überschreitet schnell das Limit, auch wenn der Durchschnitt niedrig ist.

import asyncio
from collections import deque
from datetime import datetime, timedelta

class AdaptiveRateLimiter:
    """
    Intelligenter Rate-Limiter mit dynamischer Anpassung
    basierend auf 429-Response-Headern
    """
    
    def __init__(self, requests_per_minute: int = 60):
        self.rpm_limit = requests_per_minute
        self.request_timestamps: deque = deque(maxlen=requests_per_minute)
        self.actual_limit: int = requests_per_minute
        self.retry_after: int = 60
        self.backoff_until: datetime = None
    
    async def acquire(self):
        """Blockiert bis Request erlaubt ist"""
        # Prüfe Backoff-Phase
        if self.backoff_until and datetime.utcnow() < self.backoff_until:
            wait_seconds = (self.backoff_until - datetime.utcnow()).total_seconds()
            print(f"[RateLimiter] Backoff aktiv, warte {wait_seconds:.1f}s...")
            await asyncio.sleep(wait_seconds)
        
        # Prüfe lokales Limit
        now = datetime.utcnow()
        cutoff = now - timedelta(minutes=1)
        
        # Entferne alte Timestamps
        while self.request_timestamps and self.request_timestamps[0] < cutoff:
            self.request_timestamps.popleft()
        
        # Warte falls Limit erreicht
        if len(self.request_timestamps) >= self.actual_limit:
            oldest = self.request_timestamps[0]
            wait_time = (cutoff - oldest).total_seconds() + 1
            print(f"[RateLimiter] RPM-Limit ({self.actual_limit}) erreicht, warte {wait_time:.1f}s...")
            await asyncio.sleep(max(0.1, wait_time))
            return await self.acquire()  # Rekursiv
        
        self.request_timestamps.append(now)
    
    def handle_429(self, response_headers: dict):
        """Passt Limiter nach 429-Response an"""
        # Extrahiere Server-Limit aus Header
        if 'X-RateLimit-Limit' in response_headers:
            server_limit = int(response_headers['X-RateLimit-Limit'])
            self.actual_limit = min(self.actual_limit, server_limit)
            print(f"[RateLimiter] Limit angepasst auf {self.actual_limit}")
        
        # Setze Backoff
        if 'Retry-After' in response_headers:
            self.retry_after = int(response_headers['Retry-After'])
            self.backoff_until = datetime.utcnow() + timedelta(seconds=self.retry_after)
            
            # Reduziere zukünftiges Limit um 50%
            self.actual_limit = max(1, int(self.actual_limit * 0.5))
            print(f"[RateLimiter] Backoff {self.retry_after}s, neues Limit: {self.actual_limit}")
        
        # Exponentieller Backoff für wiederholte 429s
        if self.backoff_until:
            current_wait = (self.backoff_until - datetime.utcnow()).total_seconds()
            if current_wait > 0:
                self.backoff_until = datetime.utcnow() + timedelta(
                    seconds=current_wait * 2
                )

Integration in Tracer

limiter = AdaptiveRateLimiter(requests_per_minute=500) async def throttled_completion(tracer, messages, model): await limiter.acquire() try: result = await tracer.chat_completion(messages, model) return result except httpx.HTTPStatusError as e: if e.response.status_code == 429: limiter.handle_429(dict(e.response.headers)) return await throttled_completion(tracer, messages, model) # Retry raise

3. Fehler: Token-Zählung stimmt nicht mit Rechnung überein

Ursache: Die lokale Token-Schätzung weicht von der tatsächlichen Zählung durch das Modell ab. Unterschiedliche Tokenizer erzeugen verschiedene Ergebnisse.

import tiktoken
from typing import Tuple

class AccurateTokenCounter:
    """
    Zählt Tokens exakt nach Modell-Tokenizer
    mit automatischer Erkennung
    """
    
    ENCODINGS = {
        'gpt-4.1': 'cl100k_base',           # GPT-4 Serie
        'claude-sonnet-4.5': 'cl100k_base', # Claude nutzt gleiche Base
        'gemini-2.5-flash': 'cl100k_base',  # Gemini-kompatibel
        'deepseek-v3.2': 'cl100k_base'      # DeepSeek Base
    }
    
    def __init__(self):
        self.encoders: dict = {}
        self._init_encoders()
    
    def _init_encoders(self):
        """Lazy Loading der Encoder"""
        for model, encoding_name in self.ENCODINGS.items():
            if encoding_name not in self.encoders:
                self.encoders[encoding_name] = tiktoken.get_encoding(encoding_name)
    
    def count(self, text: str, model: str) -> int:
        """Zählt Tokens für gegebenen Text und Modell"""
        encoding_name = self.ENCODINGS.get(model, 'cl100k_base')
        encoder = self.encoders[encoding_name]
        return len(encoder.encode(text))
    
    def count_messages(
        self, 
        messages: list, 
        model: str
    ) -> Tuple[int, int]:
        """
        Zählt Prompt- und Completion-Tokens für Chat-Format
        Berücksichtigt Message-Overhead
        """
        prompt_tokens = 0
        
        for msg in messages:
            # Message-Format Overhead (per OpenAI)
            prompt_tokens += 4
            
            # Content
            content = msg.get('content', '')
            prompt_tokens += self