This is a viewer only at the moment see the article on how this works.
To update the preview hit Ctrl-Alt-R (or ⌘-Alt-R on Mac) or Enter to refresh. The Save icon lets you save the markdown file to disk
This is a preview from the server running through my markdig pipeline
Warum ich nicht LangChain benutze und was ich stattdessen tue
Thursday, 18 December 2025
Als ich anfing, LLM-- zu bauen, wies mich jeder auf LangChain, . und " hin.' ist der Standard von ,". Sie sagten: . Alle Beispiele benutzen es.." Und sie waren richtig, wenn du...'re im Python-Ökosystem bist., Lang Chain ist überall...".
Aber hier löscht die Sache : Ich vermeide LangChain nicht, weil es 's schlecht strickt ich vermeidet es, weil sie Probleme löst, die ich bereits expliziter lösen und für meine Anwendungsfälle mehr Reibung als Wert hinzufügen..
Dies ist ein Anti- --LangChain post ,. , Es ist ein Beitrag über das Verständnis der Probleme Frameworks lösen , , , und erkennen, dass Sie möglicherweise nicht brauchen sie , . .
Thesen ,: , Wenn Sie die Probleme verstehen LangChain löst , , , Sie brauchen nicht LangChains , . ,
Was LangChain eigentlich nicht gut tut
Lassen Sie ,''s fair sein zuerst , . , LangChain zeichnet sich bei mehreren Dingen , : ,
Schnelles Prototyping Sie können eine Arbeits-Demo in Minuten haben.Die immer wieder gestarteten Beispiele sind wirklich gut.
Python-Ökosystemintegration Wenn du schon im Python bist, klebe alles nahtlos zusammen.
Absenken der Barriere Für Leute, die neu in LLMs sind, stellt es nützliche Abstraktionen zur Verfügung.
LangChain ist ein IntegrationsbeschleunigerEs beschleunigt den Weg von " ausIch habe eine Idee, " zu "aus Ich habe eine Demo, die wertvoll ' ist
Aber es ist auch, wo die Probleme beginnen für mich als C.M.S.K.1. Entwickler Gebäude Produktionssysteme.
Die Probleme LangChain Solves
Vor der Entlassung eines Rahmens... musst du verstehen, welche Probleme es gibt....
- Kontextkonstruktion Erstellen kohärenter Aufforderungen aus Schemas, Aus Proben,Aus der Geschichte,Aus und Einschränkungen
- Werkzeug-Orchestrierung Verwaltung mehrerer Tool-Aufrufe in Folge mit bedingter Logik
- Staatliche Verwaltung Pflege des Gesprächskontextes über mehrere Runden hinweg
- Wiederholung und Fehlerbehebung Recovering anmutig, wenn die LLM erzeugt ungültige Ausgabe
- Mehrstufige Argumentation Umfassende Aufgaben in sequentielle Schritte zu überführen.
- Beobachtungsfähigkeit Verfolgen, was tatsächlich während der Ausführung passiert ist
Das sind legitime Probleme. Die Frage ist: :. Benötigst du einen Rahmen, um sie zu lösen?
Wo LangChain beginnt zu verletzen
Für meine Arbeit Die Gebäudeproduktion Die .-NET-Systeme mit lokalen LLMsDie ,-Strenge der Privatsphäre und das deterministische Verhalten Das - LangChain führt Reibung in mehreren Bereichen ein
Versteckter Zustand und impliziter Kontrollfluss
LangChain verwaltet Speicher und Kontext für dich, das klingt bequem, bis du debuggen musst, warum deine Eingabeaufforderung länger ist als erwartet, oder warum die LLM plötzlich Zugang zur Gesprächsgeschichte hat, von der du dachtest, dass sie '... gelöscht wurde.
Das Rahmenwerk verkettet Aufforderungen ,, , verwaltet Speicher , , , und handhabt Ausführung Reihenfolge implizit , . , Wenn etwas bricht ,, , you .' , debugging das Framework , das Verhalten der ' , nicht Ihr Code , ' , Verhalten ,
Rahmenbedingungen für das vernetzte Denken
Sobald du LangChain-, akzeptierst, fängst du an zu entwerfen für LangChainIhre Architektur wird mit dem Rahmen gekoppelt ,' , Abstraktionen , : , Ketten , , agents , , , Retriever ,M, , Speicherpuffer ,
Dies ist nicht einzigartig für LangChain -.Alle Frameworks tun dies aber in einem schnellen, sich bewegenden Feld wie LLMs,, wo die richtigen Abstraktionen sind '.t noch geregelt Kopplung an ein Rahmenwerk ' ist riskant
Die Python-Impedanz-Mismatch
LangChain geht davon aus, dass
- Langanhaltende Prozesse ( Notizbuch -Stil-Workflows
- Mutabler globaler Zustand
- Python-'s dynamische Typisierung und Ententypisierung
- Blockieren von I/-O-Mustern
Als Entwickler von .-NET gehe ich davon aus, dass :
- Beantragen Sie die Lebensdauer von -, scoped lifetimes.(, ASP-.,NET Kernmuster
- Immutierbarer oder explizit verwalteter Zustand
- Starke Schreib- und Kompilierungssicherheit
- Async-/-await überall
Das LangChain-Ports exist-, , aber sie sind es, die mit der Python-Version und den Abstraktionen noch fühlen sich fremd zu idiomatisch C.#.
Produktionsrealitätslücken
Wenn du dich vom Prototyp zur Produktion bewegst, brauchst du
- Determinismus Die gleiche Eingabe sollte vorhersagbares Verhalten erzeugen
- Validierung Vergewissern Sie sich, dass die Ausgabe von LLM-'s vor der Ausführung sicher ist.
- Sandboxen Begrenzen Sie, was generierter Code tatsächlich tun kann
- Kostenkontrolle Verfolgen Sie Token-Nutzung und setzen Sie Grenzen
- Lokale Schlussfolgerung Ausführen von Modellen offline ohne Cloud-Abhängigkeiten
LangChain optimiert für Iterationsgeschwindigkeit, nicht Produktion Härten. Dass ' fein für Demos; es ist ein Problem für die Produktion.
Was ich stattdessen baue
Hier ist das mentale Modell, das ich verwende. LLMs sind Triebwerke, die nicht ausführen
LLMs tun .:
- Auslegung Benutzer-Intention von der natürlichen Sprache verstehen
- Planung Überbrechen komplexer Aufgaben in Schritte
- Übersetzung Umwandeln von Intent in strukturierte Formate
LLMs tun NICHT :
- Aggregate berechnen Zeilen, die summieren
- Datensätze scannen Suche nach großen Dateien
- Eigener Staat Langzeitgedächtnis beibehalten
Das Prinzip„:" LLMs Grund ,. , Motoren berechnen , . ,
Diese Trennung treibt alles an, was ich baue.
Expliziter Kontext, nicht magischer Speicher
Anstelle des Rahmens, des verwalteten Speichers, der ,, baue ich den Kontext explizit pro Anfrage aus.
public class QueryContext
{
public List<ColumnInfo> Schema { get; set; }
public List<Dictionary<string, string>> SampleRows { get; set; }
public List<ConversationTurn> History { get; set; }
public string UserQuestion { get; set; }
}
Jede prompte Konstruktion ist sichtbar. Ich weiß genau, was an die LLM gesendet wird, weil ich selbst den String gebaut habe.
private string BuildPrompt(QueryContext context)
{
var sb = new StringBuilder();
sb.AppendLine("You are a SQL expert. Generate a query based on:");
sb.AppendLine();
// Schema
sb.AppendLine("Schema:");
foreach (var col in context.Schema)
sb.AppendLine($" - {col.Name}: {col.Type}");
// History (if any)
if (context.History.Any())
{
sb.AppendLine("\nPrevious conversation:");
foreach (var turn in context.History.TakeLast(3))
sb.AppendLine($" Q: {turn.Question} → SQL: {turn.Sql}");
}
// Current question
sb.AppendLine($"\nQuestion: {context.UserQuestion}");
sb.AppendLine("Generate SQL (no explanation, just the query):");
return sb.ToString();
}
Kein versteckter Zustand... keine magische Verkettung... nur explizites String-Gebäude... wenn es falsch ist... ich weiß warum...
Deterministische Ausführungsebenen
Anstatt das LLM irgendetwas ausführen zu lassen, benutze ich es zum Generieren. AbsichtDann führen Sie diese Absicht durch deterministische Motoren aus.
- SQL-Motoren Für Datenabfragen
- Suchmaschinen Für den Dokumentenabruf
- Regelmotoren Für die Geschäftslogik
- Dienstleistungen von Domains Für validierte Operationen
Die LLM generiert SQL-.-DuckDB führt es aus Das LLM sieht nie die Daten.
// LLM generates intent
var sql = await GenerateSqlAsync(context);
// Validate before execution
var error = ValidateSql(connection, sql);
if (error != null)
{
// Retry with error feedback
sql = await GenerateSqlAsync(context, previousError: error);
}
// Execute in sandboxed engine
var results = ExecuteQuery(connection, sql);
Das ist sicherer, schneller und debuggbar. DROP TABLE weil ich die SQL zuerst validiere Die LLM-Kanone Auslaufdaten, weil sie nie sieht, dass die Daten nur das Schema
Ein konkretes Beispiel für eine CSV-Analyse ohne Rahmen
Ich habe vor kurzem über Analyse großer CSV-Dateien mit lokalen LLMsDie Architektur
Benutzerfrage LLM SQL Ergebnisse
Die LLM erhält
- Das CSV-Schema .( .Spalte Namen und Typen
- Beispielzeilen von (um das Datenformat zu verstehen
- Die Frage des Benutzers
Die LLM erzeugt .: .
- Eine DuckDB SQL-Abfrage
Das System dann
- Validiert die SQL mit
EXPLAINFehler bei der Syntax ohne Ausführen von ) - Führt die Abfrage gegen die CSV-Datei aus
- Gibt die Ergebnisse an den Benutzer zurück
Die LLM sieht nie die eigentlichen data-.-Es sieht nur Struktur-MSC1-
Dies ist, was LangChain nennen würde, ein " agent." Ausführen eines Systems, das eine LLM verwendet, um Aktionen zu generieren.MSC3 validiert sie und führt sie aus.
Außer ich baute es in den Linien von C.M.S.K1 mit keinem Rahmen
public class CsvQueryService
{
private readonly OllamaApiClient _ollama;
private readonly string _model;
public async Task<QueryResult> QueryAsync(string csvPath, string question)
{
using var connection = new DuckDBConnection("DataSource=:memory:");
connection.Open();
// 1. Build context
var context = BuildContext(connection, csvPath, question);
// 2. Generate SQL
var sql = await GenerateSqlAsync(context);
// 3. Validate
var error = ValidateSql(connection, sql);
if (error != null)
{
// Retry once with error feedback
sql = await GenerateSqlAsync(context, error);
}
// 4. Execute
return ExecuteQuery(connection, sql);
}
}
Dass es ' ist Keine Ketten , Kein Agenten-Framework, Kein Magie. Nur explizite Orchestrierung der LLM-Validierung
Was ist ein Agent?
Der Begriff " wird ständig herumgeworfen.
Ein Agent ist:
- Eine Schleife Es läuft mehrere Iterationen
- Mit Staat Es erinnert sich, was es versuchte
- mit Werkzeugen Es kann Maßnahmen in der Welt ergreifen
- Mit Rückkopplung Es beobachtet Ergebnisse und passt sich an
Ein Agent ist keine BibliothekEs ist ein Muster von .
Mein Agenten-Muster in C.M.S.K.
public class Agent
{
private readonly List<ConversationTurn> _history = new();
public async Task<string> RunAsync(string goal)
{
while (!IsGoalAchieved(goal))
{
// 1. Generate next action based on history
var action = await GenerateActionAsync(goal, _history);
// 2. Validate before executing
if (!IsActionSafe(action))
{
_history.Add(new ConversationTurn
{
Action = action,
Result = "REJECTED: Unsafe action"
});
continue;
}
// 3. Execute through deterministic tool
var result = await ExecuteActionAsync(action);
// 4. Record and continue
_history.Add(new ConversationTurn { Action = action, Result = result });
}
return GenerateSummary(_history);
}
}
Dies ist ein Agent ,. , es ist eine Schleife mit Zustand , , , Werkzeuge und Feedback , . Ich schrieb es in Linien , . , ich habe nicht brauchen ein Framework
Wo Microsoft®'s Agent Framework passt
Um fair zu sein, hat Microsoft die Microsoft Agent Framework dass die Verwendungszwecke von -, gebaut für Entwickler von .NET Gebäudeproduktion AI-Systeme
Was das Microsoft Agent Framework richtig macht
Das Rahmenwerk ( früher als Microsoft bekannt...Extensions" bietet :.
- Explizite Orchestrierung Sie steuern die Agent-Loop, nicht das Framework.
- Starke Schreibweise Zeitsicherheit für Werkzeugdefinitionen und Funktionsaufrufe
- Erste Beobachtbarkeit der --Klasse - Builded- , in der Telemetrie ,, , Protokollierung und verteilte Tracing über OpenTelemetry
- Unternehmensgrenzen Konzipiert für die Produktion von . NET-Systemen mit korrekter Konfiguration und Lebenszyklusmanagement
- Unterstützung für Multi---Modelle Abstractions over OpenAI, ,, Azure OpenAI und andere Anbieter
- Integration des Semantischen Kernels Funktioniert mit einem breiteren AI-Stack von Microsoft.
Schlüsselkomponenten
IChatClientUnified Interface für Chat-VervollständigungenIEmbeddingGeneratorVector embeddings zwischen AnbieternAIFunctionSicherheitsfunktion ruft- Middleware-Pipeline für das Protokollieren von ,, retry-,, Caching-,, Telemetrie
Beispiel:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddChatClient(builder =>
builder.UseOllama("llama3.2")
.UseOpenTelemetry()
.UseLogging());
var app = builder.Build();
app.MapPost("/chat", async (IChatClient client, string message) =>
{
var response = await client.CompleteAsync(message);
return response.Content;
});
Wo ich immer noch untere Ebene
Selbst mit Microsoft-Frameworks von ' Ich bevorzuge es, Kernorchestration explizit zu halten
Ich will nicht
- Undurchsichtige Planer Der Rahmen, der autonom entscheidet, welches Werkzeug zum Aufrufen
- Implizite Werkzeugauswahl Magic Routing basierend auf natürlichen Sprachbeschreibungen
- Versteckte Wiederholung Logik --Framework---Managed Fehlerwiederherstellung Ich kann '-Inspektion
Ich will
- Sichtbare Schleifen Ich sehe jede Iteration in meinem Code
- Prüfbare Schritte Ich kann die Entscheidungslogik testen
- Auswechselbare Komponenten Ich kann das LLM-,, die Werkzeuge, die Validierungsschicht austauschen.
- Expliziter Zustand Ich weiß genau, was im Kontext ist.
Microsoft®' s Agent Framework ist näher an, wie ich denke, als LangChain... Es respektiert . NET-Muster... verwendet Abhängigkeitsspritze richtig... und kämpft gegen das Ökosystem... aber lieber schreibe ich die Orchestrierung selbst.
Wann Sie das Microsoft Agent Framework verwenden möchten
- Erstellen von Chat-Anwendungen mit Funktionsaufruf
- Brauchen Sie Multi---Modell Unterstützung .( switch zwischen OpenAI , , , Azure , , , Ollama ,) ,
- Gewünschte Enterprise-Features (, Telemetrie,, Protokollierung,, verteiltes Tracing)
- Arbeit in einem Team, das Framework-Konsistenz bevorzugt
- Aufbau auf dem Semantic Kernel
Wann zu gehen framework- - --less-:
- Du brauchst volle Kontrolle über die Agent-Loop
- Sie bauen benutzerdefinierte Argumentationsmuster
- Sie wollen Null Abstraktion über Kopf
- Sie optimieren für spezifische Anwendungsfälle die CSV-Analyse oder das Web Scraping.
- Sie wollen genau verstehen, wie es funktioniert
Das Rahmenwerk doesns.' eliminiert architektonische Entscheidungen... Sie wählen immer noch, was im Kontext zu setzen ist... wie man Daten zerstückelt und wann man es erneut versucht.
Warum diese Skala besser lang ist
Rahmenbedingungen – keine Systeme altern aus mehreren Gründen besser
Leistung Mein CSV-Abfragedienst läuft sub.-100.ms, weil dort kein Rahmen zwischen dem LLM und DuckDB.. ist.
Kostenvorhersagbarkeit Ich kontrolliere genau, was zum LLM.. geht Keine versteckte prompte Inflation vom Rahmen...
Debuggability Wenn etwas bricht, debuggen I'm meinen Code nicht umkehren -engineering a framework 's magic
Privatsphäre Für Systeme mit strengen Anforderungen an die Datenresidenz, die genau wissen, was die Maschine ausmacht
Offline-Szenarien Edge-Geräte , air-- agappped networks, regulierte Umgebungen . Frameworks gehen davon aus, dass Internetzugang und Cloud-Dienste .
Einhaltung der Rechtsvorschriften Im Finanzwesen – , – Gesundheitsversorgung –, – und Regierung – , – müssen Sie oft jede Entscheidung erklären und auditieren.. – Das Rahmenwerk, das es getan hat, ist eine akzeptable Antwort.
Je eingeschränkter Ihre Umgebung ist, desto mehr wollen Sie explizite Kontrolle
Wann würde ich LangChain benutzen?
Um Kritiker zu entwaffnen, gibt es legitime Fälle, in denen I'...
Hackathons Geschwindigkeit zu demo zählt mehr als Architektur
Wegwerf-POCs Wenn Sie eine Idee validieren und planen, für die Produktion sowieso neu zu schreiben
Python---schwere Teams Wenn dein Team bereits fließend in Python ist, dann passt das Ökosystem stark.
Unterrichtskonzepte Die Abstraktionen von LangChain-' können Anfängern helfen, das Agentenmuster zu verstehen, bevor sie selbst bauen.
Zu wissen wann nicht etwas zu verwenden ist so wertvoll wie zu wissen, wann es zu benutzen ist
Das breitere Muster – :-Frameworks vs. .-Erste Prinzipien
Dies ist wirklich über LangChain... Es geht um das Tradeoff zwischen Frameworks und First--.Grundsätze Engineering.
Rahmen beschleunigen bekannte Probleme, wenn du das Gebäude der CRUD API mit 100 zusammenbringst.,. Reichweite für Entity Framework oder Dapper..
Aber LLM---powered Systeme Die richtigen Abstraktionen sind ,' situiert yet , noch , . , Wir wissen nicht , wenn ," , Ketten , oder , " agents , " , , und ," , Retriever , sind die richtigen mentalen Modelle .. .
In dieser Umgebung bevorzugen ich es, in der Nähe des Metalls zu bauen.
- LLMs über direkte API-Aufrufe
OllamaSharpOpenAI-SDK-) - Prompte Konstruktion über explizites String-Gebäude
- Validierung über die Domäne--spezifische Logik
- Ausführung mittels Verwendungszwecks--Building Engines Suche nach , usw.
Als Entwickler von .-NET habe ich eine starke Meinung darüber, wie Systeme gebaut werden sollten.
LangChain-'-Abstraktionen don.'.t Karte sauber zu jenen Meinungen, also benutze ich sie nicht.
Das Takeaway
Wenn du ein Entwickler von .®NET bist und LangChain ansiehst und mich fragst, ob ich das brauche, dann ist es meine Antwort.
Sie müssen die Probleme lösen LangChain löst Kontext-Management-Tool-Orchestrierungswerkzeug-Orchestralisierungs-Logik-Retry, Beobachtungsfähigkeit.
Du brauchst LangChain, um sie zu lösen Vor allem, wenn du die Explizitheit wertest, die starke Schreibweise und die Verhärtung der Produktion über das Rapid Prototyping
Das Prinzip, auf dem ich basiere
"-LLMs Grund ,.-Motoren berechnen ,.-Orchestertion ist Ihr zu besitzen , ."-
Oder mehr einfach
Wenn Sie die Probleme verstehen, die ein Framework löst, brauchen Sie häufig das Framework.
Bauen Sie Systeme, die Sinn in Ihrem Ökosystem machen, mit Ihren Einschränkungen, die ,, mit Ihrer Sprache, ', Idiomen, MSC3, für mich, MKK4, dass, ', C...
Für dich könnte es anders sein... und dass...
Das Ziel ist es, Frameworks zu vermeiden.Das Ziel ist, sie bewusst zu wählen.
Weiteres Lesen
- Analysieren von großen CSV-Dateien mit lokalen LLMs in C.# Ein konkretes Beispiel für LLM-SQL ohne Frameworks
- Abrufen und Analysieren von Webinhalten mit LLMs Web Scraping und Analyse ohne Frameworks
- Microsoft Agent Framework Dokumentation Offizielles Microsoft-Agenten-Framework für .-NET
- Microsoft-Erweiterungen. Grundlegende KI-Abstraktionen für ,."NET
- Semantischer Kern LLM-Orchestrierung SDK
- LangChain Dokumentation Um zu verstehen, was Sie wählen, nicht zu verwenden
- OllamaSharp Client für lokale LLM-Inferenz