GraphRAG: Pourquoi la recherche par vecteur se détériore au niveau du corpus
Votre système RAG est excellent à "needle" questions : récupérer quelques morceaux pertinents et synthétiser une réponseM SK3 Il se heurte à deux types de demandes courantesMSC4
- Sensibilisation: "Qu'est-ce que les principaux thèmes de ce corpus?
- Connexion: "Comment X se rapporte-t-il à Y dans les différents documents?
Ces questions ne sont pas résolues par un seul bloc de réponses. Couplage + regroupement + liaison.
Pourquoi la recherche par vecteur ne fonctionne pas ici:
- Il classe les morceaux de façon indépendante par analogie à la demande
- La similitude optimise la pertinence, non couverture mondiale
- Embeddings capture "qu'est-ce qui est semblable à ce qu'on entendM SK1non "quelles sont reliées à ce que l'on comprend"
Vous pouvez brute-forcer cela avec l’invitation et le post-procédure, mais vous finirez par reconstruire une solution en forme de graphe.
Le point de vue clé: GraphRAG modifie l'unité de recherche. Pour les questions sur le corpus que vous ne voulez pas'dont vous ne souhaitez pas "topM SK3K fragments similairesMSC4 que vous voulez Communautés conceptuelles reliées ( et leurs résumésM SK1 de sorte que le modèle voit la structure, non les fragments .
GraphRAG provient de Microsoft Research's Documentation et est disponible en tant que mise en œuvre de source open-. Il maintient la recherche vectorielle pour des questions spécifiques , mais il ajoute un graphique de connaissance et des résumés communautaires pour le corpus
Navigation de la série GraphRAG:
- Partie 1: GraphRAG Fundamentals (le présent articleM SK1
- Partie 2: Graphique minimale viable (Optionnelle par -Calls LLM de Chunk)
Quand ne pas utiliser GraphRAG
Avant de plonger dans l’eau, laissez-moi savoir quand c’est une surpêche.
- Les petits ensembles de documents (aux termes de ~50 documents): utiliser simplement la recherche par vecteur
- Seules les questions "comment puis-je répondre à la question ?: GraphRAG a remporté
- Contenu uniforme (aucune variété d'entitésM SK1pas de structure graphique à exploiter
- Coût-contrôlé: l'indexation nécessite de nombreuses appels LLM
Si vos utilisateurs ne posent que des questions précises, rester avec recherche sémantique. GraphRAG brille lorsque les utilisateurs ont besoin du le grand tableau, et que ' est un auditoire plus restreint que les fournisseurs le suggèrent
Introduction
Navigation de série: Il s'agit d'une partie 6 de la série RAGM SK1
- Partie 1: Origines et fondements - Historique, motivationM SK2 et concepts de base
- Partie 2: Architecture et intérieurs - plongée technique profonde
- Partie 3: RAG dans la pratique - Établissement de systèmes réels
- Partie 4a: ONNX & Mise en œuvre de la garantie - CPU-cherche sémantique conviviale
- Partie 4b: Recherche sémantique en action - Typeahead , recherche hybride, et UI
- Pièce 5: Recherche hybride & AutoM SK2Indexage - Intégration de la production
- Partie 6: GraphRAG (le présent articleM SK1 - Graphiques de connaissances pour le corpus-compréhension du niveau
Tout au long de cette série, nous avons construit des systèmes RAG de plus en plus sophistiqués. fractions similaires, non concepts connexes. Pour corpus-niveau Questions (themes couvrant de nombreux documents) vous avez besoin d’une structureM SK2
Le chemin recommandé: Si vous avez déjà Qdrant-basé sur la recherche locale qui fonctionne M SK1comme nous le faisons ), prototype avec Python sidecar pour valider les valeurs, conserver des vecteurs de recherche localeMNK4 et ajouter un graphique léger pour la recherche mondialeMMK5questions d'DRIFTMZK6 Allez seulement MNK7 GraphRAG completMKK8 une fois que vos utilisateurs prouvés ont posé ces questionsMGK9
Le problème avec le RAG Pure Vector
Permettez-moi de vous montrer ce que je veux dire par un exemple concret.
Ce que fait bien le Vektor RAG
Question: "Comment puis-je utiliser l'HTMX avec Alpine?
Processus RAG vecteur:
- Insérer la question:
[0.234, -0.891, 0.567, ...] - Trouver des morceaux similaires dans Qdrant
- Retour en haut-K matches sur HTMX et AlpineM SK1js
- LLM synthétise la réponse de ces tronçons
Cela fonctionne parce que la question et le contenu pertinent sont caractéristiques sémantiques similaires. Les embeddings captent cette similitudeM SK1
// This is what our current SemanticSearchService does
var embedding = await _embeddingService.GetEmbeddingAsync(query);
var results = await _qdrantService.SearchAsync(
collectionName: "blog_posts",
queryVector: embedding,
limit: 10
);
// Returns chunks about HTMX, Alpine.js, frontend patterns
Où le Vektor RAG se bat
Question: " Quelles sont les principales technologies dont je parle et comment elles se rapportent-elles?
Quel vecteur RAG retourne:
Result 1: "HTMX makes it easy to add AJAX to your pages..."
Result 2: "Docker Compose orchestrates multiple containers..."
Result 3: "PostgreSQL's full-text search is surprisingly capable..."
Result 4: "Alpine.js provides reactive state management..."
Il mentionne le Docker, PostgreSQL, HTMXM SK2 ONNX ... mais ne les regroupe pas ou n’explique pas comment ils se connectentMSC5 Vous obtiendrez des fragmentsMST6 non une vue d’ensembleMSS7
Le problème: Cette question exige agrégation et compréhension des relations sur l’ensemble du corps. Vous devez
- Identifier toutes les technologies mentionnées
- Comprendre ce qui est utilisé ensemble
- Groupez-les en thèmes cohérents
La similitude des vecteurs seuls ne vous donne pas ce qui suit :
Inscrire GraphRAG
GraphRAG est la solution à ce problème de Microsoft Research' Papier GraphRAG a identifié les deux types de demandes que le RAG de base gère mal (sensationnel et d’une part, le fait de ne pas se conformer à la législation communautaire et, d’autre part) et a construit un système spécifique pour les traiter
Au lieu de simplement intégrer des tronçons, GraphRAG construit un Graphique du savoir qui saisit les entités et leurs relations, puis les regroupe en communautés avec des résumés.
Comment fonctionne GraphRAG
Pipeline à un coup d’œil:
- Indexage: Unités → entitésM SK1relations → graphe → communautés S→ résumés
- Question: Locale = tronçons + quartier du graphique SSK2 Sommaires communautaires mondiaux = sommaires de la collectivité S| DRIFT
GraphRAG ajoute plusieurs composants au pipeline RAG, groupés en trois catégoriesM SK1
- Extraction (entités + relations
- Établissement de graphiques (entreposage des graphes de connaissancesM SK1
- Résumé (détection communautaire + hiérarchie
flowchart TB
subgraph "Traditional RAG (What We Have)"
A[Documents] --> B[Chunks]
B --> C[Embeddings]
C --> D[Vector Store]
end
subgraph "GraphRAG Additions"
B --> E[Entity Extraction]
E --> F[Relationship Extraction]
F --> G[Knowledge Graph]
G --> H[Community Detection]
H --> I[Community Summaries]
end
subgraph "Query Time"
J[User Query] --> K{Query Type?}
K -->|Specific| L[Local Search]
K -->|Global| M[Global Search]
K -->|Hybrid| N[DRIFT Search]
D --> L
G --> L
I --> M
G --> N
I --> N
end
style E stroke:#f9f,stroke-width:2px
style H stroke:#bbf,stroke-width:2px
style I stroke:#9f9,stroke-width:2px
Étape 1: Extraction des entités
Un LLM lit chaque tronçon et extrait les entités (les choses dont il est question):
Chunk: "Docker Compose makes it easy to define multi-container applications.
I use it with PostgreSQL for my blog's database layer."
Extracted Entities:
- Docker Compose (technology)
- PostgreSQL (database)
- blog (project)
- database layer (concept)
Étape 2: Extraction des relations
Le même LLM identifie la relation entre les entités:
Relationships:
- Docker Compose --[used_with]--> PostgreSQL
- blog --[has_component]--> database layer
- PostgreSQL --[implements]--> database layer
Étape 3: Construction du Graphique des connaissances
Toutes les entités et relations forment un graphique:
graph LR
subgraph "Frontend Cluster"
HTMX[HTMX]
Alpine[Alpine.js]
Tailwind[Tailwind CSS]
end
subgraph "Infrastructure Cluster"
Docker[Docker]
Compose[Docker Compose]
Postgres[PostgreSQL]
Qdrant[Qdrant]
end
subgraph "AI/ML Cluster"
ONNX[ONNX Runtime]
Embeddings[Embeddings]
RAG[RAG]
end
HTMX -->|used_with| Alpine
HTMX -->|styled_by| Tailwind
Alpine -->|styled_by| Tailwind
Docker -->|orchestrated_by| Compose
Compose -->|runs| Postgres
Compose -->|runs| Qdrant
ONNX -->|generates| Embeddings
Embeddings -->|stored_in| Qdrant
RAG -->|uses| Embeddings
RAG -->|uses| Qdrant
style HTMX stroke:#f9f
style Docker stroke:#bbf
style RAG stroke:#9f9
Étape 4: Détection communautaire ( Algorithme lié de l'algorithme
L'article 5 de la Loi sur l'immigration et le statut des réfugiés Algorithme de Leiden les nodes étroitement reliés dans des collectivités. Cela est important parce qu’il vous donne Établissement stable Les communautés deviennent vos unités de recherche pour les demandes mondiales.
- Communauté 1: "Frontend Stack"
- Communauté 2: "Container Infrastructure" | | (DockerMSC4 ComposeM SK5 PostgreSQLMST6 QdrantMSL7
- Communauté 3: " Pipeline RAG" ≥(ONNXM SK4 EmbeddingsMska5 QdrantM Ska6 RAG~Mska7
Notez comment Qdrant apparaît dans deux communautés :
Étape 5: Résumés communautaires
Un LLM produit des résumés pour chaque communauté à chaque niveau hiérarchique:
Community 1 Summary (Frontend Stack):
"The frontend approach combines HTMX for server-driven interactivity
with Alpine.js for client-side state management, styled using Tailwind CSS.
This stack prioritizes HTML-first development with minimal JavaScript,
focusing on progressive enhancement over SPA complexity."
Community 2 Summary (Container Infrastructure):
"The blog runs on Docker Compose, orchestrating PostgreSQL for persistent
storage, Qdrant for vector search, and the ASP.NET Core application.
This containerized architecture enables consistent local development
and production deployment."
Modes de demande
GraphRAG offre trois modes de demande, chacun optimisé pour différents types de questions:
Recherche mondiale
Le meilleur pour: "Qu'est-ce que les principaux thèmes?
Utilise les sommaires communautaires (pas des chunks individuelsM SK1 pour répondre aux questions de sensibilisation :
Query: "What technologies does this blog cover most?"
Process:
1. Retrieve all community summaries
2. Map: Ask LLM to extract technology themes from each summary
3. Reduce: Combine partial answers into final response
Response:
"The writing centres on three technology clusters:
1. **Frontend Development** - HTMX, Alpine.js, Tailwind CSS for minimal-JS web UIs
2. **AI/ML Infrastructure** - RAG pipelines, ONNX embeddings, vector search with Qdrant
3. **DevOps/Containerization** - Docker, PostgreSQL, ASP.NET Core deployment"
Recherche locale
Le meilleur pour: "Comment configurer XM SK1 "Qu'est-ce que Y?"
Combine l’entité-la traverse graphique axée sur la recherche vectorielle traditionnelle:
Query: "How do I use Qdrant with ONNX embeddings?"
Process:
1. Identify entities in query: Qdrant, ONNX, embeddings
2. Retrieve graph neighborhood around those entities
3. Also retrieve vector-similar chunks
4. Combine into rich context for LLM
Response includes:
- Direct relationships (ONNX generates embeddings stored in Qdrant)
- Related entities (all-MiniLM-L6-v2 model, cosine similarity)
- Specific code examples from vector-retrieved chunks
Recherche DRIFT
Le meilleur pour: "Comment X se rapporte-t-il à Y?
Recherche DRIFT (Dynamic Reasoning and Inference with Flexible Traversal), tel que décrit dans les documents GraphRAG, combine la recherche locale avec le contexte communautaire . Il' continue d’utiliser le raisonnement de LLM au-dessus du contexte structuré récupéré.
Query: "How do the frontend and backend technologies connect?"
Process:
1. Start with entities: HTMX, ASP.NET Core
2. Traverse graph to find connection paths
3. Include community summaries for context
4. Generate answer showing the full picture
Response:
"HTMX makes requests to ASP.NET Core endpoints, which query PostgreSQL
and Qdrant. The connection flows through the API layer, where endpoints
return HTML fragments that HTMX swaps into the DOM. Alpine.js handles
client-side state for interactive components like search typeahead."
Comparaison de GraphRAG à notre système actuel
Let's map GraphRAG concepts to what we already have in Mostlylucid.SemanticSearch:
| Composante | Système courant | Équivalence de GraphRAG M |
|---|---|---|
| Embeddings | ONNX (tousM SK2MiniLM-LMST4vMSC5 | Le même MSC7ou OpenAIMSC8 |
| Entrepôt de vecteurs | Qdrant | |
| Extraction d'entités | Aucune | |
| Graphique du savoir | Aucune | |
| Détection communautaire Algorithme de Leiden | ||
| Demande: spécifique | SemanticSearchService.SearchAsync() Recherche locale |
|
| Demande: Global | Non supporté | Recherche mondiale |
Notre gestion de la mise en œuvre actuelle Recherche locale bien. GraphRAG ajouterait Recherche mondiale et Recherche DRIFT capacités.
// What we have today (Local Search equivalent)
public async Task<List<SearchResult>> SearchAsync(string query, int limit = 10)
{
var embedding = await _embeddingService.GetEmbeddingAsync(query);
return await _qdrantService.SearchAsync("blog_posts", embedding, limit);
}
// What GraphRAG would add
public async Task<string> GlobalSearchAsync(string query)
{
// 1. Retrieve community summaries (not chunks)
var summaries = await _graphService.GetCommunitySummariesAsync();
// 2. Map: Extract relevant themes from each summary
var partialAnswers = await Task.WhenAll(
summaries.Select(s => _llm.ExtractThemesAsync(query, s))
);
// 3. Reduce: Combine into final answer
return await _llm.SynthesizeAsync(query, partialAnswers);
}
Approches de mise en œuvre
Il y a trois façons d’ajouter GraphRAG à un système existant.
Option 1: Python Sidecar (Recommandé pour l'exploration)
Faire fonctionner Microsoft's GraphRAG en tant que service distinct
# docker-compose.graphrag.yml
services:
graphrag:
build:
context: ./graphrag
volumes:
- ./data/input:/app/input
- ./data/output:/app/output
environment:
- OPENAI_API_KEY=${OPENAI_API_KEY}
graphrag-api:
build:
context: ./graphrag-api
ports:
- "8001:8000"
depends_on:
- graphrag
// GraphRagClient.cs - Call from ASP.NET Core
public class GraphRagClient
{
private readonly HttpClient _http;
public GraphRagClient(HttpClient http)
{
_http = http;
_http.BaseAddress = new Uri("http://graphrag-api:8000");
}
public async Task<string> GlobalSearchAsync(string query)
{
var response = await _http.PostAsJsonAsync("/query/global", new { query });
var result = await response.Content.ReadFromJsonAsync<GraphRagResponse>();
return result.Answer;
}
public async Task<string> LocalSearchAsync(string query)
{
var response = await _http.PostAsJsonAsync("/query/local", new { query });
var result = await response.Content.ReadFromJsonAsync<GraphRagResponse>();
return result.Answer;
}
}
Pros: Utilisez Microsoft'la bataille de -la mise en oeuvre expérimentée, rapidement au prototype Cons: dépendance de Python, Coûts liés à l'indexation par LLM, communication croisée
Option 2: .NET Native (Path de production)
Élaborer les composants clés de C#. L’extraction fondée sur le BERTM SK1 et les modèles Ollama provenant des DocSummarizer Travailler de la même façon ici.
Extraction d'entités
Demander à un LLM d'identifier les choses (entitésM SK1 dans chaque tronçon - entités structurées plutôt que libres
public async Task<List<Entity>> ExtractEntitiesAsync(string chunk)
{
var prompt = $"""
Extract entities from this text. Return JSON array.
Types: technology, concept, project, person, organization
Text: {chunk}
Format: [{{"name": "Docker", "type": "technology"}}]
""";
var response = await _ollama.GenerateAsync(prompt);
return JsonSerializer.Deserialize<List<Entity>>(response);
}
Exigences de production: LLM JSON sortie de l’intention interruption. Il ne s'agit pas d'un affaiblissement facultatif. Vous avez besoin d'une de ces
- Schema-génération restreinte (OllamaM SK1s
format: json, OpenAI's fonction d'appel de ) - Essayer de réparer les boucles-avec- (détecter un JSON malformé, demander à LLM de le corrigerM SK2
- Extraction en arrière-plan (patterns regex pour les types d'entités communesM SK1
Les LLM sont probabilistes; votre pipeline d'extraction ne doit pas être.
Extraction des relations
Une fois que vous avez des entités, demandez au LLM comment elles se connectent:
public async Task<List<Relationship>> ExtractRelationshipsAsync(
string chunk, List<Entity> entities)
{
var names = string.Join(", ", entities.Select(e => e.Name));
var prompt = $"""
Given entities: {names}
Extract relationships. Return JSON array.
Text: {chunk}
Format: [{{"source": "Docker", "target": "PostgreSQL", "rel": "runs"}}]
""";
return JsonSerializer.Deserialize<List<Relationship>>(
await _ollama.GenerateAsync(prompt));
}
Entreposage de graphiques avec normalisation d'entités
La plus grande douleur pratique est Alisage de l'entité: "ASPM SK2NET Core",
public class KnowledgeGraph
{
private readonly Dictionary<string, Entity> _entities = new();
private readonly List<Relationship> _relationships = new();
public void AddEntity(Entity entity)
{
var key = Normalise(entity.Name); // "ASP.NET Core" → "aspnetcore"
_entities[key] = entity;
}
private string Normalise(string name) =>
name.ToLowerInvariant().Replace(".", "").Replace("-", "").Trim();
}
Pour une utilisation sérieuse, considérer l’incorporation - la déduplication d’entités fondée sur les entités M SK2 si deux noms d’entité ont des embeddings semblables , ils MSC4 sont probablement la même chose
Points de souffrance de production (GraphRAGM SK1la valeur dépend de la qualité du graphe):
- Synonyme/tableaux d'alias: conserver les noms canoniques et les alias connus
- Contrôle du schéma de relations: constraint permet aux prédicteurs d'empêcher les types de relations hallucinatoires
- Évaluation de la confiance + coupe: pas toutes les relations extraites sont tout aussi fiables
- Incremental re-indexing: lorsque les documents sont mis à jour, vous devez patcher le graphe , ne pas le reconstruire
Traversement du graphique
Trouver des entités apparentées est une largeur
public List<Entity> GetNeighbors(string entityName, int depth = 1)
{
var result = new HashSet<Entity>();
var queue = new Queue<(string Name, int Depth)>();
queue.Enqueue((Normalise(entityName), 0));
while (queue.Count > 0)
{
var (name, d) = queue.Dequeue();
if (d >= depth) continue;
// Find all entities connected to this one
var neighbours = _relationships
.Where(r => Normalise(r.Source) == name || Normalise(r.Target) == name)
.SelectMany(r => new[] { r.Source, r.Target });
foreach (var neighbour in neighbours)
if (_entities.TryGetValue(Normalise(neighbour), out var entity))
if (result.Add(entity))
queue.Enqueue((Normalise(neighbour), d + 1));
}
return result.ToList();
}
Détection communautaire
Il s'agit d'une ligne de base connectée-components, non pas Leiden complet. Leiden optimise pour la modularité (connexions internes densesM SK2connes externes épargnes ). Pour une mise en œuvre appropriéeMSC4 utiliser une bibliothèque de graphes ou portuer l’algorithmeMNK5
public List<Community> DetectCommunities(KnowledgeGraph graph)
{
// Connected components: group everything reachable together
var visited = new HashSet<string>();
var communities = new List<Community>();
foreach (var entity in graph.GetAllEntities())
{
if (visited.Contains(entity.Name)) continue;
// BFS to find all connected entities
var community = new Community();
var queue = new Queue<string>();
queue.Enqueue(entity.Name);
while (queue.Count > 0)
{
var name = queue.Dequeue();
if (!visited.Add(name)) continue;
community.Entities.Add(graph.GetEntity(name));
foreach (var neighbor in graph.GetNeighbors(name, depth: 1))
queue.Enqueue(neighbor.Name);
}
communities.Add(community);
}
return communities;
}
Résumé communautaire
Chaque collectivité reçoit un résumé décrivant son thème.
public async Task<string> SummarizeCommunityAsync(Community community)
{
var entities = string.Join("\n",
community.Entities.Select(e => $"- {e.Name}: {e.Description}"));
var prompt = $"""
Summarize what unites these concepts (2-3 sentences):
{entities}
""";
return await _ollama.GenerateAsync(prompt);
}
Option 3: Hybride (Pragmatic Middle GroundM SK2
C'est l'approche recommandée si vous avez déjà une recherche vectorielle en cours de travail. Gardez Qdrant pour la recherche locale, Ajouter une couche graphique léger pour Global
Classification de la demande
Premièrement, détecter quel type de question il s’agit:
// WARNING: Toy heuristic for illustration only.
// In production, use a classifier prompt or few-shot rules and log misroutes.
private QueryMode ClassifyQuery(string query)
{
var q = query.ToLowerInvariant();
if (q.Contains("main theme") || q.Contains("summarize") || q.Contains("what topics"))
return QueryMode.Global;
if (q.Contains("relate") || q.Contains("connect") || q.Contains("compare"))
return QueryMode.Drift;
return QueryMode.Local;
}
Recherche locale (Enhanced)
Utiliser la recherche vectorielle existante, optionnellement enrichie avec le contexte graphique:
private async Task<string> LocalSearchAsync(string query)
{
// Existing semantic search (what we have today)
var chunks = await _semanticSearch.SearchAsync(query, limit: 10);
// NEW: Enrich with related entities from graph
var entities = await _graphService.ExtractEntitiesFromQueryAsync(query);
var related = await _graphService.GetEntityContextAsync(entities);
return await _llm.GenerateAsync(query, FormatContext(chunks, related));
}
Recherche mondiale (Nouvelle capacité)
Carte-diminution par rapport aux résumés communautaires M SK1pas de recherche vectorale requise):
private async Task<string> GlobalSearchAsync(string query)
{
var summaries = await _graphService.GetAllCommunitySummariesAsync();
// Map: Extract relevant info from each community
var partials = await Task.WhenAll(
summaries.Select(s => _llm.ExtractRelevantInfoAsync(query, s)));
// Reduce: Combine into final answer
return await _llm.SynthesizeAsync(query, partials.Where(p => !string.IsNullOrEmpty(p)));
}
Recherche DRIFT (Questions liées à la connectivité)
Combiner les résultats locaux avec le contexte communautaire pour "comment X se rapporte-t-il à Y?
private async Task<string> DriftSearchAsync(string query)
{
var localResults = await LocalSearchAsync(query);
var entities = await _graphService.ExtractEntitiesFromQueryAsync(query);
var communities = await _graphService.GetCommunitiesForEntitiesAsync(entities);
var themes = string.Join("\n", communities.Select(c => c.Summary));
return await _llm.GenerateAsync(
$"Question: {query}\n\nDetails:\n{localResults}\n\nBroader themes:\n{themes}",
systemPrompt: "Synthesize the details with the thematic context.");
}
Considérations relatives aux coûts et au rendement
GraphRAG présente des retombées importantes par rapport à RAG de vecteur pur.
Coûts d'indexation
Entité/coûts d’extraction de la relation varient considérablement selon le modèleM SK1conception rapide , et taille du tronçon.En ordre approximatif un ou deux appels LLM par chunk plus un nombre moindre d’appels pour les résumés communautaires.
| Opération | RAG vectoriel | GraphRAG S |
|---|---|---|
| Intégration | 1 appel/chunk MSC3 Même MSC4 | |
| Entité/Extraction des relations | Aucune | |
| Résumé communautaire | Aucune |
Pour un corpus de 1,000 articles sur le blog avec 5 tronçons chacune |(5,000 tronchons totaux | ), vecteur | L'indexation seulement est essentiellement simplement l'incorporation des coûts | SMC5 | GraphRAG ajoute des milliers d'appels LLM pour extraction et sommisation |SMC6 | Le coût exact dépend fortement du choix de votre modèle et de l'efficacité rapide | MSMC7 | Utilisant les modèles locaux |MSMC8 | Ollama avec llama | SMMC9 | ou similaire | SSMC10 | élimine entièrement les coûts API | FSMC11 | qui est la méthode recommandée pour l'expérimentation |SMMC12
Coûts de la demande
| Type de la demande | RAG vecteur | GraphRAG local | GrafRAG global S | |||
|---|---|---|---|---|---|---|
| Recherche par vecteur | 1 appels | 1 | appels | |||
| Traversement graphique Questions | 0 | 2 | 3 | 4 | 5 | |
| Les appels LLM | 1 ≥ | ≤1-2 | N carte |
La recherche mondiale est plus coûteuse par demande, mais elle répond aux questions que la Recherche locale peut simplement répondre'tM SK2 Vous pouvez aussi cacher les réponses globales et les actualiser seulement lorsque le corpus changeMSC3
Modes de défaillance GraphRAG
GraphRAG n’est pas't magique. Veuillez vous assurerM SK2
- Les erreurs d'extraction: Les LLM manquent d’entités ou hallucinaient des relations
- Alisage des entités: "ASPM SK2NET Core" vs.
- Déplacement des graphiques: Lorsque les dossiers sont mis à jour,, le graphique peut devenir bloqué
- Les résumés communautaires ne sont plus valables: Sommaires donM SK1t auto-update quand les entités changent
La normalisation de l’entité est la plus grande douleur pratique.
- Noms canoniques + aliases
- Case-normalisation des plis et de la ponctuation
- Insertion optionnelle de la déduplication d'entités fondée sur le modèle -
Intégration avec notre recherche sur le blog
Voici comment GraphRAG pourrait améliorer le blog, la recherche sémantique existante de ' et :
Flux actuel
User types in search → SemanticSearchService → Qdrant → Results
Flux amélioré
Le classeur permet d’acheminer les demandes vers différentes stratégies de recherche. Demande globale flows - note qu’il ne touche jamais le store vecteurM SK1
sequenceDiagram
participant U as User
participant API as Search API
participant C as Query Classifier
participant G as Global Search
participant KG as Knowledge Graph
U->>API: "What topics does this blog cover?"
API->>C: Classify query
C-->>API: QueryMode.Global
API->>G: GlobalSearch(query)
G->>KG: GetCommunitySummaries()
KG-->>G: [Frontend, Infrastructure, AI/ML]
G->>G: MapReduce over summaries
G-->>API: Synthesized answer
API-->>U: "The blog covers three main areas..."
Comparez ce qui suit : Demande locale, qui combine la recherche par vecteur avec le contexte graphique pour obtenir des réponses plus riches
sequenceDiagram
participant U as User
participant API as Search API
participant C as Query Classifier
participant L as Local Search
participant Q as Qdrant
participant KG as Knowledge Graph
U->>API: "How do I use HTMX?"
API->>C: Classify query
C-->>API: QueryMode.Local
API->>L: LocalSearch(query)
L->>Q: Vector search
Q-->>L: Relevant chunks
L->>KG: GetEntityContext("HTMX")
KG-->>L: Related: Alpine.js, Tailwind, ASP.NET
L-->>API: Answer with rich context
API-->>U: "HTMX is used with Alpine.js for..."
La différence clé: les demandes globales regroupent les sommaires communautaires (corpus-thèmes de niveauM SK3 alors que les recherches locales reçoivent des chunks spécifiques enrichis par des relations d’entitésMSC4
Une solution plus simple: GraphRAG est encore très largement un outil de recherche - extraction d'entités, construction de graphiquesM SK2 et détection communautaire ajoutent une complexité significative et des coûts liés à la LLM Emplacements BERT + BMM SK1 matchage de mots clés Il fonctionne mieux. C'est ce que Sourcegraphe's Cody utilisations pour l’intelligence de code, et ce qui DocSummarizer utilisations pour la récapitulation des documents. Le modèle: les handles de recherche hybride relevance ; les handlers LLM assembly, non Décision. Vous obtiendrez 80% de l’avantage avec 20% de la complexité
Ébauche de la mise en œuvre
L'API est simple: classer la demande, route vers le gestionnaire appropriéM SK2
[HttpGet("api/search")]
public async Task<IActionResult> Search([FromQuery] string q, [FromQuery] string mode = "auto")
{
if (mode == "auto")
mode = ClassifyQuery(q);
// global/local return synthesised answers; default returns raw search results
return mode switch
{
"global" => Ok(await _graphRag.GlobalSearchAsync(q)), // synthesised answer
"local" => Ok(await SearchWithGraphContext(q)), // answer with citations
_ => Ok(await _semanticSearch.SearchAsync(q)) // raw ranked results
};
}
La recherche par vecteur et la recherche par graphe se complètent mutuellement. Utilisez les vecteurs pour " comment faire IM SK2 questions , les graphiques pour " quels sont les thèmesMSC5 questions
Conclusion
GraphRAG étend RAG de "recherche des tronçons similaires" à "comprendre la structure du savoirM SK3 Il n’est pas un remplacement pour la recherche par vecteurMSC5 il est une amélioration qui permet d’établir de nouveaux types de demandes
Ce que GraphRAG ajoute:
- Extraction d'entités et de relations
- Construction de graphiques des connaissances
- Détection communautaire et résumés hiérarchiques
- Recherche mondiale pour les questions de sens
- DRIFT Recherche de raisonnements connexes
Quand l'utiliser:
- Vous avez une collection de documents considérable
- Les utilisateurs se demandent : "Qu'est-ce que les thèmes?
- Votre contenu comporte des entités et des relations claires
- Vous voulez que les connexions de surface se fassent automatiquement
Voie de mise en œuvre:
- Premièrement, demanderM SK1 vous avez-vous réellement besoin de ce type d’appareil? ? BERT + BMMSC4 le renseignement hybride gère la plupart des cas utilisés
- Si oui, prototype avec Python sidecar pour valider la valeur
- Élaborer .NET native si les coûts sont élevés/affaire de la disponibilité
- Utiliser des LLM locaux (Ollama) pour contrôler les coûts d'indexation
Ressources
GraphRAG Official:
- Documentation GraphRAG - Dossiers officiels de Microsoft'
- GraphRAG GitHub - Code source et exemples
- Papier GraphRAG - Document de recherche original
- Document d'algorithme de Leiden - Algorithme de détection communautaire
Série RAG:
- Partie 1: Origines et fondements du RAG
- Partie 2: Architecture et éléments internes du RAG
- Partie 3: RAG dans la pratique
- Partie 4: Recherche sémantique avec ONNX et Qdrant
- Pièce 5: Recherche hybride & AutoM SK2Indexage
Solutions de rechange simples (BERT + BMM SK2
- DocSummarizer Part 3 - Récupération hybride sans frais graphiques
- Architecture de Cody Sourcegraph - Recherche hybride de production