ในฐานะวิศวกรที่ทำงานกับระบบ RAG (Retrieval-Augmented Generation) มานานกว่า 3 ปี ผมเคยเจอปัญหาซ้ำแล้วซ้ำเล่า: การค้นหาแบบ vector similarity แม้จะเร็ว แต่ขาดความเข้าใจเชิงความสัมพันธ์ ทำให้คำตอบบางครั้งไม่ตรงบริบท Graph RAG จึงเข้ามาแก้ปัญหานี้ด้วยการใช้ Knowledge Graph ในการจัดโครงสร้างข้อมูลและเพิ่มประสิทธิภาพการ检索
Graph RAG คืออะไร และทำไมต้องสนใจ
Graph RAG เป็นเทคนิคที่ผสมผสาน Knowledge Graph เข้ากับ RAG pipeline ปกติ แทนที่จะ检索เอกสารทั้งหมดแบบแบนราบ (flat) เราจะสร้างกราฟของ entities, relationships และ properties ทำให้ระบบเข้าใจความเชื่อมโยงระหว่างข้อมูลได้ดีขึ้น ผลลัพธ์คือคำตอบที่แม่นยำและมีบริบทมากขึ้น โดยเฉพาะกับคำถามที่ต้องการการวิเคราะห์เชิงลึก
สถาปัตยกรรม Graph RAG แบบ Production-Ready
จากประสบการณ์ส่วนตัว ผมได้พัฒนา architecture ที่รองรับ workload จริงใน production ดังนี้:
"""
Graph RAG Pipeline - Production Architecture
สถาปัตยกรรมที่รองรับ high-concurrency และ low-latency
"""
import asyncio
from typing import List, Dict, Optional, Tuple
from dataclasses import dataclass, field
from enum import Enum
import numpy as np
from collections import defaultdict
import hashlib
import time
class RetrievalStrategy(Enum):
VECTOR_ONLY = "vector"
GRAPH_ONLY = "graph"
HYBRID = "hybrid" # แนะนำสำหรับ most use cases
GRAPH_FIRST = "graph_first"
@dataclass
class Entity:
id: str
type: str
properties: Dict[str, any]
embedding: Optional[np.ndarray] = None
created_at: float = field(default_factory=time.time)
@dataclass
class Relationship:
source_id: str
target_id: str
relation_type: str
weight: float = 1.0
properties: Dict[str, any] = field(default_factory=dict)
@dataclass
class KnowledgeGraph:
entities: Dict[str, Entity] = field(default_factory=dict)
relationships: List[Relationship] = field(default_factory=list)
adjacency: Dict[str, List[Tuple[str, str]]] = field(default_factory=dict)
def add_entity(self, entity: Entity):
self.entities[entity.id] = entity
if entity.id not in self.adjacency:
self.adjacency[entity.id] = []
def add_relationship(self, rel: Relationship):
self.relationships.append(rel)
self.adjacency[rel.source_id].append((rel.target_id, rel.relation_type))
self.adjacency[rel.target_id].append((rel.source_id, rel.relation_type))
def get_neighbors(self, entity_id: str, depth: int = 1) -> List[str]:
"""Graph traversal สำหรับ context expansion"""
visited = {entity_id}
current_level = {entity_id}
for _ in range(depth):
next_level = set()
for node in current_level:
for neighbor, _ in self.adjacency.get(node, []):
if neighbor not in visited:
next_level.add(neighbor)
visited.update(next_level)
current_level = next_level
return list(visited - {entity_id})
class GraphRAGEngine:
def __init__(
self,
api_key: str,
base_url: str = "https://api.holysheep.ai/v1",
embedding_model: str = "text-embedding-3-large",
llm_model: str = "gpt-4.1",
max_concurrent: int = 50,
cache_ttl: int = 3600
):
self.api_key = api_key
self.base_url = base_url
self.embedding_model = embedding_model
self.llm_model = llm_model
self.semaphore = asyncio.Semaphore(max_concurrent)
# In-memory cache สำหรับลด API calls
self._cache: Dict[str, any] = {}
self._cache_ttl = cache_ttl
# Knowledge Graph instance
self.kg = KnowledgeGraph()
def _get_cache_key(self, query: str, strategy: str) -> str:
return hashlib.md5(f"{query}:{strategy}".encode()).hexdigest()
async def _get_embedding(self, text: str) -> np.ndarray:
"""ดึง embedding ผ่าน HolySheep API - ราคาถูกกว่า 85%"""
cache_key = self._get_cache_key(text, "embedding")
if cache_key in self._cache:
return self._cache[cache_key]
async with self.semaphore:
# HolySheep API - base_url ต้องเป็น https://api.holysheep.ai/v1
response = await self._make_request(
endpoint="/embeddings",
payload={
"model": self.embedding_model