Back to "كيفية تحليل ملفات CVSV الكبيرة مع LLLMs المحلية في C"

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

AI C# Data Analysis DuckDB LLM Ollama

كيفية تحليل ملفات CVSV الكبيرة مع LLLMs المحلية في C

Thursday, 18 December 2025

السلسلة: LLLs المحلي للبيانات - الجزء 1 من 2

هذا هو الخطأ الذي يرتكبه الجميع: يحاولون أن يغذيوا سيرتهم الذاتية في إل إل إل إل إل إل. لا تفعل. وينبغي أن تولد هذه السجلات استفسارات، لا أن تستهلك البيانات.

لديك ملف CSV و تريد أن تسأل "ما هو متوسط قيمة الترتيب بحسب المنطقة؟" أدوات مثل جاري التنفيذ في Excel هل تستطيع فعل هذا ، ولكن ماذا لو كانت بياناتك حساسة جدا لخدمات السحابة ؟ ماذا لو احتجت ان تبنيها بنفسك ؟

هذه المقالة تظهر لكم كيف - محليا، خاصا، في C#.

استخدم DakDB للاستفسار عن ملفات CSV مباشرة. استخدم LLM محلي لتولد SQL. الـ LLM لا ترى بياناتك - فقط المخطط. Case: sub- 100m queentions on millon- row files, outline.

وللاطلاع على علاج تكميلي يركز بقدر أكبر على المبادرة المتكاملة للبيانات المكانية ويتوسع في استخدام الملامح الإحصائية كواجهة LLM (ويظهر أداة كاملة لتنفيذ هذه الأفكار - التنميط، وأسلوب SQL الآمن، والاستنساخ الاصطناعي، والكشف عن الانجراف)، انظر المقال المرافق: البيانات SD البيانات مخطِط: تحديد البيانات المحلية السريعة - ولا سيما القسم المعنون "The Key Update: Statistics as Interspace". وتشكل هاتان المقالتان سلسلة قصيرة عن أنماط LLM المحلية العملية + الاستعلام.

البصيرة الأساسية

استخدام LLM كمخزن بيانات هو خطأ التجريد. LLMs هي أساساً غير قادرة على مسح الملايين من الصفوف لحساب متوسط - هذا ليس ما هي عليه. حتى نافذة السياق الرمزي 200K تناسب ربما 50000 صف. لديك 500MB CSV ملايين.

الـ صحيح نمط: أسباب LLLL، قاعدة البيانات الحسابية.

flowchart LR
    A[User Question] --> B[LLM]
    B --> C[SQL Query]
    C --> D[DuckDB]
    D --> E[Results]
    
    style B stroke:#333,stroke-width:4px
    style D stroke:#333,stroke-width:4px

لاحظ ما يحدث: LLLM يولد استعلام SQL بناءً على سؤالك والمخطط. DakDB ينفذه على البيانات الفعلية. LLM لا يلمس بياناتك أبداً - إنه فقط يرى أسماء وأصناف الأعمدة. لهذا السبب هو سريع وخاص ودقيق.

وللاطلاع على مزيد من المعلومات عن معالجة النبذات باعتبارها واجهة LLLLM (ومؤشراً عملياً عملياً ملموساً يُنفِّذ التوصيفات - أولاً السرد، وسؤالاً مأموناً مدعوماً من SQL، وQ&A، وجلسات مدعومة بالسجل، واستنساخاً إصطناعياً)، انظر: البيانات SD البيانات مخطِط: تحديد البيانات المحلية السريعة.

لماذا لا مجرد تحميلها في الذاكرة؟

والنُهُج الواضحة تتشاطر جميعاً نفس العيب المميت:

Csvvvverer / إعدادات البياناتحمّل ملفّ الكل ملفّ إلى NAM. A 500MB CSV يصبح 2-4GB من كائنات. A 5GB ملفّ؟ OOOM تحطّم.

SQLite / PostgresQL: يحتاج إلى درجة استيراد بطيئة (دقائق للملفات الكبيرة)، وتعاريف أولية، وتكاليف عامة لإدارة قاعدة البيانات.

PandsAI: ما زالت تحمل كل شيء في الذاكرة. بالإضافة إلى ذلك، تنفيذ LLM الشفرة التعسفية المولدة من LLM كابوس أمني - SQL هو تفسيري ورمل قابل للتغليف؛ Python ليس.

لماذا DADB

DDB هو إستفسارات CCSV ملفات مباشرة مباشرة - لا خطوة استيراد، لا تحميل في الذاكرة:

using var connection = new DuckDBConnection("DataSource=:memory:");
connection.Open();
using var cmd = connection.CreateCommand();
cmd.CommandText = "SELECT Region, SUM(Amount) FROM 'sales.csv' GROUP BY Region";
// Executes directly against the file - no import, no memory explosion

السمة القاتلة: يُعامل الملفات كجداوللا يوجد طابور، لا مدخل سائب، لا إنتظار.

Vactor / Csvfrder / SQLite / DaddB / |--------|-----------|--------|--------| | ذاكرة يحمّل كامل ملفّ حمولات أثناء استيراد / سطور من قرص / | إنشاء [لا يوجد] Schema + استيراد: لا يوجد] | **** □ 2GB RAM □ دقائق لاستيراد □ | **** تحطّم في مكان الحادث / بطيئ جداً جداً يَعْملُ غرامةَ / | **** لا، لا، لا، نعم (10-100x أسرع)

DakDB هو ما يستخدمه مهندسو البيانات في بايثون في حالة الاستخدام هذه. صحائف التجليات تعطيك كامل دعم ADO.net - يبدو مثل أي قاعدة بيانات أخرى، إلا أنك تستجوب الملفات.

الـ

• العنصر / لماذا هذا الشخص / |-----------|--------------| | DDB أسئلة CSV مباشرة، لا توجد خطوة استيراد | الرشـتـان دعم كامل لـ ADO.net، يشعر بالوطن | الوليمة استدلال محلي، لا مفاتيح API، لا سحابة | الكسس □ بيانات الاختبار الواقعية على أي نطاق □ | qwen2.5-coder:7b أفضل دقة QQL SQL في حجم 7B

مذكرة بشأن الأمنهذا أكثر أماناً من الشفرة التعسفية، لكنّه ما زال يتطلب التحقق. قسم الأمن وللاطلاع على مناقشة أوسع بشأن تحويل الملامح إلى واجهة LLLL ومؤشراً محلياً ينفذ هذه الأنماط، انظر القطعة المرافقة. البيانات SD البيانات مخطِط: تحديد البيانات المحلية السريعة.

إنشاء مشروع

دعونا ننشئ مشروع عينة. تثبيت الحزمة:

dotnet add package DuckDB.NET.Data.Full
dotnet add package OllamaSharp
dotnet add package Bogus

سحب a تشفير التركيز نموذج هو جيّد في SQL:

ollama pull qwen2.5-coder:7b

ألف- الهيكل

وهنا كيف تنسجم القطع مع بعضها البعض:

flowchart TB
    subgraph Input
        Q[User Question]
        CSV[CSV File]
    end
    
    subgraph Processing
        Schema[Extract Schema]
        Sample[Get Sample Rows]
        Context[Build LLM Context]
        LLM[Generate SQL]
        Validate[Validate SQL]
        Execute[Execute Query]
    end
    
    subgraph Output
        Results[Query Results]
    end
    
    CSV --> Schema
    CSV --> Sample
    Schema --> Context
    Sample --> Context
    Q --> Context
    Context --> LLM
    LLM --> Validate
    Validate -->|Error| LLM
    Validate -->|OK| Execute
    CSV --> Execute
    Execute --> Results
    
    style LLM stroke:#333,stroke-width:4px
    style Execute stroke:#333,stroke-width:4px

الفكرة الرئيسية: نحن نعطي LLLM ثانياً - البيانات المتعلقة بالمخطط والبيانات المتعلقة بالعينةلا البيانات الفعلية. هذا يبقي السياق صغير والاستجابات سريعة.

لهذا السبب هذا الأمرالدالة LLM توليد النية (SQL). DaDB ينفّذ ذلك. الـ confid this this this this status synstatus obthing obs قبل التنفيذ. الـ restry place communicle fault. هذا الفصل هو ما يجعل النظام أكثر أماناً ودقة. لمزيد من التفصيل CLI- conconnect reviews (بما في ذلك النبذة - الأوّل thirg and sQL الآمن standards) انظر. البيانات SD البيانات مخطِط: تحديد البيانات المحلية السريعة.

الخطوة 1: توليد بيانات اختبار مع

هل لديك بيانات CSV؟ إلى هذا الخطوة 2: بناء الإطار.

قبل أن نتمكن من اختبار جهاز تحليل CSV الذي يعمل بطاقته LLLL، نحتاج إلى بيانات لتحليلها. من أجل التطوير والاختبار، البيانات الإصطناعية تتغلب على البيانات الحقيقية:

  1. الاختبار - توليد 100K أو 1M أو 10M صفوف للتحقق من الأداء في مختلف الأحجام
  2. **** - عدم وجود خطر الكشف عن البيانات الحقيقية للعميل/الشركات التجارية في العروض التوضيحية أو لقطات الشاشة
  3. **** - نفس البذرة = نفس البيانات، مما يجعل الحشرات قابلة لإعادة المعالجة
  4. حُجج - التحكم في التوزيع (مثل عودة القوة 5 في المائة، ونطاقات تواريخ محددة)

ما هو بوغوس؟

الكسس هو ميناء NET لمكتبة المزيفين الشعبية. يولّد بيانات زائفة واقعية المظهر - الأسماء، العناوين، البريد الإلكتروني، التواريخ، الأرقام - مع دعم محلي مناسب. بدلاً من اختبار التركيب اليدوي ملفات CSV أو استخدام بيانات القمامة العشوائية، بوغوس يعطيك بيانات أن النظرات في الواقع:

  • f.Name.FullName() • "جون سميث" (وليس "asdf1234")
  • f.Internet.Email() □ "[email protected]" (الصيغة الموضحة بصورة مباشرة)
  • f.Date.Between(start, end) □ التوزيع الحقيقي لتاريخ التوزيع
  • f.Commerce.ProductName() "الجبن الغراني المصنَّع" (متعة، ولكن يمكن الاعتراف بها)

هذا الأمر مهم لأن البيانات الواقعية تساعدك على تحديد القضايا - التهيئة الغريبة، التجميعات غير المتوقعة، حالات الحافة في التعامل مع التاريخ - التي يمكن أن تختبئ فيها السلاسل العشوائية.

التعريف بنموذج البيانات

internal class SaleRecord
{
    public string OrderId { get; set; } = "";
    public DateTime OrderDate { get; set; }
    public string CustomerId { get; set; } = "";
    public string CustomerName { get; set; } = "";
    public string Region { get; set; } = "";
    public string Category { get; set; } = "";
    public string ProductName { get; set; } = "";
    public int Quantity { get; set; }
    public decimal UnitPrice { get; set; }
    public decimal Discount { get; set; }
    public bool IsReturned { get; set; }
}

منفذ

يستخدم بوغوس معدلاً قياسياً متقناً لتحديد قواعد التوليد:

var categories = new[] { "Electronics", "Clothing", "Home & Garden", "Sports", "Books" };
var regions = new[] { "North", "South", "East", "West", "Central" };

var faker = new Faker<SaleRecord>()
    .RuleFor(s => s.OrderId, f => f.Random.Guid().ToString()[..8].ToUpper())
    .RuleFor(s => s.OrderDate, f => f.Date.Between(
        new DateTime(2022, 1, 1), 
        new DateTime(2024, 12, 31)))
    .RuleFor(s => s.CustomerId, f => $"CUST-{f.Random.Number(10000, 99999)}")
    .RuleFor(s => s.CustomerName, f => f.Name.FullName())
    .RuleFor(s => s.Region, f => f.PickRandom(regions))
    .RuleFor(s => s.Category, f => f.PickRandom(categories))
    .RuleFor(s => s.ProductName, (f, s) => GenerateProductName(f, s.Category))
    .RuleFor(s => s.Quantity, f => f.Random.Number(1, 20))
    .RuleFor(s => s.UnitPrice, f => f.Random.Decimal(9.99m, 299.99m))
    .RuleFor(s => s.Discount, f => f.Random.Bool(0.3f) ? f.Random.Decimal(0.05m, 0.25m) : 0m)
    .RuleFor(s => s.IsReturned, f => f.Random.Bool(0.05f));

دعونا نوضح ما يحدث:

  • f (الضعف) - حالة المولد مع إمكانية الوصول إلى جميع وحدات البيانات (الاسم، التاريخ، المنطقة العشوائية، وما إلى ذلك)
  • f.Random.Guid().ToString()[..8] - تُعدّ علامة رمزية ولكن تأخذ فقط أولاً فقط 8 درجات لـ a قراءة أمر تعريف
  • f.Date.Between() - التاريخ العشوائي ضمن نطاق واقعي )وليس السنة ٩٩٩٩٩(
  • f.PickRandom(array) - انتقِش عشوائياً من خيارات معرفة مسبقاً (الضمانات
  • f.Random.Bool(0.3f) - 30 في المائة فرصة حقيقية (30 في المائة من الطلبات تحصل على خصم)
  • **(f, s) ** - الوصول إلى كل من المزيفة والمزيفة والسجل الجزئي - هذا يسمح ProductName الاعتماد على Category

الـ (f, s) هذا التماسك يجعل البيانات المتولدة أكثر واقعية لاختبار التجميعات مثل "الإيراد حسب الفئة".

أنشئ واكتب إلى CSV

var records = faker.Generate(100_000); // Adjust for your testing needs

await using var writer = new StreamWriter(csvPath, false, Encoding.UTF8);
await writer.WriteLineAsync("OrderId,OrderDate,CustomerId,CustomerName,Region,Category,...");

foreach (var record in records)
{
    var total = record.Quantity * record.UnitPrice * (1 - record.Discount);
    await writer.WriteLineAsync($"{record.OrderId},{record.OrderDate:yyyy-MM-dd},...");
}

الـ توليد هو سريع لـ لـ بوغوس لـ سَتّة.

بِتْ بِجِيجأولاً- وضع Randomizer.Seed = new Random(12345) قبل توليد للحصول على بيانات قابلة للتكرير. نفس البذرة = نفس سجلات "العشوائية" في كل مرة، وهو أمر قيم للتنقيط.

الخطوة 2: بناء الإطار

قبل LLM قادر على توليد SQL، يحتاج إلى فهم بنية البيانات. نستخرج هذا من DakDB:

ألف - النموذج

public class DataContext
{
    public string CsvPath { get; set; } = "";
    public List<ColumnInfo> Columns { get; set; } = new();
    public List<Dictionary<string, string>> SampleRows { get; set; } = new();
    public long RowCount { get; set; }
}

public class ColumnInfo
{
    public string Name { get; set; } = "";
    public string Type { get; set; } = "";  // VARCHAR, DOUBLE, TIMESTAMP, etc.
}

هذا يلتقط كل شيء تحتاج إليه LLLM: أسماء الأعمدة، الأنواع، وعدد قليل من صفوف العينات لفهم شكل البيانات.

اخراج المخطط

DachdB يمكن أن يصف أي CVS بدون تحميله كلّ:

private DataContext BuildContext(DuckDBConnection connection, string csvPath)
{
    var context = new DataContext { CsvPath = csvPath };

    // Get schema - DuckDB infers types from the CSV
    using var cmd = connection.CreateCommand();
    cmd.CommandText = $"DESCRIBE SELECT * FROM '{csvPath}'";
    using var reader = cmd.ExecuteReader();

    while (reader.Read())
    {
        context.Columns.Add(new ColumnInfo
        {
            Name = reader.GetString(0),  // Column name
            Type = reader.GetString(1)   // Inferred type
        });
    }

    return context;
}

الـ DESCRIBE الأمر يقرأ فقط ترويسة الملف بالإضافة إلى بضعة صفوف للنوع الاستدلال - هو موجود حتى على ملفات ضخمة.

الحصول على البيانات

تساعد صفّات العينات LLLM على فهم أشكال البيانات (التواريخ، الهويات، وما إلى ذلك):

using var cmd = connection.CreateCommand();
cmd.CommandText = $"SELECT * FROM '{csvPath}' LIMIT 3";
using var reader = cmd.ExecuteReader();

while (reader.Read())
{
    var row = new Dictionary<string, string>();
    for (int i = 0; i < reader.FieldCount; i++)
    {
        var value = reader.IsDBNull(i) ? "NULL" : reader.GetValue(i)?.ToString() ?? "";
        row[reader.GetName(i)] = value;
    }
    context.SampleRows.Add(row);
}

ثلاثة صفوف عادة ما تكون كافية - فهي تبين LLLM ما هي الأشكال التي يمكن توقعها بدون إهدار الرموز.

خطوة توليد SQL مع LLL

هذا هو الجزء الصعب. الهندسة السريعة هنا غير قابلة للتفاوض - بدون قواعد صارمة، LLMs المحلية سوف تنتج الإبداع ولكن كسر SQL. الهدف هو التحديد، وليس الإبداع.

المبنى (المبنى)

private string BuildPrompt(DataContext context, string question, string? previousError)
{
    var sb = new StringBuilder();

    sb.AppendLine("You are a SQL expert. Generate a DuckDB SQL query to answer the user's question.");
    sb.AppendLine();
    sb.AppendLine("IMPORTANT RULES:");
    sb.AppendLine("1. The table is accessed directly from the CSV file path");
    sb.AppendLine("2. Use single quotes around the file path in FROM clause");
    sb.AppendLine("3. DuckDB syntax - use LIMIT not TOP, use || for string concat");
    sb.AppendLine("4. Return ONLY the SQL query, no explanation, no markdown");
    sb.AppendLine();
    
    sb.AppendLine($"CSV File: '{context.CsvPath}'");
    sb.AppendLine($"Row Count: {context.RowCount:N0}");
    sb.AppendLine();
    
    // Schema
    sb.AppendLine("Schema:");
    foreach (var col in context.Columns)
    {
        sb.AppendLine($"  - {col.Name}: {col.Type}");
    }

قسم القواعد مهم جداً - فهو يخبر LLLM بالضبط كيفية تشكيل الإستفسار لـ DakDB. أن يكون صريحاً حول syditax (LIMT vs TOP, concateation الأوتار) يمنع الأخطاء الشائعة.

جاري إضافة البيانات

    if (context.SampleRows.Count > 0)
    {
        sb.AppendLine();
        sb.AppendLine("Sample data (first 3 rows):");
        foreach (var row in context.SampleRows)
        {
            var values = row.Select(kv => $"{kv.Key}='{kv.Value}'");
            sb.AppendLine($"  {{{string.Join(", ", values)}}}");
        }
    }

تعافي

إذا فشلت محاولة سابقة، أدرج الخطأ:

    if (previousError != null)
    {
        sb.AppendLine();
        sb.AppendLine("YOUR PREVIOUS QUERY HAD AN ERROR:");
        sb.AppendLine(previousError);
        sb.AppendLine("Please fix the query based on this error.");
    }

    sb.AppendLine();
    sb.AppendLine($"Question: {question}");
    sb.AppendLine();
    sb.AppendLine("SQL Query (no markdown, no explanation):");

    return sb.ToString();
}

آلية إعادة البحث هذه مهمة - LLLS المحلية في بعض الأحيان تفعل أخطاء في الصياغة، وتعطيهم الخطأ عادة إصلاحه على المحاولة الثانية.

# نداء # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # # #

var request = new GenerateRequest { Model = _model, Prompt = prompt };
var response = await _ollama.GenerateAsync(request).StreamToEndAsync();
var sql = CleanSqlResponse(response?.Response ?? "");

الـ StreamToEndAsync() تنتظر الإستجابة الكاملة. لـ a أفضل UX، أنت يُمْكِنُ أَنْ تَرْفعَ الرموزَ عندما تَصِلُ.

تنظيف الاستجابة

غالباً ما تلف LLS SQL في كتل رمزية على الرغم من أنه تم إخبارها بعدم:

private string CleanSqlResponse(string response)
{
    var sql = response.Trim();

    // Remove markdown code blocks if present
    if (sql.StartsWith("```"))
    {
        var lines = sql.Split('\n').ToList();
        lines.RemoveAt(0);  // Remove opening ```sql
        if (lines.Count > 0 && lines[^1].Trim().StartsWith("```"))
        {
            lines.RemoveAt(lines.Count - 1);  // Remove closing ```
        }
        sql = string.Join('\n', lines);
    }

    return sql.Trim('`', ' ', '\n', '\r');
}

الخطوة 4: المصادقة قبل التنفيذ

DDB's EXPLAIN نتحقق من SQL selection unther this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this this

private string? ValidateSql(DuckDBConnection connection, string sql)
{
    try
    {
        using var cmd = connection.CreateCommand();
        cmd.CommandText = $"EXPLAIN {sql}";
        cmd.ExecuteNonQuery();
        return null; // Valid
    }
    catch (Exception ex)
    {
        return ex.Message;
    }
}

إذا فشل التحقق، نقوم بتغذية الخطأ مرة أخرى إلى LLM و إعادة الاختبار (حتى حد أقصى).

الخطوة 5: التنفيذ والشكل

الـ جاري التنفيذ و تنسيق مخرجات:

private QueryResult ExecuteQuery(DuckDBConnection connection, string sql)
{
    var result = new QueryResult { Sql = sql };

    try
    {
        using var cmd = connection.CreateCommand();
        cmd.CommandText = sql;
        using var reader = cmd.ExecuteReader();

        // Capture column names
        for (int i = 0; i < reader.FieldCount; i++)
        {
            result.Columns.Add(reader.GetName(i));
        }

        // Capture rows
        while (reader.Read())
        {
            var row = new List<object?>();
            for (int i = 0; i < reader.FieldCount; i++)
            {
                row.Add(reader.IsDBNull(i) ? null : reader.GetValue(i));
            }
            result.Rows.Add(row);
        }

        result.Success = true;
    }
    catch (Exception ex)
    {
        result.Success = false;
        result.Error = ex.Message;
    }

    return result;
}

الـ QueryResult (الصنف (مصنف بالكامل في مشروع العينة) يشمل ToString() كجدول مقروء.

ولأغراض التحليل التفاعلي، كثيراً ما يرغب المستعملون في طرح أسئلة متابعة:

"What's the total revenue?"
→ "Break that down by region"
→ "Show the top 5 regions"

والسؤالان الثاني والثالث لا معنى لهما إلا مع السياق من الأول.

تاريخ الحوار

public class ConversationTurn
{
    public string Question { get; set; } = "";
    public string Sql { get; set; } = "";
    public bool Success { get; set; }
    public int RowCount { get; set; }
    public string Summary { get; set; } = "";  // "Single value: 1234567.89"
}

إدراج التاريخ في الكتابات

if (_history.Count > 0)
{
    sb.AppendLine();
    sb.AppendLine("CONVERSATION HISTORY (for context):");
    
    foreach (var turn in _history.TakeLast(5))  // Last 5 turns
    {
        sb.AppendLine($"Q: {turn.Question}");
        sb.AppendLine($"SQL: {turn.Sql}");
        if (turn.Success)
        {
            sb.AppendLine($"Result: {turn.Summary}");
        }
        sb.AppendLine();
    }
}

التاريخ يعطي سياق LLLM لفهم الإشارات مثل "ذلك" أو "تلك النتائج" أو "كسره إلى أبعد من ذلك".

أي نموذج يمكن استخدامه؟

من أجل توليد SQQL، تعمل النماذج المركزة على الترميز بأفضل طريقة. ها هي الخيارات المتاحة عن طريق مكتبة أولاما النموذجية:

□ نموذج نموذجي للحجم JIU QQQQQ Quality link o

------- ------ ------- --------- ------
deepseek-coder-v2:16b □ 9GB / متوسط / متوسط / أفضل / الوليمة
codellama:7b * ٤ ملڠڠڠڠ / سرعة سريعة / / الوليمة
llama3.2:3b ° 2Ggggypt 2GB / سريع جداً جداً وسريع جداً وسريع جداً وسريع جداً الوليمة

بالنسبة لحالات الاستخدام الأكثر استخداماً، qwen2.5-coder:7b QL، سرعة جيدة، تشغيل على أجهزة متواضعة (8GB+RM).

م م م م

المقاييس المرجعية الحقيقية - العالمية

على اختبار 100K صف CSV ملف CSV (14MB) على آلة dev القياسية (Ryzen 5, NVMe SSD, 32GPRM):

• نوع السؤال/ الوقت |------------|------| الحساب المبسـط / 65ms / / /مجمـع بالمجموع بالسوم □ تجميع مركب مع ميكروم الفريق المتعدد الأطراف من إعداد فريق عامل

تحت-100m للاستفسارات التحليلية على 100K صف - بدون أي خطوة استيراد. استفسر عن التعقيدات التي تهم أكثر من عدد الصف ؛ DakDB محرك عمودي commends بفعالية بغض النظر عن حجم الملف.

نقل هذا إلى سِفك

للملفات فوق 1GB، هو 10.100x أسرع:

using var cmd = connection.CreateCommand();
cmd.CommandText = $"COPY (SELECT * FROM '{csvPath}') TO '{parquetPath}' (FORMAT PARQUET)";
cmd.ExecuteNonQuery();

ملف باركيت المضغوط هو أيضا أصغر بكثير.

الاعتبارات الأمنيــة

عند تنفيذ LLLMSQL:

private bool IsSafeQuery(string sql)
{
    var dangerous = new[] { "DROP", "DELETE", "TRUNCATE", "UPDATE", "INSERT", "ALTER", "CREATE" };
    var upperSql = sql.ToUpperInvariant();
    return !dangerous.Any(d => upperSql.Contains(d));
}

DADB في نمط الذاكرة في DADB يوفر أيضا العزلة الطبيعية - لا يمكن أن تؤثر على قواعد بيانات الإنتاج الخاصة بك.

مثال كامل

وهنا كيف تجمعت كلها معاً:

// Generate test data
await GenerateSalesCsvAsync("sales.csv", 100_000);

// Simple query
using var service = new CsvQueryService("qwen2.5-coder:7b", verbose: true);
var result = await service.QueryAsync("sales.csv", "What are total sales by region?");
Console.WriteLine(result);

// Conversational analysis
using var analyser = new ConversationalCsvAnalyser("sales.csv", "qwen2.5-coder:7b");

Console.WriteLine(await analyser.AskAsync("What's the total revenue?"));
Console.WriteLine(await analyser.AskAsync("Break that down by category"));
Console.WriteLine(await analyser.AskAsync("Which category has the most returns?"));

أولاً - موجز

النموذج العقلي للحفاظ على: أسباب LLLLS; قواعد البيانات compitute.

لا إطعام البيانات إلى LLM. إطعامها تخطيطية ، السماح لها بتوليد SQL ، تنفيذ أن SQL على محرك مناسب للاستفسار. هذا الفصل هو السبب في أن النهج يعمل على مقياس.

(أ) التنفيذ:

  1. DDB استفسارات CSV مباشرة - لا استيراد، مجاري من القرص
  2. الوصفة + العينات إعطاء LLLLM بما يكفي سياق بدون بيانات الكشف
  3. قواعد التنبيه المشددة SQL ، ليس مبتكر
  4. التصديق عن طريق EXPAIN منظمة الأمم المتحدة
  5. **** المُمَاَضَعَة لِزَلَةِ المُعَلِّمَةِ

النتيجة: استفسارات تحليلية تحت - 100ms على ملفات المليار دور، تماماً خارج الشبكة، مع بيانات لا تترك آلتك أبداً.

ويمكن الاطلاع على كامل مشروع العينة في الموقع التالي: CssvLlm - بما في ذلك CsvQueryService, ConversationalCsvAnalyser، وتوليد البيانات القائمة على بوغوس.

الموارد الخارجة عن

DDB

المكلم & LLLLs

اختبار توليد

(بآلاف دولارات الولايات المتحدة)

مواد مُسْمِمْمِم

logo

© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.