Varför använder jag inte LangChain? Vad gör jag istället?
I' är en . NET-utvecklare . När jag började bygga LLM, -, kraftfulla system,,, pekade alla på mig mot LangChain.., ", det är ', standarden.," sa de: "" ., M SK10, alla exempel använder den ""..", och de hade rätt.
Men här är det: ' är grejen, : Jag undviker LangChain eftersom den är dålig. . Jag undvek den för att den löser problem som jag redan löst mer explicitt., och för mina användarfall.
Det här är en post om att förstå vilka problemframställningar löser och att inse att man kanske inte behöver dem.
Teorin: Om du förstår problemen som LangChain löser,
Vad LangChain faktiskt gör bra
Låt oss vara rättvisa först. LangChain är duktig på flera saker.
Rapid prototyping - Du kan få en fungerande demo på några minuter . De exemplen som du fått igång är riktigt bra
Pythons ekosystemintegration - Om du ' är redan i Python/Jupyter
Att sänka barriären - För folk som nykommar till LLMs , den ger användbara abstraktioner : prompt-templater M SK3 verktygsrakande mönster för att ringa Mska4 minneshantering M Ska5 vektordatabasintegreringar
LangChain är en integrationsaccelerator, inte en AI-anforderung . Den accelererar vägen från "~ Jag har en idé till "~ I have a demo ."~ Det är värdefullt
Men det är också där problemet börjar för mig som C-byggare som bygger produktionssystem.
Problemet som LangChain löser
Innan man avlägsnar ett ramverk, måste man förstå vilka problem det löser.
- Kontextkonstruktion - Att bygga konsekventa prompter från schemat , prover
- verktygsorkestering - Att hantera flera verktygsuttalande i sekvenser med villkorlig logik
- Stadsstyre - Att upprätthålla konversationskontext över flera vridningar
- Försök igen och lösa fel - Att återhämta elegant när LLM genererar felaktig utgång
- Multi-steg resonemang - Breaking of complex tasks into sequential steps
- Observerbarhet - Att följa vad som faktiskt hände under uitvoeringen
Det här är legitima problem.
Var LangChain börjar skadas
För mitt arbete - byggproduktion . NET-system med lokala LLMs | , | strikta privatlivsbehov |, | och deterministiskt beteende ♫ - | LangChain introducerar friktion i flera områden
Hemliga tillstånd och dolda kontrollflöden
LangChain sköter minnet och kontexten för dig.
Frameworket kankotekera instruktioner, sköter minnet , och hanterar exécutionsorten implizit. När något går sönderM SK3 gör duMSC4 avbuggar frameworket ' beteenden Mska6 inte din kod Mske7 beteendetMska8
Framework-Koppelat tankesätt
När du håller på med LangChain, så börjar du designa för LangChain. Din arkitektur blir kopplad till ramverket ' abstraktionerna M SK2 kedjor , agenter
Detta är inte unikt för LangChain. Alla ramverk gör det. Men i ett snabbt rörligt område som LLM, där rätt abstraktioner inte finns, är ' ännu löst. , kopplar ihop med ett ramverk, ' synsättet på världen är riskfyllt.
Impedans mismatch i Python
LangChain antar:
- lång tidiga processer
- Flygbar global tillstånd
- Python's dynamiska typning och duck-typning
- Att blockera I/O-mönster
Som .NET-utvecklare , antar jag
- begäran-inriktade livslängder (ASPM SK2NET Core-mönster
- Immutable or explicit-manad state
- Den starka typen och sammansättningen-tidssäkerhet
- Async/ väntar överallt
Den LangChain .NET-Porter existerar, men de spelar catch med Pythonversionen, och abstraktionerna känns fortfarande främmande för språkliga C.
Production Reality Gaps
När du flyttar från prototyp till produktion
- Determinism - Samma inmatning borde ge ett förutsägbart beteende
- Validering - Se till att LLMs output är säker innan man driver den
- Sandboxing - Begränsa vad genererad kod faktiskt kan göra
- kostnadskontroll - användandet av spårets token och införa gränser
- Lokala slutsatser - kör modeller offline utan molnhängande
LangChain optimerar för upprepningshastigheten.
Vad jag bygger istället
Här är den mentala modellen jag använder LLM är tankemotorer
LLMs Do:
- Interpretering - Att förstå användarmedvetandet från naturlig språk
- Planering - Delade komplexa uppgifterna i steg
- Vertaling - Konverterande av mening till strukturerade format SQL, JSONM SK3 funktionssignaler
LLMs gör inte det:
- Beräkningar av agregater - sammanfattning 100,000 rader
- Scan datamängder - Söker genom stora filer
- Själva staten - Att upprätthålla lång tid
Principen: LLMs skäl. Motorernas beräkningar.
Den här separationen driver allt jag bygger.
Explicerad Kontext , Inte magisk minne
Istället för ett ramverk-kontrollerad minne , bygger jag kontext explicit per utmaning:
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; }
}
Varje promptkonstruktion är synlig.
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();
}
Inga dolda tillstånd . Inga magiska koncatenationer. Bara explicitt strömbyggande. När det är felM SK3
Deterministiska utföringslayer
Istället för att låta LLM utföra något, använder jag den för att generera avsikt, sedan utför den intentionen genom deterministiska motorer
- SQL-motorer (DuckDB
- sökmotorer (LuceneM SK1 Postgresfulla -text) - För att hitta dokument
- Reglermotorer - För affärslogi
- Domaintjänster - För validerade operationer
LLM genererar SQL. DuckDB löser det
// 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);
Det är säkrare, snabbare , och lösbart. LLM kan inte köra på grund av olyckor DROP TABLE eftersom jag validerar SQL först
Ett konkret exempel: CSV-analys utan ram
Jag skrev nyligen om att analysera stora CSV-filer med lokala LLMs. Architekturen
Användarfråga → LLM | → | SQL | → | DuckDB |→
LLM får:
- CSV-schematen (columns namn och typer)
- 3 prover rader ( för att förstå dataformatet
- Användaren's fråga
LLM genererar:
- En DuckDB SQL-fråga
Systemet då:
- Validerar SQL med hjälp av
EXPLAIN( fångar syntaktiska fel utan att utföra - Executerar queryn mot CSV: s file
- Ge tillbaka resultat till användaren
LLM ser aldrig faktiska data.
Detta är vad LangChain skulle kalla ett system som använder en LLM för att generera handlingar
Förutom att jag byggde den i ~200 linjer av C# utan ram
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);
}
}
Det är ', det är det . No chains, no agent framework, no magic. Just explicit orchestration of LLM.
Vad är en agent?
Ordet """, agenten, ", sprids ständigt "", ,, brukar betyda """, allt som involverar en LLM.
En agent är:
- En lus - Den kör flera repetitioner
- Med stat - Den minns vad den triedt
- Med verktyg - Den kan ta åtgärder i världen
- Med återkoppling - Den observerar resultat och justerar
En agent är inte en bibliotek. Det ' är ett mönster
Mitt agentmönster i C#:
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);
}
}
Det här är en agent.
Där Microsofts Agent Framework passar
För att vara rättvis mot .NET ekosystem , Microsoft har släppt Microsoft Agent Framework att's syfte- byggts för NET utvecklare som bygger produktions-AI-system.
Vad Microsoft Agent Framework får rätt till
Frammedan ( tidigare känt som Microsoft .Extensioner.AIM SK3 erbjuder
- Explicerad orkestrering - Du kontrollerar agentloopet , inte ramverket
- Den starka typen - Kompilera - tids säkerhet för verktygsdefinitioner och funktionsändning
- Observerbarhet i första klass - Inbyggda - i telemetrin , registrerade data, , och fördelade spårning via OpenTelemetry
- Företagsgränser - Designad för produktion .NET-system med rätt DI, konfiguration , och livscykelanalys
- Multi-modellstöd - Abstraktioner över OpenAI
- Semantisk Kernelintegrering - Fungerar med Microsofts bredare AI-steg
Nyckelkomponenter:
IChatClient- Förenklad gränssnitt för konversationerIEmbeddingGenerator- Vektor-inbäddar mellan leverantörerAIFunction- Typ- Medverkningssledning - För att registrera apparater , för att återtesta apparaterna
exempel:
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;
});
Där jag fortfarande stannar lägre
Även med Microsofts framework, prefererar jag att hålla kärnans orkestr explicit.
Jag vill inte
- Osynliga planörer - Ramen som självständigt bestämmer vilket verktyg man ska använda
- Implicita verktygslektioner - Magikartade baserat på naturspråksbeschreibunger
- Hemlig återtestningslogik - ramverk - skött felupphävaning Jag kan inspectera
Jag vill:
- Visible kretsar - Jag ser varje repetition i min kod
- Testbara steg - Jag kan testa beslutslogiken
- Ersättningsbara komponenter - Jag kan byta ut LLM, ,, verktygen och ,, bekräftelselayern
- Explicerad tillstånd - Jag vet exakt vad
Microsofts Agent Framework är närmare det jag tror än LangChains.
När man använder Microsoft Agent Framework:
- Att bygga chat-applikationer med funktionen
- Bra multi- --- -modellsupport. (- -överkoppling mellan OpenAI, ,- -Azure, ,- -Ollama och )-
- Vill företagsdelar (telemetri,loggningM SK2 fördelad spårning )
- Att arbeta i ett lag som föredrar ramkonsistens
- Byggnader ovanför den semantiska kärnan
När ska man gå fram i ramverket-lös:
- Du behöver full kontroll över agentloopet
- Du, ', bygger egna tankesätt
- Du vill ha noll abstraktion överhead
- Du optimerar för specifika användningsområden ( som CSV-analys eller web scraping
- Ni vill förstå exakt hur det fungerar
Frameworket eliminerar inte arkitektoniska beslut. Man väljer fortfarande vad man ska sätta in i sammanhanget. ,, hur man bryter ihop data.
Varför skalar detta bättre långt
Framework-lösa system åldras bättre av flera anledningar
Förmågor - Ingen abstraktion överhuvudtaget . Mitt CSV-sökningscenter kör sub-100ms eftersom det inte finns något ramverk mellan LLM och DuckDB
Förutsägbarhet - Jag kontrollerar exakt vad som går till LLM . Ingen gömd promptinflation från ramverket
Debuggbarhet - När något går sönder, Jag ' gör ont i min kod , inte bakåtvända, - utvecklar ett ramverk
Privatliv - För system med strikta dataresidensbehov , med exakt kunskap om vad som gör maskinen viktig
Offlinescenarior - Randdevicer , luft, - anpassningsbara nätverk, M SK3 reglerade miljöer, . Ramverk tar emot internet- och molntjänster,.
Reguleringsobservation - I finansiellt , inom sjukvården, , och i staten, M SK3 behöver man ofta förklara och revidera varje beslut.
Ju mer begränsad din miljö är, desto mer vill du ha explicit kontroll.
När jag skulle använda LangChain
För att avbrutna kritiker finns det legitima fall där jag
Hackathon - Rymden för att demonstrera är viktigare än arkitekturen
Slängda POCs - Om du 'Validerar en idé och planerar att skriva om för produktion i alla fall
Python-heavy teams - Om ditt team redan är flytande i Python
Lärningskoncepter - LangChain 's abstraktioner kan hjälpa nybörjare att förstå agentpattern innan de bygger sin egen
Att veta när inte att använda något är lika värdefullt som att veta när man ska använda det.
Det bredare mönstret, :, ramverk och ., första principerna
Det här handlar inte om LangChain, det handlar om ramverk och ingenjörskonst.
Ramper accelererar bekanta problem. Om du Builder ' den andra CRUD APIn
Men LLM, -, kraftfulla system, ?, rätt abstraktioner är inte klarat ännu, ', ., vi vet inte om ", kedjor, M SK6, eller ", agenter,", eller | ", sökare och ", är de rätta mentala modellerna.
I den miljön prefererar jag att bygga nära metallen
- LLM via direkt API sändning (
OllamaSharp, OpenAI SDK - Vinniga konstruktion genom explicitt strängbyggande
- Validering via domain-specifik logik
- Ausführung genom syfte-byggda motorer (SQLM SK2 sökningarMska3 etcMske4
Jag har starka åsikter om hur system ska byggas.
LangChains abstraktioner skiljer inte ' tydligt från de åsikterna, så jag använder dem inte
The Takeaway
Om du är en .NET-utvecklare som tittar på LangChain och undrar: "" Är det här något jag behöver? ""
Du behöver lösa problemen som LangChain löser - kontextstyrning , verktygsorganisering , repetitionslogik
Du behöver inte LangChain för att lösa dem. - Särskilt om du värderar upptydlighet , starkt skrivande M SK2 och att produktionen blir hårdare än snabb prototypisering
Principen jag bygger på
"LLMs skälM SK1 Motorernas beräkningar . Orchester är ditt eget
Eller mer enkelt:
"Om du förstår de problem som rammet löser,
Att bygga system som är vettiga i ditt ekosystem.,, med dina begränsningar.,, med hjälp av ditt språk.
För dig kanske det är annorlunda.
Målet är att välja dem medvetet, förstå vad de erbjuder och vad de kostar.
Weiterlesen:
- Att analysera stora CSV-Dater med lokala LLM i C# - Ett konkret exempel på LLM
- Att hämta och analysera webb innehåll med LLMs - Webskrapping och analys utan ramverk
- Microsoft Agent Framework Dokumentation - Microsofts officiella agentgränssnitt för .NET
- Microsoft.Extensioner.AI - Fundamental AI abstraktioner för .NET
- Semantisk kärna - Microsoft's LLM orkestrering SDK
- LangChain Dokumentation - För att förstå vad du väljer att inte använda
- Ollamascharp - C# klient för den lokala LLM-förklaringen