C# / .NET 8 Künstliche Intelligenz

Mistral AI API in ASP.NET Core integrieren

Stephan Pfeiffer

Künstliche Intelligenz ist nicht mehr wegzudenken. Anstatt jedoch teure Abos für vorgefertigte Chatbots zu zahlen, ist es für Softwareentwickler oft sinnvoller, Large Language Models (LLMs) direkt via API in das eigene Backend einzubinden. In diesem Artikel zeige ich am Beispiel des KI-Assistenten auf meiner eigenen Website, wie man Mistral AI in C# nutzt.

Warum Mistral AI?

Mistral AI bietet exzellente Open-Weight und proprietäre Modelle (wie mistral-small-latest), die in Sachen Latenz und Kosten-Nutzen-Verhältnis oft besser abschneiden als die großen Platzhirsche. Die REST-API ist OpenAI-kompatibel, was den Wechsel zwischen Anbietern im Code trivial macht.

Das Minimal API Setup in .NET 8

Für die Anbindung benötigen wir keinen riesigen Controller. Die Minimal APIs in .NET 8 gepaart mit der IHttpClientFactory bieten den perfekten, leichtgewichtigen Rahmen. Zuerst legen wir einen Endpunkt an und holen uns den API-Key sicher aus der Konfiguration:

Program.cs (Auszug)
app.MapPost("/api/chat", async (ChatRequest request, IConfiguration config, IHttpClientFactory httpClientFactory) =>
{
    var apiKey = config["MistralApiKey"];
    if (string.IsNullOrEmpty(apiKey))
        return Results.StatusCode(500);

    var client = httpClientFactory.CreateClient();
    client.DefaultRequestHeaders.Authorization = 
        new AuthenticationHeaderValue("Bearer", apiKey);
    
    // ... Payload Aufbau folgt
});
Architektur-Tipp: Nutze immer IHttpClientFactory anstatt new HttpClient() manuell zu instanziieren, um Socket-Erschöpfung (Socket Exhaustion) bei vielen gleichzeitigen Chat-Anfragen zu vermeiden!

System Prompts & RAG (Retrieval-Augmented Generation)

Ein KI-Modell ist nur so schlau wie sein Kontext. Mein Portfolio-Chatbot kennt meinen Lebenslauf nicht auswendig. Daher lade ich beim Start des Servers eine Wissensbasis (PDFs und TXT-Dateien) in den RAM und hänge sie als System-Prompt dynamisch an jede Anfrage an.

Payload Konstruktion
var systemPrompt = @"Du bist der persönliche KI-Assistent von Stephan Pfeiffer. 
Antworte präzise, hilfsbereit und kurz.";

// RAG: Lokales Wissen anfügen
if (!string.IsNullOrEmpty(cachedWissensbasis))
{
    systemPrompt += "\n\nHier ist ZUSÄTZLICHES WISSEN:\n" + cachedWissensbasis;
}

var payload = new
{
    model = "mistral-small-latest",
    messages = new[]
    {
        new { role = "system", content = systemPrompt },
        new { role = "user", content = request.Message }
    }
};

Die Ausführung & JSON Parsing

Schließlich senden wir den serialisierten Payload an Mistral und werten die Antwort aus. Dank JsonDocument aus dem System.Text.Json Namespace brauchen wir dafür nicht einmal strikte C#-Klassen anzulegen, wenn wir nur den reinen Antworttext benötigen.

Request & Response
var content = new StringContent(
    JsonSerializer.Serialize(payload), 
    Encoding.UTF8, 
    "application/json"
);

var response = await client.PostAsync("https://api.mistral.ai/v1/chat/completions", content);

if (response.IsSuccessStatusCode)
{
    var responseString = await response.Content.ReadAsStringAsync();
    using var jsonDoc = JsonDocument.Parse(responseString);
    var reply = jsonDoc.RootElement
                       .GetProperty("choices")[0]
                       .GetProperty("message")
                       .GetProperty("content")
                       .GetString();
                       
    return Results.Ok(new { reply });
}

return Results.StatusCode((int)response.StatusCode);

Fazit

Mit knapp 30 Zeilen Code lässt sich in ASP.NET Core eine voll funktionsfähige Schnittstelle zu einem der besten LLMs der Welt aufbauen. Diese Methode nutze ich auch für mein Projekt FaStep, um Bewerbungsanschreiben vollautomatisch aus Lebensläufen zu generieren.