KI-Agenten entwickeln, die Ihre Excel-Modelle tatsächlich nutzen

Von Excel zum KI-Agent in 30 Minuten

Ihre Excel-Tabelle hat sich über Jahre entwickelt. Sie verarbeitet Sonderfälle, implementiert komplexe Geschäftsregeln und verkörpert tiefes Domänenwissen. Jetzt möchten Sie, dass ein KI-Agent sie nutzt.

Die meisten Tutorials sagen Ihnen, Sie sollen "einfach als CSV exportieren" oder "in Python neu implementieren." Wir werden etwas Besseres machen: Wir geben Ihrem KI-Agent direkten Zugriff auf Excels Berechnungsengine.

Was wir entwickeln

Einen Kundenservice-KI-Agent, der:

  • Genaue Angebote mit Ihrer Preis-Excel berechnet
  • Liefertermine mit Ihrem Logistikmodell prüft
  • Rabatte basierend auf komplexen Geschäftsregeln anwendet
  • Sonderfälle genau wie Ihr Team behandelt

Alles unter Verwendung Ihrer bestehenden Excel-Dateien. Keine Neuimplementierung erforderlich.

Voraussetzungen

# Sie benötigen:
npm install langchain @langchain/openai
# oder
pip install langchain openai

# Und ein SpreadAPI-Konto (kostenlose Stufe funktioniert)
# Registrieren Sie sich unter https://spreadapi.io

Schritt 1: Excel für KI vorbereiten

Ihre Excel-Struktur

PricingModel.xlsx
├── Eingaben
│   ├── B2: Produktcode
│   ├── B3: Menge
│   ├── B4: Kundentyp
│   └── B5: Region
├── Berechnungen (Vor KI verborgen)
│   ├── Komplexe VLOOKUP-Formeln
│   ├── Rabattmatrizen
│   └── Geschäftsregeln
└── Ausgaben
    ├── E10: Grundpreis
    ├── E11: Rabattbetrag
    ├── E12: Endpreis
    └── E13: Liefertermin

Upload zu SpreadAPI

  1. Bei SpreadAPI Dashboard anmelden
  2. Neuen Service namens "pricing-model" erstellen
  3. Ihre Excel hochladen
  4. Schnittstelle definieren:
{
  "inputs": {
    "productCode": "B2",
    "quantity": "B3",
    "customerType": "B4",
    "region": "B5"
  },
  "outputs": {
    "basePrice": "E10",
    "discount": "E11",
    "finalPrice": "E12",
    "deliveryDate": "E13"
  }
}

Schritt 2: Den KI-Agent erstellen

Basis-Agent mit Function Calling

import { ChatOpenAI } from '@langchain/openai';
import { SpreadAPITool } from './spreadapi-tool';

// Das Excel-Berechnungs-Tool definieren
const pricingTool = {
  name: "calculate_pricing",
  description: "Genaue Preisberechnung mit dem Unternehmens-Preismodell. Verwenden Sie dieses Tool, wann immer Sie Preise anbieten oder Rabatte prüfen müssen.",
  parameters: {
    type: "object",
    properties: {
      productCode: {
        type: "string",
        description: "Produktcode (z.B. 'PRO-001')"
      },
      quantity: {
        type: "number",
        description: "Anzahl der Einheiten"
      },
      customerType: {
        type: "string",
        enum: ["standard", "premium", "enterprise"],
        description: "Art des Kundenkontos"
      },
      region: {
        type: "string",
        enum: ["US", "EU", "APAC"],
        description: "Region des Kunden"
      }
    },
    required: ["productCode", "quantity", "customerType", "region"]
  },
  execute: async (params) => {
    // SpreadAPI aufrufen
    const response = await fetch('https://api.spreadapi.io/v1/services/pricing-model/execute', {
      method: 'POST',
      headers: {
        'Authorization': `Bearer ${process.env.SPREADAPI_KEY}`,
        'Content-Type': 'application/json'
      },
      body: JSON.stringify({ inputs: params })
    });
    
    const result = await response.json();
    return result.outputs;
  }
};

// Den KI-Agent erstellen
const model = new ChatOpenAI({
  modelName: "gpt-4",
  temperature: 0
});

const tools = [pricingTool];
const modelWithTools = model.bind({ tools });

Agent-Logik implementieren

class CustomerServiceAgent {
  constructor(model, tools) {
    this.model = model;
    this.tools = tools;
    this.conversation = [];
  }
  
  async respond(userMessage) {
    // Benutzernachricht zum Gespräch hinzufügen
    this.conversation.push({
      role: 'user',
      content: userMessage
    });
    
    // KI-Antwort mit möglichen Tool-Aufrufen erhalten
    const response = await this.model.invoke(this.conversation);
    
    // Tool-Aufrufe behandeln
    if (response.tool_calls && response.tool_calls.length > 0) {
      for (const toolCall of response.tool_calls) {
        const tool = this.tools.find(t => t.name === toolCall.name);
        
        if (tool) {
          // Excel-Berechnung ausführen
          const result = await tool.execute(toolCall.arguments);
          
          // Tool-Ergebnis zum Gespräch hinzufügen
          this.conversation.push({
            role: 'tool',
            content: JSON.stringify(result),
            tool_call_id: toolCall.id
          });
        }
      }
      
      // Endgültige Antwort nach Tool-Ausführung erhalten
      const finalResponse = await this.model.invoke(this.conversation);
      this.conversation.push({
        role: 'assistant',
        content: finalResponse.content
      });
      
      return finalResponse.content;
    }
    
    // Keine Tool-Aufrufe erforderlich
    this.conversation.push({
      role: 'assistant',
      content: response.content
    });
    
    return response.content;
  }
}

Schritt 3: Produktionsreife Muster

Muster 1: Multi-Tool-Agent

// Mehrere Excel-basierte Tools hinzufügen
const tools = [
  {
    name: "calculate_pricing",
    description: "Produktpreise und Rabatte berechnen",
    spreadapiService: "pricing-model",
    execute: spreadapiExecutor("pricing-model")
  },
  {
    name: "check_inventory",
    description: "Produktverfügbarkeit und Lieferzeiten prüfen",
    spreadapiService: "inventory-tracker",
    execute: spreadapiExecutor("inventory-tracker")
  },
  {
    name: "calculate_shipping",
    description: "Versandkosten und Liefertermine berechnen",
    spreadapiService: "logistics-calculator",
    execute: spreadapiExecutor("logistics-calculator")
  }
];

// Hilfsfunktion für SpreadAPI-Ausführung
function spreadapiExecutor(serviceName) {
  return async (params) => {
    const response = await fetch(
      `https://api.spreadapi.io/v1/services/${serviceName}/execute`,
      {
        method: 'POST',
        headers: {
          'Authorization': `Bearer ${process.env.SPREADAPI_KEY}`,
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({ inputs: params })
      }
    );
    
    if (!response.ok) {
      throw new Error(`Excel-Berechnung fehlgeschlagen: ${response.statusText}`);
    }
    
    const result = await response.json();
    return result.outputs;
  };
}

Muster 2: Kontextbewusster Agent

class ContextAwareAgent {
  constructor() {
    this.customerContext = {};
    this.calculationCache = new Map();
  }
  
  async handleQuery(query, customerId) {
    // Kundenkontext laden
    if (!this.customerContext[customerId]) {
      this.customerContext[customerId] = await this.loadCustomerData(customerId);
    }
    
    const context = this.customerContext[customerId];
    
    // Prompt mit Kontext erweitern
    const enhancedPrompt = `
      Kundeninformationen:
      - Typ: ${context.customerType}
      - Region: ${context.region}
      - Kaufhistorie: ${context.totalPurchases} Bestellungen
      
      Benutzeranfrage: ${query}
      
      Anweisungen:
      - Verwenden Sie das calculate_pricing-Tool für alle Preisangebote
      - Wenden Sie automatisch den entsprechenden Kundentyp an
      - Berücksichtigen Sie deren Region für Versandberechnungen
    `;
    
    return await this.respond(enhancedPrompt);
  }
  
  async loadCustomerData(customerId) {
    // Aus Ihrer Datenbank laden
    return {
      customerType: 'enterprise',
      region: 'US',
      totalPurchases: 47
    };
  }
}

Muster 3: Validierung und Fehlerbehandlung

class RobustAgent {
  async executeToolSafely(tool, params) {
    try {
      // Eingaben vor Übertragung an Excel validieren
      const validation = this.validateInputs(tool.name, params);
      if (!validation.valid) {
        return {
          error: `Ungültige Eingabe: ${validation.message}`,
          suggestion: validation.suggestion
        };
      }
      
      // Zuerst Cache prüfen
      const cacheKey = `${tool.name}:${JSON.stringify(params)}`;
      if (this.cache.has(cacheKey)) {
        return this.cache.get(cacheKey);
      }
      
      // Mit Timeout ausführen
      const result = await Promise.race([
        tool.execute(params),
        new Promise((_, reject) => 
          setTimeout(() => reject(new Error('Berechnungs-Timeout')), 5000)
        )
      ]);
      
      // Erfolgreiche Ergebnisse cachen
      this.cache.set(cacheKey, result);
      
      // Ausgabe validieren
      if (result.finalPrice < 0) {
        return {
          error: 'Ungültiges Berechnungsergebnis',
          suggestion: 'Bitte prüfen Sie Produktcode und Menge'
        };
      }
      
      return result;
      
    } catch (error) {
      console.error('Tool-Ausführung fehlgeschlagen:', error);
      
      // Fallback-Antwort
      return {
        error: 'Berechnung momentan nicht möglich',
        suggestion: 'Bitte versuchen Sie es erneut oder kontaktieren Sie den Support',
        reference: error.message
      };
    }
  }
  
  validateInputs(toolName, params) {
    if (toolName === 'calculate_pricing') {
      if (params.quantity < 1) {
        return {
          valid: false,
          message: 'Menge muss mindestens 1 betragen',
          suggestion: 'Bitte geben Sie eine gültige Menge an'
        };
      }
      
      if (!params.productCode.match(/^[A-Z]{3}-\d{3}$/)) {
        return {
          valid: false,
          message: 'Ungültiges Produktcode-Format',
          suggestion: 'Produktcodes sollten wie ABC-123 aussehen'
        };
      }
    }
    
    return { valid: true };
  }
}

Schritt 4: Erweiterte Agent-Fähigkeiten

Fähigkeit 1: Mehrstufige Berechnungen

const complexWorkflowTool = {
  name: "quote_with_options",
  description: "Vollständiges Angebot mit mehreren Produktoptionen erstellen",
  execute: async (params) => {
    const { products, customerType, region } = params;
    
    // Preisberechnung für jedes Produkt
    const quotes = await Promise.all(
      products.map(async (product) => {
        const pricing = await spreadapiExecutor('pricing-model')({
          productCode: product.code,
          quantity: product.quantity,
          customerType,
          region
        });
        
        const shipping = await spreadapiExecutor('logistics-calculator')({
          productCode: product.code,
          quantity: product.quantity,
          region,
          expedited: product.expedited || false
        });
        
        return {
          product: product.code,
          quantity: product.quantity,
          pricing,
          shipping,
          total: pricing.finalPrice + shipping.cost
        };
      })
    );
    
    // Bundle-Rabatt berechnen, falls anwendbar
    if (quotes.length > 1) {
      const bundleResult = await spreadapiExecutor('bundle-calculator')({
        products: products.map(p => p.code),
        quantities: products.map(p => p.quantity),
        customerType
      });
      
      return {
        individualQuotes: quotes,
        bundleDiscount: bundleResult.discount,
        bundleTotal: bundleResult.total
      };
    }
    
    return { quotes };
  }
};

Fähigkeit 2: Erklärungen und Begründungen

class ExplainableAgent {
  async respondWithExplanation(query) {
    const response = await this.model.invoke([
      {
        role: 'system',
        content: `Sie sind ein hilfreicher Kundenservice-Agent.
        Bei der Verwendung von Preis-Tools erklären Sie immer:
        1. Welche Faktoren den Preis beeinflusst haben
        2. Welche Rabatte angewendet wurden
        3. Warum dies die beste Option für den Kunden ist`
      },
      {
        role: 'user',
        content: query
      }
    ]);
    
    // Tool-Aufrufe verarbeiten und Erklärungen hinzufügen
    if (response.tool_calls) {
      const explanations = [];
      
      for (const toolCall of response.tool_calls) {
        const result = await this.executeTool(toolCall);
        
        // Erklärung basierend auf Ergebnissen generieren
        if (toolCall.name === 'calculate_pricing') {
          const discount = result.basePrice - result.finalPrice;
          const discountPercent = (discount / result.basePrice * 100).toFixed(1);
          
          explanations.push({
            calculation: toolCall.name,
            explanation: `
              Grundpreis: €${result.basePrice}
              ${discount > 0 ? `Rabatt angewendet: €${discount} (${discountPercent}%)` : 'Kein Rabatt anwendbar'}
              Endpreis: €${result.finalPrice}
              Lieferung bis: ${result.deliveryDate}
            `
          });
        }
      }
      
      // Endgültige Antwort mit Erklärungen erhalten
      const finalResponse = await this.model.invoke([
        ...this.conversation,
        {
          role: 'system',
          content: `Fügen Sie diese Berechnungsdetails in Ihre Antwort ein: ${JSON.stringify(explanations)}`
        }
      ]);
      
      return finalResponse.content;
    }
    
    return response.content;
  }
}

Fähigkeit 3: Szenario-Vergleich

const scenarioTool = {
  name: "compare_scenarios",
  description: "Verschiedene Kaufszenarien vergleichen, um die beste Option zu finden",
  execute: async (params) => {
    const scenarios = [
      {
        name: "Einzelkauf",
        params: {
          quantity: params.quantity,
          customerType: params.customerType
        }
      },
      {
        name: "Großeinkauf",
        params: {
          quantity: params.quantity * 3,
          customerType: params.customerType
        }
      },
      {
        name: "Jahresvertrag",
        params: {
          quantity: params.quantity * 12,
          customerType: 'enterprise' // Automatische Aufwertung
        }
      }
    ];
    
    const results = await Promise.all(
      scenarios.map(async (scenario) => {
        const pricing = await spreadapiExecutor('pricing-model')({
          ...params,
          ...scenario.params
        });
        
        return {
          scenario: scenario.name,
          totalQuantity: scenario.params.quantity,
          unitPrice: pricing.finalPrice / scenario.params.quantity,
          totalPrice: pricing.finalPrice,
          savings: (params.quantity * (pricing.basePrice / scenario.params.quantity)) - pricing.finalPrice
        };
      })
    );
    
    // Beste Option finden
    const bestOption = results.reduce((best, current) => 
      current.unitPrice < best.unitPrice ? current : best
    );
    
    return {
      scenarios: results,
      recommendation: bestOption,
      potentialSavings: results[0].totalPrice - bestOption.totalPrice
    };
  }
};

Schritt 5: Deployment und Monitoring

Produktionskonfiguration

// config/agent.js
export const agentConfig = {
  model: {
    name: process.env.MODEL_NAME || 'gpt-4',
    temperature: 0,
    maxTokens: 1000,
    timeout: 30000
  },
  
  spreadapi: {
    baseUrl: process.env.SPREADAPI_URL || 'https://api.spreadapi.io/v1',
    apiKey: process.env.SPREADAPI_KEY,
    timeout: 5000,
    retries: 3
  },
  
  caching: {
    ttl: 300, // 5 Minuten
    maxSize: 1000
  },
  
  monitoring: {
    logLevel: process.env.LOG_LEVEL || 'info',
    metricsEnabled: true,
    tracingEnabled: process.env.NODE_ENV === 'production'
  }
};

Monitoring und Analytics

class MonitoredAgent {
  constructor(config) {
    this.metrics = {
      totalRequests: 0,
      toolCalls: {},
      errors: {},
      responseTime: []
    };
  }
  
  async handleRequest(query) {
    const startTime = Date.now();
    const requestId = generateRequestId();
    
    try {
      console.log(`[${requestId}] Verarbeite Anfrage:`, query);
      
      const response = await this.agent.respond(query);
      
      const duration = Date.now() - startTime;
      this.metrics.responseTime.push(duration);
      this.metrics.totalRequests++;
      
      console.log(`[${requestId}] Abgeschlossen in ${duration}ms`);
      
      // An Analytics senden
      await this.sendAnalytics({
        requestId,
        duration,
        toolsUsed: this.agent.lastToolCalls,
        success: true
      });
      
      return response;
      
    } catch (error) {
      const errorType = error.name || 'Unbekannt';
      this.metrics.errors[errorType] = (this.metrics.errors[errorType] || 0) + 1;
      
      console.error(`[${requestId}] Fehler:`, error);
      
      await this.sendAnalytics({
        requestId,
        error: error.message,
        success: false
      });
      
      throw error;
    }
  }
  
  getMetrics() {
    const avgResponseTime = 
      this.metrics.responseTime.reduce((a, b) => a + b, 0) / 
      this.metrics.responseTime.length;
    
    return {
      totalRequests: this.metrics.totalRequests,
      averageResponseTime: avgResponseTime,
      toolUsage: this.metrics.toolCalls,
      errorRate: Object.values(this.metrics.errors).reduce((a, b) => a + b, 0) / 
                 this.metrics.totalRequests
    };
  }
}

Häufige Fallstricke und Lösungen

Fallstrick 1: Den Agent überlasten

//  Schlecht: Dem Agent zu viel Freiheit geben
const badPrompt = "Helfen Sie dem Kunden bei allem, was er braucht";

//  Gut: Klare Grenzen und Fähigkeiten
const goodPrompt = `Sie sind ein Kundenservice-Agent, spezialisiert auf:
1. Produktpreise (verwenden Sie das calculate_pricing-Tool)
2. Lagerverfügbarkeit (verwenden Sie das check_inventory-Tool)
3. Versandschätzungen (verwenden Sie das calculate_shipping-Tool)

Für andere Anfragen erklären Sie höflich, womit Sie helfen können.`;

Fallstrick 2: Excel-Fehler nicht behandeln

//  Robuste Fehlerbehandlung
const toolWithErrorHandling = {
  execute: async (params) => {
    try {
      const result = await spreadapiCall(params);
      
      // Excel-Ergebnisse validieren
      if (result.outputs.error) {
        return {
          success: false,
          error: 'Berechnungsfehler in Excel',
          details: result.outputs.error,
          suggestion: 'Bitte Produktcode prüfen und erneut versuchen'
        };
      }
      
      return { success: true, ...result.outputs };
      
    } catch (error) {
      if (error.status === 422) {
        return {
          success: false,
          error: 'Ungültige Eingabeparameter',
          suggestion: 'Bitte prüfen Sie Ihr Produktcode-Format'
        };
      }
      
      throw error; // Unerwartete Fehler erneut werfen
    }
  }
};

Fallstrick 3: Performance ignorieren

//  Performance-Optimierung
class OptimizedAgent {
  constructor() {
    this.cache = new LRUCache({ max: 500, ttl: 1000 * 60 * 5 });
    this.batchQueue = [];
    this.batchTimer = null;
  }
  
  async calculatePricing(params) {
    // Zuerst Cache prüfen
    const cacheKey = JSON.stringify(params);
    if (this.cache.has(cacheKey)) {
      return this.cache.get(cacheKey);
    }
    
    // Ähnliche Anfragen stapeln
    return new Promise((resolve) => {
      this.batchQueue.push({ params, resolve });
      
      if (!this.batchTimer) {
        this.batchTimer = setTimeout(() => this.processBatch(), 50);
      }
    });
  }
  
  async processBatch() {
    const batch = this.batchQueue.splice(0, 50); // Bis zu 50 auf einmal verarbeiten
    
    const results = await spreadapiExecutor('pricing-model').batch(
      batch.map(item => item.params)
    );
    
    results.forEach((result, index) => {
      const { params, resolve } = batch[index];
      this.cache.set(JSON.stringify(params), result);
      resolve(result);
    });
    
    this.batchTimer = null;
  }
}

Ihren Agent testen

// test/agent.test.js
describe('Kundenservice-Agent', () => {
  let agent;
  
  beforeEach(() => {
    agent = new CustomerServiceAgent();
  });
  
  test('sollte Preise genau berechnen', async () => {
    const response = await agent.respond(
      "Wie ist der Preis für 100 Einheiten von PRO-001 für einen Enterprise-Kunden in den USA?"
    );
    
    expect(response).toContain('Preis');
    expect(response).toMatch(/€[0-9.,]+/);
  });
  
  test('sollte ungültige Produktcodes behandeln', async () => {
    const response = await agent.respond(
      "Preis für Produkt XYZ"
    );
    
    expect(response).toContain('gültiger Produktcode');
  });
  
  test('sollte Szenarien vergleichen, wenn gefragt', async () => {
    const response = await agent.respond(
      "Soll ich jetzt 10 Einheiten kaufen oder auf eine Großbestellung warten?"
    );
    
    expect(response).toContain('Szenario');
    expect(response).toContain('Empfehlung');
  });
});

Go-Live-Checkliste

  • [ ] Excel-Modelle zu SpreadAPI hochgeladen
  • [ ] Input/Output-Mappings definiert
  • [ ] API-Schlüssel sicher gespeichert
  • [ ] Agent-System-Prompt verfeinert
  • [ ] Tool-Beschreibungen klar und spezifisch
  • [ ] Fehlerbehandlung implementiert
  • [ ] Caching-Strategie vorhanden
  • [ ] Monitoring und Logging konfiguriert
  • [ ] Rate Limiting aktiviert
  • [ ] Testabdeckung > 80%
  • [ ] Last-Tests abgeschlossen
  • [ ] Fallback-Antworten definiert
  • [ ] Dokumentation aktualisiert

Nächste Schritte

  1. Einfach anfangen: Ein Excel-Modell, ein Tool, einfacher Agent
  2. Intelligenz hinzufügen: Kontextbewusstsein, mehrstufige Workflows
  3. Hochskalieren: Mehrere Modelle, Caching, Monitoring
  4. Optimieren: Performance-Tuning, Kostenoptimierung

Bereit, Ihren KI-Agent zu entwickeln? Beginnen Sie mit SpreadAPI

Fragen? Beispiele? Schreiben Sie uns an hello@airrange.io

Verwandte Artikel

Entdecken Sie weitere Excel-API- und KI-Integrations-Anleitungen: