في الجزء 1, استكشفنا لماذا يهم GraphRAG GraphRAG الأقل قابلة للحياة مع ثلاثة اشكال استخراج:
| الطريقة | إتصالات الـ LLM | الأفضل ل |
|---|---|---|
| الهيوريستيكس (លំនាំដើម) | ♫0 لكل قطعة ♫ | |
| الهجين | 1 لكل سند | توازن السرعة والدقة S |
| LLM | 2 لكل قطعة | جودة الكيان الأعلى |
جميع الادوات تستخدم
السلسلة Navigation:
الرمز: الأكثر وضوحا.GraphRag على GitHub
flowchart LR
subgraph Indexing
MD[Markdown Files] --> CH[Chunker]
CH --> EMB[BERT Embeddings]
CH --> EXT[Entity Extractor]
EXT --> |heuristics + links| ENT[Entities]
ENT --> REL[Relationships]
REL --> COM[Communities]
end
subgraph Storage
EMB --> DB[(DuckDB)]
ENT --> DB
REL --> DB
COM --> DB
end
subgraph Query
Q[Query] --> CLASS{Classify}
CLASS --> |local| HS[Hybrid Search]
CLASS --> |global| CS[Community Search]
CLASS --> |drift| BOTH[Both + Synthesis]
HS --> LLM[Ollama]
CS --> LLM
BOTH --> LLM
end
DB --> HS
DB --> CS
style MD stroke:#22c55e,stroke-width:2px
style DB stroke:#3b82f6,stroke-width:2px
style LLM stroke:#a855f7,stroke-width:2px
مايكروسوفت's GraphRAG يستخدم تخزيناً منفصلاً للميكتورات M SK1LanceDB), الكائنات ♫(ParquetMSC4 والعلاقات |(المزيد Parquet | ). | DuckDB يبسط هذا |
.duckdb ملف لكل شيءDuckDB ليس قاعدة بيانات رسمية - وأن ' هو النقطة هذا ليس ' "Neo" 4 "J" . الترانزيون سطحي "M SK3" "SQL" "MSSK4" مبني "MSC5" و متعمد "Mスク6" هذه القيود تجعل النظام قابل للحل والتكلفة المنخفضة
يستخدم الرسم البياني إنضمام الجداول للمستوطن - يمكننا أن نسأل " أي قطعة تشير إلى كيان XM SK2 مباشرة:
erDiagram
documents ||--o{ chunks : contains
chunks ||--o{ entity_mentions : has
chunks ||--o{ relationship_mentions : has
entities ||--o{ entity_mentions : mentioned_in
entities ||--o{ relationships : source
entities ||--o{ relationships : target
relationships ||--o{ relationship_mentions : mentioned_in
communities ||--o{ community_members : contains
entities ||--o{ community_members : belongs_to
chunks {
varchar id PK
varchar document_id FK
text text
float[] embedding
}
entities {
varchar id PK
varchar name
varchar type
int mention_count
}
entity_mentions {
varchar entity_id FK
varchar chunk_id FK
}
قرار التصميم الرئيسي: لا VARCHAR[] من provenance. Join tables (entity_mentions, relationship_mentions) تمكن الاستبيانات الفعالة مثل " تحصل على جميع الأجزاء التي تشير إلى "دوكر"
مؤشر DuckDB's HNSW ينشط فقط مع array_cosine_distance + ORDER BY + LIMIT:
// GraphRagDb.cs - SearchChunksAsync
cmd.CommandText = $"""
SELECT id, document_id, text, chunk_index,
array_cosine_distance(embedding, $1::FLOAT[{_dim}]) as distance
FROM chunks
WHERE embedding IS NOT NULL
ORDER BY distance
LIMIT $2
""";
// Convert distance to similarity: 1.0f - distance
إستخدام array_cosine_similarity لن يستخدم المؤشر - لقد فاز ’ لم ي trigger HNSW index. On nonM SK3trivial corporaMSC4 this turns a ♫~5ms indexed query into a full table scan ♫
هذا هو المكان الذي نبتعد عنه من مقاربة مايكروسوفت LLM-per-ممرات استخراج القمامة تستخدم في مرجع مايكروسوفت' أنابيب GraphRAG استخراج إحصائي مبني على IDF-. الهدف هو مستقرة, كتلة- إشارات نسبية التي لا تحتاج لـ LLM لإنتاج ــ . . هذا يتقاسم مع بعض ال recall من أجل التفاضل والتكامل ــ, . قابلة للتحقق ـــ , . وتكلفة متوقعة . . - . خيار مصمم للمؤسسات التقنية .
flowchart TB
subgraph "Phase 1: Signal Collection"
TEXT[All Chunks] --> IDF[Compute IDF Scores]
TEXT --> STRUCT[Structural Signals]
STRUCT --> HEAD[Headings]
STRUCT --> CODE[Inline Code]
STRUCT --> LINKS[Links]
IDF --> RARE[High-IDF = Rare Terms]
RARE --> CAND[Candidates]
HEAD --> CAND
CODE --> CAND
LINKS --> |explicit rels| LINKREL[Link Relationships]
end
subgraph "Phase 2: Dedup"
CAND --> EMBED[BERT Embeddings]
EMBED --> SIM[Similarity > 0.85]
SIM --> MERGE[Merge Duplicates]
end
subgraph "Phase 3: Classify"
MERGE --> LLM{LLM Available?}
LLM --> |yes| BATCH[Single Batch Call]
LLM --> |no| HEUR[Heuristic Types]
end
style IDF stroke:#f59e0b,stroke-width:2px
style BATCH stroke:#a855f7,stroke-width:2px
المقاربة البسيطة هي برمجة صلبة HashSet<string> KnownTech = { "Docker", "Kubernetes", ... }. هذا يقطع ل:
IDF (تردد العكس للوثائق) يحل هذا إحصائياً
$$\textM SK1IDF}(tMSC3 = | | \log |\frac |
أين:
IDF عالي = كلمة نادرة = محتمل أن كيان . "Docker" يظهر في 5 من 100 الجسيمات لديه IDF أعلى من "the \ " يظهر فى \100 من الـ 100.
لمعرفة المزيد عن TF-IDF و BM25, انظروا إلى بريدي على البحث الهجين مع BM25.
تخبرنا هيكلة العلامات التجارية ما هو مهم
## Docker Setup) → كيان`docker-compose`) → كيان[Docker](https://docker.com)) → كيان + علاقة// EntityExtractor.cs - structural signal extraction
private void ExtractStructuralEntities(string chunk, string chunkId)
{
// Headings: ## Docker Compose Setup → "Docker Compose Setup"
foreach (Match m in Regex.Matches(chunk, @"^#{1,3}\s+(.+)$", RegexOptions.Multiline))
{
var heading = m.Groups[1].Value.Trim();
AddCandidate(heading, chunkId, weight: 2.0); // Higher weight
}
// Inline code: `docker-compose` → "docker-compose"
foreach (Match m in Regex.Matches(chunk, @"`([^`]+)`"))
{
AddCandidate(m.Groups[1].Value, chunkId, weight: 1.5);
}
}
الروابط المخصصة للتسويق بوضوح العلاقات التي لا تحتاج إلى استنتاج LLM
// EntityExtractor.cs - ExtractLinks
foreach (Match m in Regex.Matches(chunk, @"\[([^\]]+)\]\((/blog/[^)]+)\)"))
{
var linkText = m.Groups[1].Value; // "semantic search"
var slug = m.Groups[2].Value; // "/blog/semantic-search-with-qdrant"
yield return new Relationship(linkText, $"blog:{slug}", "references", chunkId);
}
أسماء الوحدات مثل "Docker Compose", "dockerM SK3composeMSC4 و "DokerCompose" ينبغي أن تدمجMST7 نحن نستخدم مداخلات بيرت لإكتشاف التشابه الدلالي:
// EntityExtractor.cs - DeduplicateAsync
var embeddings = await _embedder.EmbedBatchAsync(candidates.Select(c => c.Name), ct);
for (int i = 0; i < candidates.Count; i++)
{
for (int j = i + 1; j < candidates.Count; j++)
{
var similarity = CosineSimilarity(embeddings[i], embeddings[j]);
if (similarity > 0.85)
{
// Merge into canonical entity (keep higher mention count)
canonical.MentionCount += duplicate.MentionCount;
canonical.ChunkIds.UnionWith(duplicate.ChunkIds);
}
}
}
هذه الخطوة هي O(n²) ضمن مجموعة من المرشحين المحدودةM SK2 لكن أعداد المرشحون محدودة من خلال التصفية IDF و الإشارات الهيكلية - ليس حجم الجسم . لمعرفة المزيد عن تداخلات BERTMSC5 consulte البحث الدلالي مع ONNX و BERT.
ال CLI يدعم ثلاثة طرق استخراج من خلال --extraction-mode:
dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode heuristic
يستخدم IDF + إشارات هيكلية للكشف عن الكائنات, مع التصنيف الخيالي لحزمة LLMM SK2 صفر لكل مكالمات - - فقط ~1 إتصال لكل 50 كيانات لتصنيف الأنواع.
dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode hybrid
أفضل من كلا العالمين:
flowchart LR
subgraph "Per Document"
CHUNKS[Document Chunks] --> HEUR[Heuristic Extraction]
HEUR --> CAND[30 Candidates]
CAND --> LLM[Single LLM Call]
LLM --> ENT[Validated Entities]
LLM --> REL[Semantic Relationships]
end
style HEUR stroke:#22c55e,stroke-width:2px
style LLM stroke:#a855f7,stroke-width:2px
في 5 الوثائق مع 62 قطع ,, režim الهجين يجعل 5 مكالمات LLM (vs 124 لنظام LLM الكامل). تحصل على
dotnet run --project Mostlylucid.GraphRag -- index ./Markdown --extraction-mode llm
النهج الكامل لMicrosoft GraphRAG: 2 مكالمات LLM لكل قطعة (استخراج الكائنات +استخلاص العلاقات). أغلى الثمنM SK3 لكن أعلى جودة للنص الغير منظمMSC4
| الطريقة | إتصالات الـ LLM | الأفضل ل |
|---|---|---|
| الهيوريستيكس MSC0 MSC1 لكل SMC2 كيان | إحصاء سريعMSc4 جيدMScs5 تخفيض منظم msc6 | |
| الهجين | 1 لكل سند | توازن الغطاء والكفاءة SSK3 |
| LLM | 2 لكل قطعة | نص غير منظم, جودة عالية |
للوثائق التقنية, تبدأ مع المزيج mode. إنه يعطيك علاقات سيمانسية دون مقابلة تأملي للسرعة النقية, أو الـ Llm للنص الروائي.
البحث الهجين يجمع مقاربتين متكاملتين:
كثافة (BERT): يفهم المعنى. "وعاء الدوكرM SK2 تطابق "containerizationMSC4 المعزوفة (BM25): يتطابق المصطلحات الدقيقة. "HNSWM SK2 تتطابق فقط "HN SWMSC4
flowchart LR
Q[Query] --> BERT[BERT Embedding]
Q --> BM25[BM25 Tokenize]
BERT --> DENSE[Dense Search<br/>HNSW Index]
BM25 --> SPARSE[Sparse Search<br/>TF-IDF Scoring]
DENSE --> RRF[RRF Fusion]
SPARSE --> RRF
RRF --> TOP[Top K Results]
TOP --> ENR[Enrich with<br/>Entities + Rels]
style RRF stroke:#f59e0b,stroke-width:2px
BM25 (أفضل تطابق 25) يسجل الدرجات للأدوات اعتماداً على فرط مصطلح البحثM SK3 المعادلةMSC4
$$\textM SK1score}(D+,Q+) = \sum_ \textMSC4IDFMNK5qMRK6i+) ==\cdot \fracMMK10fMEK11q=i&, DMST14 \cdo MSSK16kMsek17 ♪+ |1)}{f~(q+ |I&, D) ♫+ k | _1 ,\ cdot \ (1 . .- b . + b
المعتقدات الرئيسية:
للتطبيق الكامل بـ BM25ـ , , см. البحث الهجين والمؤشر.
RRF يدمج التصنيفات من مختلف أنظمة البحث. كل مكان في المرتبة يحصل على النتيجة:
$$\textM SK1RRF}(dMSC3 = \summa_{r \in RM SK2 \frac{1}{k M+ rMSC6dMST7
حيث \(k\) (معتاداً |60) prevents overweighting the top result كلاهما تحسن التصنيفات
// SearchService.cs - RRF fusion
const int k = 60;
foreach (var (chunk, rank) in denseResults.Select((c, i) => (c, i)))
scores[chunk.Id] = 1.0 / (k + rank + 1);
foreach (var (chunk, rank) in sparseResults.Select((c, i) => (c, i)))
{
var rrfScore = 1.0 / (k + rank + 1);
if (scores.TryGetValue(chunk.Id, out var existing))
scores[chunk.Id] = existing + rrfScore; // Boost for appearing in both!
else
scores[chunk.Id] = rrfScore;
}
مثال: سند يصنف #1 في الكثافة و #3 في الضباب
flowchart TB
Q[Query] --> CLASS[Classify Query]
CLASS --> |"How do I use X?"| LOCAL[Local Search]
CLASS --> |"What are the themes?"| GLOBAL[Global Search]
CLASS --> |"How does X relate to Y?"| DRIFT[DRIFT Search]
LOCAL --> HS[Hybrid Search] --> CTX1[Chunk + Entity Context]
GLOBAL --> CS[Community Summaries] --> MAP[Map-Reduce]
DRIFT --> BOTH[Local + Communities] --> SYN[Synthesize]
CTX1 --> LLM[LLM Answer]
MAP --> LLM
SYN --> LLM
style LOCAL stroke:#22c55e,stroke-width:2px
style GLOBAL stroke:#3b82f6,stroke-width:2px
style DRIFT stroke:#a855f7,stroke-width:2px
// QueryEngine.cs
private static QueryMode ClassifyQuery(string query)
{
var q = query.ToLowerInvariant();
if (q.Contains("main theme") || q.Contains("summarize") || q.Contains("overview"))
return QueryMode.Global;
if (q.Contains("relate") || q.Contains("connect") || q.Contains("compare"))
return QueryMode.Drift;
return QueryMode.Local;
}
هذا التصنيف بسيط بشكل قصدي - وسهل استبداله مع نموذج لهدف صغير لاحقاً . إذا لم تتطابق كيانات الـ , فإن النظام يتحلل بوضوح إلى إستخراج هجين نقي | .
# Heuristic mode (default) - fast, no per-chunk LLM
dotnet run --project Mostlylucid.GraphRag -- index ./test-markdown
# LLM mode - Microsoft-style classification
dotnet run --project Mostlylucid.GraphRag -- index ./test-markdown --extraction-mode llm
GraphRAG Indexer
Source: test-markdown
Database: graphrag.duckdb
Model: llama3.2:3b
Extraction: Heuristic (IDF + signals)
Initializing...
Indexing docker-development-deep-dive.md: 0%
Indexing docker-swarm-cluster-guide.md: 40%
Indexing dockercomposedevdeps.md: 80%
Indexing complete: 100%
Classifying entities...: 0%
Extracted 168 entities, 315 rels (4 LLM calls): 100%
Found 10 communities: 100%
Summarizing c_0_2 (12 entities): 20%
Summarizing c_0_8 (4 entities): 80%
────────────────── Indexing Complete ───────────────────
┌───────────────┬───────┐
│ Metric │ Count │
├───────────────┼───────┤
│ Documents │ 5 │
│ Chunks │ 62 │
│ Entities │ 168 │
│ Relationships │ 312 │
│ Communities │ 10 │
└───────────────┴───────┘
dotnet run --project Mostlylucid.GraphRag -- query "How do I use Docker Compose?"
──────────────────── Local Search ────────────────────
Query: How do I use Docker Compose?
╭─Answer────────────────────────────────────────────────╮
│ To run the services defined in the │
│ devdeps-docker-compose.yml file, you need to run the │
│ following command in the same directory as the file: │
│ │
│ docker compose -f .\devdeps-docker-compose.yml up -d │
│ │
│ This command will start the containers in detached │
│ mode. │
╰───────────────────────────────────────────────────────╯
Related Entities: Docker, container, services, image
Sources: 5 chunks (top score: 0.016)
dotnet run --project Mostlylucid.GraphRag -- stats
─────────────── GraphRAG Database Stats ────────────────
┌───────────────┬───────┐
│ Metric │ Count │
├───────────────┼───────┤
│ Documents │ 5 │
│ Chunks │ 62 │
│ Entities │ 168 │
│ Relationships │ 312 │
│ Communities │ 10 │
└───────────────┴───────┘
Database size: 7.76 MB
من أجل 100 المدونات (~500 المقطوعات, ~100 الوثائقM SK4
| عمليات | MSFT GraphRAG | ||||||||
|---|---|---|---|---|---|---|---|---|---|
| إستخراج الكائنات | 1,000 الإتصالات | 0 | |||||||
| تحسن الوثائق | - | - ♪ | 100 | إتصالات | |||||
| التصنيف | بما فيه | ~4 بستة S | - | ~4 | بستة | ||||
| إحصائيات المجتمع | ~20 | ♫ | ~20 ♫ | ||||||
| كل مكالمات LLM | ~1,020 | ~24 | ~120 | ~1,024 | |||||
| جودة العلاقات | الدلالية | المصاحبة - الحدوث | المفهوم الدلالي | المفاهيم الدلالتي | |||||
| التكلفة (gpt-4oM SK2mini ) | ~$5-10 | ~$0.15 | ~$0.75 | ~$5-10 | |||||
| التكلفة (Ollama) | N/A |
المزيج هو النقطة الحلوة للكثير من المحتويات التقنية : تحصل على العلاقات الدلالية ( ليس فقط كـ . .
طلب دقيق-of-estimate ofmagnitudeM SK2التكلفة الدقيقة تعتمد على حجم القطعة والشكل الفوري
| وجهة نظر | هدرية MSSK2 هجين | LLM | MSFT GraphRAG | |||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| الكشف عن الكائنات | الهيكل IDF | + | الهيكل | IDF | ||||||||||||
| العلاقات | ثنائي الـ- المصادفة | LLM | - | غير مصادمة | ثنايي الـ - | المصادمة | ||||||||||
| إتصالات الـ LLM | ||||||||||||||||
| جودة العلاقات | منخفضة | عالية | من basse | عالية | ||||||||||||
| يعمل خارج نطاق الإنترنت | نعم | أجل | МSK3 | أولاما | ماسك4 | الـ | نعم | الماسك6 | اولاما ٬ ماسك7 | ماسك8 | API مطلوب | |||||
| الأفضل لM SK1 السرعة-critical | المُوصيل | موصل قديم | نص غير منظم |
من الناحية النظرية , هذا هو نفس خط الأنابيب DocSummarizer: بناء الهيكل أولا, ثم ترك LLM يشرحها
أين ينكسر هذا؟ النص الخيالي أو القصصي بدون علامة هيكلية. علاقات غير واضحة بدون إشارة لفظية . أسماء كيانات غامضة جداً التي تتطلب معرفة عالمية لتفكيك التفاوت. في هذه الحالاتM SK3 استخدام نظام LLM أو مايكروسوفت
التنفيذ هو الحد الأدنى - ~2,000 خطوط على طول هذه الملفات:
Mostlylucid.GraphRag/
├── Storage/GraphRagDb.cs # DuckDB with HNSW + provenance
├── Services/EmbeddingService.cs # ONNX BERT wrapper
├── Services/OllamaClient.cs # LLM client
├── Extraction/
│ ├── IEntityExtractor.cs # Extractor interface
│ ├── EntityExtractor.cs # Heuristic mode
│ ├── HybridEntityExtractor.cs # Hybrid mode (recommended)
│ └── LlmEntityExtractor.cs # Full LLM mode
├── Search/SearchService.cs # BM25 + BERT hybrid
├── Graph/CommunityDetector.cs # Leiden + summarization
├── Query/QueryEngine.cs # Local/Global/DRIFT
├── Indexing/MarkdownIndexer.cs # Chunking
├── GraphRagPipeline.cs # Orchestration
├── Models.cs # Shared types + ExtractionMode enum
└── Program.cs # CLI
المصدر: Mostlylucid.GraphRag/
© 2026 Scott Galloway — Unlicense — All content and source code on this site is free to use, copy, modify, and sell.