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
Thursday, 18 December 2025
Όταν άρχισα να φτιάχνω συστήματα LLM, όλοι με έδειχναν προς την LangChain. "Είναι το πρότυπο," είπαν. "Όλα τα παραδείγματα το χρησιμοποιούν." Και είχαν δίκιο - αν είσαι στο οικοσύστημα Python, ο LangChain είναι παντού.
Αλλά εδώ είναι το θέμα: Δεν αποφεύγω LangChain επειδή είναι κακό. Το αποφεύγω επειδή λύνει προβλήματα που ήδη λύνω πιο ρητά, και για τη χρήση μου περιπτώσεις - C#, τοπικό συμπέρασμα, ιδιωτικότητα, προσδιορισμός - πλαίσια προσθέτουν τριβή αντί αξία.
Αυτό δεν είναι ένα post anti-LangChain. Είναι μια δημοσίευση σχετικά με την κατανόηση τι προβλήματα πλαίσια λύνουν, και συνειδητοποιώντας ότι μπορεί να μην τα χρειάζεστε.
Διατριβή: Αν καταλάβεις τα προβλήματα που λύνει ο Λανγκ Τσέιν, δεν χρειάζεσαι τον Λανγκ Τσέιν.
Ας είμαστε δίκαιοι πρώτα. LangChain υπερέχει σε πολλά πράγματα:
Γρήγορη πρωτοτυποποίηση - Μπορείς να έχεις ένα ντέμο σε λίγα λεπτά.
Ενσωμάτωση του οικοσυστήματος Python - Αν είστε ήδη στον κόσμο του Πάιθον/Τζούπιτερ/Πάντας, ο ΛανγκΤσέιν τα κόβει όλα μαζί απρόσκοπτα.
Χαμηλώνοντας το φράγμα - Για τους νέους ανθρώπους σε LLMs, παρέχει χρήσιμες αφαιρέσεις: άμεσα πρότυπα, εργαλεία κλήση μοτίβα, διαχείριση μνήμης, ενσωμάτωση διανυσματικών DB.
LangChain είναι ένα Επιταχυντής ενσωμάτωσηςΕπιταχύνει το μονοπάτι από το "Έχω μια ιδέα" μέχρι το "Έχω ένα ντέμο."
Αλλά είναι επίσης το σημείο όπου τα προβλήματα αρχίζουν για μένα ως ένα σύστημα παραγωγής C#.
Πριν από την απόρριψη ενός πλαισίου, θα πρέπει να καταλάβετε τι προβλήματα που λύνει. LangChain αντιμετωπίζει αυτά τα πραγματικά ζητήματα:
Πρόκειται για θεμιτά προβλήματα. " ερώτηση είναι: χρειάζεστε ένα πλαίσιο για την επίλυσή τους;
Για το έργο μου - κατασκευή παραγωγής .NET συστήματα με τοπικές LLMs, αυστηρές απαιτήσεις απορρήτου, και αποφασιστική συμπεριφορά - LangChain εισάγει τριβές σε διάφορους τομείς.
LangChain διαχειρίζεται τη μνήμη και το πλαίσιο για σας. Αυτό ακούγεται βολικό μέχρι να χρειαστεί να αποσφαλματώσετε γιατί η πρότασή σας είναι 10.000 μάρκες περισσότερο από το αναμενόμενο, ή γιατί η LLM ξαφνικά έχει πρόσβαση στο ιστορικό συζήτησης που νόμιζες ότι είχες καθαρίσει.
Όταν κάτι σπάει, αποσφαλματώνεις τη συμπεριφορά του πλαισίου, όχι τη συμπεριφορά του κώδικα σου.
Μόλις υιοθετήσεις την LangChain, αρχίζεις να σχεδιάζεις για LangChain. Αρχιτεκτονική σας συνδυάζεται με τις αφαιρέσεις του πλαισίου: αλυσίδες, πράκτορες, ριτρίβερ, μνήμη μνήμης.
Αυτό δεν είναι μοναδικό για τον LangChain - όλα τα πλαίσια το κάνουν αυτό. Αλλά σε ένα ταχέως κινούμενο πεδίο όπως LLMs, όπου οι σωστές αφαιρέσεις δεν έχουν ακόμη διευθετηθεί, η σύνδεση με την κοσμοθεωρία ενός πλαισίου είναι επικίνδυνη.
Η LangChain υποθέτει:
Ως προγραμματιστής NET, υποθέτω:
Η Λιμάνια LangChain NET υπάρχουν, αλλά παίζουν catch-up με την έκδοση Python, και οι αφαιρέσεις εξακολουθούν να αισθάνονται ξένοι σε idiomatic C#.
Όταν μετακινείστε από πρωτότυπο στην παραγωγή, χρειάζεστε:
Η LangChain βελτιστοποιεί την ταχύτητα της ροής, όχι τη σκλήρυνση της παραγωγής.
Εδώ είναι το πνευματικό μοντέλο που χρησιμοποιώ: Οι LLM είναι μηχανές λογικής, όχι κινητήρες εκτέλεσης.
Η αρχή: Λόγο LLMs.Οι μηχανές compute.
Αυτός ο χωρισμός οδηγεί ό,τι φτιάχνω.
Αντί για μνήμη που διαχειρίζεται το πλαίσιο, φτιάχνω ρητά το πλαίσιο ανά αίτημα:
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; }
}
Ξέρω ακριβώς τι στέλνεται στο LLM επειδή έφτιαξα τη χορδή μόνος μου:
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();
}
Δεν υπάρχει κρυφή κατάσταση, δεν υπάρχει μαγεία, απλά σαφής κατασκευή χορδών, όταν είναι λάθος, ξέρω γιατί.
Αντί να αφήσω το LLM να εκτελέσει οτιδήποτε, το χρησιμοποιώ για να δημιουργήσω πρόθεση, στη συνέχεια να εκτελέσει αυτή την πρόθεση μέσω καθοριστικοί κινητήρες:
Το LLM παράγει SQL. DuckDB το εκτελεί. Το LLM δεν βλέπει ποτέ τα δεδομένα:
// 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);
Αυτό είναι ασφαλέστερο, γρηγορότερο και αποσφαλματωμένο. DROP TABLE Το LLM δεν μπορεί να διαρρεύσει δεδομένα επειδή δεν βλέπει ποτέ τα δεδομένα - μόνο το σχήμα.
Πρόσφατα έγραψα για ανάλυση μεγάλων αρχείων CSV με τοπικά LLMs. Η αρχιτεκτονική:
Ερώτηση χρήστη → LLM → SQL → DuckDB → Αποτελέσματα
Το LLM λαμβάνει:
Το LLM δημιουργεί:
Το σύστημα τότε:
EXPLAIN (Σφάλματα σύνταξης αλιευμάτων χωρίς εκτέλεση)Το LLM δεν βλέπει ποτέ τα πραγματικά δεδομένα.
Αυτό είναι αυτό που ο LangChain θα αποκαλούσε "πράκτορα" - ένα σύστημα που χρησιμοποιεί ένα LLM για να παράγει ενέργειες, να τις επικυρώνει, να τις εκτελεί, και ενδεχομένως επαναπροσδιορίζει την αποτυχία.
Μόνο που το έφτιαξα σε ~200 γραμμές του C# χωρίς πλαίσιο:
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);
}
}
Χωρίς αλυσίδες, χωρίς πλαίσιο πρακτόρων, χωρίς μαγεία, μόνο ρητή ενορχήστρωση του LLM → επικύρωση → εκτέλεση.
Ο όρος "πράκτορας" ρίχνεται συνεχώς, συνήθως σημαίνει "οτιδήποτε αφορά ένα LLM." Ας είμαστε ακριβείς.
Ένας πράκτορας είναι:
Ένας πράκτορας είναι όχι βιβλιοθήκηΕίναι ένα μοτίβο.
Το μοτίβο μου για τον πράκτορα στο 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);
}
}
Αυτός είναι ένας πράκτορας, είναι ένας βρόχος με κρατικά εργαλεία, και σχόλια, το έγραψα σε 30 γραμμές, δεν χρειαζόμουν πλαίσιο.
Για να είμαστε δίκαιοι με το οικοσύστημα .NET, η Microsoft έχει κυκλοφορήσει το Πλαίσιο Microsoft Agent Είναι φτιαγμένο για προγραμματιστές .NET που φτιάχνουν συστήματα παραγωγής AI.
Το πλαίσιο (πρώην γνωστό ως Microsoft.Extensions.AI) παρέχει:
Βασικά συστατικά:
IChatClient - Unified interface για ολοκλήρωση συνομιλίαςIEmbeddingGenerator - Καταχωρήσεις Vector σε όλους τους παρόχουςAIFunction - Λειτουργία ασφαλείας τύπου κλήσηςΠαράδειγμα:
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;
});
Ακόμα και με το πλαίσιο της Microsoft, προτιμώ να κρατάω τον πυρήνα της ενορχήστρωσης σαφή:
Δεν θέλω.
Θέλω:
Το Microsoft's Agent Framework είναι πιο κοντά στο πώς σκέφτομαι από το LangChain. Σέβεται τα πρότυπα .NET, χρησιμοποιεί ένεση εξάρτησης σωστά, και δεν καταπολεμά το οικοσύστημα.
Πότε να χρησιμοποιήσετε το πλαίσιο Microsoft Agent:
Πότε να πάει χωρίς πλαίσιο:
Το πλαίσιο δεν εξαλείφει τις αρχιτεκτονικές αποφάσεις. Εξακολουθείς να επιλέγεις τι να βάλεις στο πλαίσιο, πώς να κόβεις δεδομένα και πότε να ξαναπροσπαθείς.
Τα συστήματα χωρίς πλαίσιο γερνούν καλύτερα για διάφορους λόγους:
Επιδόσεις Η υπηρεσία έρευνας του CSV τρέχει κάτω από 100ms επειδή δεν υπάρχει πλαίσιο μεταξύ του LLM και του DuckDB.
Πρόβλεψη κόστους - Ελέγχω ακριβώς τι πάει στο LLM... δεν υπάρχει κρυφός άμεσος πληθωρισμός από την μνήμη του πλαισίου.
Αποσφαλματισμός - Όταν κάτι σπάσει, αποσφαλματώνω τον κωδικό μου, όχι αντιστροφή-μηχανισμός ένα πλαίσιο apos? S μαγεία.
Απόρρητο - Για συστήματα με αυστηρές απαιτήσεις παραμονής δεδομένων, γνωρίζοντας ακριβώς τι αφήνει το μηχάνημα μετράει.
Σενάρια εκτός γραμμήςName - Edge συσκευές, air-gapped δίκτυα, ρυθμιζόμενα περιβάλλοντα. Πλαίσια αναλαμβάνουν την πρόσβαση στο διαδίκτυο και υπηρεσίες σύννεφο.
Κανονιστική συμμόρφωση - Στα οικονομικά, την υγειονομική περίθαλψη και την κυβέρνηση, συχνά χρειάζεται να εξηγείτε και να ελέγχετε κάθε απόφαση. "Το πλαίσιο το έκανε" δεν είναι μια αποδεκτή απάντηση.
Όσο πιο περιορισμένο είναι το περιβάλλον σας, τόσο περισσότερο θέλετε σαφή έλεγχο.
Για να αφοπλίσω επικριτές: υπάρχουν νόμιμες υποθέσεις που θα έψαχνα για τον Λανγκ Τσέιν.
Hackathons - Η ταχύτητα στο ντέμο δεν είναι μόνο αρχιτεκτονική.
Throwaway POCs - Αν επικυρώνετε μια ιδέα και σχεδιάζετε να ξαναγράψετε για παραγωγή ούτως ή άλλως.
Ομάδες Python-heavy - Αν η ομάδα σας είναι ήδη άπταιστη στο Πάιθον, η εφαρμογή του οικοσυστήματος είναι ισχυρή.
Έννοιες διδασκαλίας - Οι αφαιρέσεις του LangChain μπορούν να βοηθήσουν τους αρχάριους να κατανοήσουν το μοτίβο του πράκτορα πριν φτιάξουν το δικό τους.
Γνωρίζοντας πότε Όχι, όχι. Το να χρησιμοποιείς κάτι είναι τόσο πολύτιμο όσο το να ξέρεις πότε να το χρησιμοποιείς.
Δεν έχει να κάνει με τον Λανγκ Τσέιν, αλλά με την ανταλλαγή μεταξύ των πλαισίων και της μηχανικής των πρώτων αρχών.
Τα πλαίσια επιταχύνουν τα οικεία προβλήματα. Αν φτιάχνετε το 100ο CRUD API, επικοινωνήστε με το Πλαίσιο ή το Ντάπερ. Τα μοτίβα είναι τακτοποιημένα.
Δεν ξέρουμε αν οι "αλυσίδες" ή οι "πράκτορες" ή οι "θρήνοι" είναι τα σωστά νοητικά μοντέλα.
Σε αυτό το περιβάλλον, προτιμώ να χτίσω κοντά στο μέταλλο:
OllamaSharp, OpenAI SDK)Ως προγραμματιστής .NET, έχω ισχυρές απόψεις σχετικά με το πώς πρέπει να κατασκευαστούν τα συστήματα: ρητή διάρκεια ζωής, ισχυρή δακτυλογράφηση, async σε όλη τη διαδρομή προς τα κάτω, ένεση εξάρτησης για τη δυνατότητα ελέγχου.
Οι αφαίρεσεις του Λανγκ Τσέιν δεν χαρτογραφούν καθαρά αυτές τις απόψεις, οπότε δεν τις χρησιμοποιώ.
Αν είσαι προγραμματιστής .NET που κοιτάζει τον LangChain και αναρωτιέται "Χρειάζομαι αυτό;," ορίστε η απάντησή μου:
Πρέπει να λύσεις τα προβλήματα που λύνει ο Λανγκ Τσέιν. - διαχείριση πλαισίων, ενορχήστρωση εργαλείων, λογική επαναπροσδιορισμού, παρατηρησιμότητα.
Δεν χρειάζεσαι τον Λανγκ Τσέιν για να τους λύσεις. - Ειδικά αν εκτιμάτε τη σαφήνεια, την ισχυρή δακτυλογράφηση, και την παραγωγή σκλήρυνσης πάνω από την ταχεία πρωτοτυποποίηση.
Η αρχή στην οποία βασίζομαι:
Η ενορχήστρωση είναι δική σου.
Ή πιο απλά:
"Αν καταλαβαίνεις τα προβλήματα που λύνει ένα πλαίσιο, συχνά δεν χρειάζεσαι το πλαίσιο."
Χτίστε συστήματα που έχουν νόημα στο οικοσύστημα σας, με τους περιορισμούς σας, χρησιμοποιώντας τους ιδιωματισμούς της γλώσσας σας.
Για σένα, μπορεί να είναι διαφορετικά και δεν πειράζει.
Ο στόχος δεν είναι να αποφευχθούν τα πλαίσια. Ο στόχος είναι να τα επιλέξετε συνειδητά, κατανοώντας τόσο το τι παρέχουν όσο και το κόστος τους.
Περαιτέρω ανάγνωση:
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.