Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
134 changes: 134 additions & 0 deletions docs/graph-rag-flow.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,134 @@
# GraphRAG Flow

## [Step 1: Document - 데이터 수집]

1. **Loader**
* **Goal**: 원본 데이터(공지사항, 게시글 등)를 시스템으로 로드
* **Process**:
* site: 지웰홈스왕십리(1000024)
* board: 공지사항(1000039), FAQ(1000038), 입주안내(1000087) etc
* site의 board를 가져와서 Document/Image로 저장

2. **Vision (이미지 처리)**
* **Goal**: 이미지 내 텍스트를 추출하여 검색 및 답변에 활용
* **Input**: Image URL
* **Process**:
* **Prompt**:
* 검색 / 답변 생성에 사용 가능한 구조화된 텍스트를 추출
* raw text: 이미지의 모든 텍스트 추출
* **Output**: OCR 또는 Vision Model을 사용하여 추출한 이미지의 모든 텍스트(Raw Text)
* 텍스트를 Image에 업데이트 (원본 보존)

## [Step 2: Transform - 데이터 변환]

1. **Build Document Content**
* **Strategy**: `MD2` (Markdown Conversion)
* **Process**: `Document` 및 `Image` 데이터를 그래프 구축에 적합한 Markdown 형식의 텍스트로 변환

## [Step 3: Graph Storage - 지식 그래프 구축]

1. **Extract Nodes (Phase 1)**
* **Goal**: 5W1H(육하원칙)에 따라 엔티티를 추출하고 분류
* **Prompt Rules**:
* **Language**: 한국어(Korean) 필수
* **Entity Types (14 types)**:
* **Who**: `ACTOR` (행위자), `AUTHOR` (작성자)
* **What**: `OBJECT` (대상), `EVENT` (사건), `IMAGE` (이미지), `WEB` (웹사이트), `CATEGORY` (카테고리)
* **How**: `PROCEDURE` (절차)
* **Why**: `CONDITION` (조건)
* **Where**: `LOCATION` (위치)
* **When**: `DATETIME` (날짜/시간), `YEAR`, `MONTH`, `DAY`
* **Attributes**:
* `type`: 엔티티 유형
* `context`: 엔티티가 포함된 문맥
* **Output**: Entity Nodes

2. **Normalize Nodes**
* **Goal**: Entity Nodes의 정규화
* **Rules**:
* **Surfcae match** (텍스트 표면 일치 및 맥락 유사도 검사)
* `base score`: `SequenceMatcher`를 통해 이름(name)이 형태적으로 얼마나 유사한지 측정 (70% 비중)
* `타입 검증 (Strict Filter)`: 이름 유사도가 높더라도 Type(Labels)이 다르면 서로 다른 존재로 간주함 (base score * 0.3)
* `맥락 보정(Context Boost)`: `SequenceMatcher`를 통해 노드의 context가 형태적으로 얼마나 유사한지 측정 (feature_match_score) (70% 비중)
* **DBSCAN** (Density-Based Spatial Clustering Of Applications With Noise)
* 밀도 기반 군집화: 계산된 유사도 score로 데이터 중심의 군집화 수행
* 거리 변환 (Distance Metric): $Distance = 1 - Similarity\_Score$
* 자동 군집화: 임계값(0.75) 이내의 밀도를 가진 노드들을 하나의 그룹으로 모음

* **Canonicalization (대표성 추출 및 병합)**
* 그룹화된 Entity들을 하나의 `Node`로 재구성
* 대표 이름 결정: 군집 내에서 가장 빈번하게 등장한 이름을 엔티티의 공식 명칭(Canonical Name)으로 선택
* 데이터 통합: 속성(attributes)과 특징(features) 데이터에서 중복을 제거한 뒤 하나로 구성
* **Output**: Normalized Entity Nodes

3. **Extract Edges (Phase 2)**
* **Goal**: 엔티티 간 인과관계 및 시간적 계층 구조 설정 (BFS 최적화)
* **Prompt Rules**:
* **Language**: 한국어(Korean) 필수
* **Hub Node Strategy**:
* **Temporal Hub**: 주요 노드(OBJECT, EVENT) -> DATETIME 연결
* **Hierarchy**: DATETIME -> DAY -> MONTH -> YEAR 연결
* **Edge Types**:
* `EXECUTED_BY`: (Procedure/Event/Object) -> (Actor/Author)
* `SCHEDULED_ON`: (Any) -> (Datetime)
* `PART_OF`: (Datetime/Day/Month) -> (Day/Month/Year)
* `DEPENDS_ON`: (Object/Procedure) -> (Condition/Datetime)
* `TRIGGERS`: (Event) -> (Procedure/Event)
* `LOCATED_IN`: (Any) -> (Location)
* `HAS_DETAIL`: (Object) -> (Image/Web/Category)
* **Output**: Entity Edges

4. **Summarize Nodes (Phase 3)**
* **Goal**: 검색 품질(BM25) 향상을 위한 노드 요약 및 키워드 추출
* **Process**:
* **Prompt Rules**:
* **Language**: 한국어(Korean) 필수
* LLM을 활용하여 Vision 텍스트를 포함하여 중요 키워드 추출
* LLM을 활용하여 노드 관련 내용을 요약
* **Output**: Attributes와 Summary가 포함된 최종 Entity Nodes

5. **Add Episode (저장)**
* **Goal**: 그래프 데이터와 원본 데이터를 통합 저장
* **Structure**:
* **Group ID**: `site-{siteId}-{strategy}`
* **Episode Body**: 원본 텍스트(Markdown) 및 Vision 추출 텍스트 보존 (답변 생성의 근거)
* **Graph**: 추출된 Node 및 Edge 저장

## [Step 4: Graph RAG - 검색 및 답변 생성]

1. **Query Rewrite**
* **Goal**: 질문 재작성
* **Prompt Rules**:
* 질문을 검색 및 답변에 용이한 완전한 문장으로 작성
* **Output**: 재작성된 질문 텍스트

2. **Graph Retrieve (Fused Search)**
* **Strategy**: Text(BM25) + Vector + Graph(BFS) 결합
* **Flow**:
* a. **BM25 Search (Text)**: 키워드 기반 노드 검색 (Weight: 02)
* b. **Vector Search (Embedding)**: 의미 기반 노드 검색 (Weight: 04)
* c. **BFS Expansion (Graph)**: Vector 검색 상위 노드를 Seed로 하여 연결된 노드(날짜, 상세 정보 등) 확장 (Weight: 04)
* d. **Fusion**: RRF(Reciprocal Rank Fusion) 방식으로 최종 순위 결정 및 상위 N개 노드 도출

3. **Prompt Construction**
* **Components**:
* **System Prompt**: 페르소나 및 답변 규칙
* **User Prompt**:
* quesiton: Original Query (사용자 질문)
* nodes: Retrieved Nodes (그래프 맥락)
* documents: Episode Body (원본 문서 및 Vision 텍스트)

4. **Generate Response**
* **Process**: LLM이 구성된 프롬프트를 바탕으로 사용자 질문에 대한 최종 답변 생성
* **Output**: 생성된 최종 답변

---

## 요약

1. **저장 (Indexing)**
* `Document` -> `Loader`/`Vision` -> `Transform(MD2)` -> `Graph Extraction` -> `Storage (Graph + Episode)`
2. **검색 (Retrieval)**
* `Query` -> `Rewrite` -> `Fused Search (BM25 + Vector + BFS)` -> `Context Construction`
3. **생성 (Generation)**
* `Context` + `Query` -> `LLM` -> `Answer`
231 changes: 231 additions & 0 deletions docs/graph-rag.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,231 @@
# Graph RAG Experiment

## 1. 목적

기존 RAG의 한계를 개선하는 것을 목표로 Graphiti 기반의 Graph RAG 구조를 적용하여, Knowledge Graph가 검색 품질과 문맥 향상에 미치는 영향을 검증한다.

구체적으로 다음을 확인한다.

1. Graph RAG 적용에 따른 연관 문서 검색 정확도
2. 엔티티 관계 기반 탐색을 활용한 복합 질의 처리 성능
3. 필터링 적용한 검색으로 단지 및 날짜별 정확도

이 과정을 통해, Graph 기반 검색 구조가 기존 벡터 기반 RAG의 구조적 한계를 넘어 높은 연관성의 문서 검색이 가능하다는 것을 검토한다.

---

## 2. 배경

### 2.1 기존 응답 사례 분석

* 문서 간 관계나 시점 정보를 인식하지 못함
* 단순 벡터 유사도에 의존한 검색 → 부정확한 맥락 + 불필요한 정보 포함

| 질의 내용 | 검색 결과 | 실제 응답 | 기대 응답 | 주요 문제점 |
| -------------------- | ------------------------------------------- | ----------------- | ----------------------- | -------------------------------------------------- |
| 이번 7월 가정식 메뉴 알려줘 | '2024년 7월'로 질문 재작성됨 → 2025년 7월 가정식 메뉴 문서 검색 | 2025년 메뉴 내용 출력 | 2025년 7월 가정식 메뉴 | **재작성 오류 + 검색 시점 인식 실패의 복합 오류**. 내부 과정의 **시점 불일치** |
| 라운지 시설 어떻게 이용할 수 있어? | ‘냉장/냉동고 정리안내’, ‘라운지 이용 설문조사’ 문서 검색 | 냉장고 정리 및 설문 관련 내용 | ‘라운지 시설은 예약제로 이용 가능하다.’ | 관련 문서가 없음에도 **유사도 스코어 기반으로 비관련 문서 선택** |

### 2.2 문제 유형

| 유형 | 원인 | 영향 |
| --------- | ---------------- | ---------------- |
| 시점 인식 오류 | 날짜·기간 메타정보 반영 부족 | 잘못된 연도·기간의 응답 생성 |
| 비관련 문서 선택 | 유사도 점수 기반 검색 | 질문 의도와 무관한 응답 생성 |

---

## 3. 실험 환경

### 3.1 모델 설정

* 임베딩: `text-embedding-3-small`
* LLM: `gpt-5-mini`

* Entity 추출 및 Edge 생성, 응답 생성

### 3.2 검색 및 랭킹 (Updated)

기존의 “Doc Entry Node → Graph 확장” 중심에서, **Fused Search + Graph(BFS) 확장** 중심으로 변경됨.

* **Text 검색 (BM25)**

* **Vector 검색 (Cosine Similarity)**

* **Graph 검색 (BFS, multi-hop)**

* Vector 결과 상위 N개를 origin으로 잡고
* `NodeSearchMethod.bfs`, `bfs_max_depth = N`로 확장

* **Fusion(RRF 스타일 가중 합산)**

* text: `0.2`
* vector: `0.4`
* graph: `0.4`
* 각 소스별 랭크에 대해 `1/(rank+1) * weight`로 점수 누적 후 최종 정렬

> 결과적으로, “의미 기반(벡터) + 정확 키워드(BM25) + 관계 기반(BFS)”를 한 번에 결합해 **비관련 문서의 비중을 낮추고 관련 문서의 비중을 높게**한다.

### 3.3 데이터 저장 (Episodes)

* Group: `site:{site_id}`
* 각 Episode는 Markdown 포맷으로 변환되 텍스트를 **episode_body로 저장**
* LLM이 원문으로부터 엔티티를 추출하여 Graph로 구조화

### 3.4 Entity / Edge 스키마 (Updated)

#### Entity Types

* **Who(주체/작성)**

* `Actor`(부서/기관/업체 등 행위 주체)
* `Author`(개인 작성자)
* **What(대상)**

* `Object`(공지/문서/자산/식단/메뉴 등 핵심 대상)
* **How(절차)**

* `Procedure`(신청/업무 단계/지침)
* **Why(근거/조건)**

* `Condition`(규정/자격/법령)
* **Event(사건/행사)**

* `Event`
* **Where(장소)**

* `Location`
* **When(시간 계층)**

* `Datetime`(정규화된 시점)
* `Year`, `Month`, `Week`, `Day`(시간 계층 노드)
* **기타**

* `Concept`(전문 용어/도메인 지식)
* `Image`(첨부 이미지)
* `Web`(외부 링크)
* `Category`(게시판/분류)

#### Edge Types

* `EXECUTED_BY` : 작성자/실행 주체 연결 (Who)
* `SCHEDULED_ON` : 특정 시점 할당 (When)
* `PART_OF` : 시간 계층 구성 (Datetime–Day–Month–Year 등)
* `DEPENDS_ON` : 조건/근거 참조 (Why)
* `TRIGGERS` : 인과/유발 관계 (Event 중심)
* `LOCATED_IN` : 장소 연결 (Where)
* `HAS_DETAIL` : 이미지/링크/카테고리/컨셉 등 상세 연결 (Metadata)

#### Edge Type Mapping(규칙 기반 연결)

엔티티 조합별 허용 엣지를 제한하여 **잘못된 엣지 생성/확장을 방지**하고, multi-hop 추론을 안정화한다.

예시:

* (`Object` → `Author`) = `EXECUTED_BY`
* (`Object` → `Datetime`) = `SCHEDULED_ON`
* (`Datetime` → `Day`) = `PART_OF`
* (`Object` → `Image/Web/Concept/Category`) = `HAS_DETAIL`
* (`Object/Procedure` → `Condition`) = `DEPENDS_ON`

### 3.5 선택 이유 (Updated)

| 항목 | 설명 |
| -------------------------------------------- | -------------------------------------------------------------- |
| **Episode Body 원본 유지** | Node/Edge는 요약/속성 중심이므로, 최종 답변 근거는 원본(episode_body)이 가장 신뢰도가 높음 |
| **도메인 엔티티 확장(Object/Procedure/Condition 등)** | “누가/무엇을/어떻게/왜/언제/어디서” 질의에 구조적으로 대응 |
| **시간 계층(Year/Month/Week/Day) + Datetime** | “이번 7월”, “올해”, “3월 2주차” 같은 기간 질의를 계층적으로 필터/확장 가능 |
| **HAS_DETAIL로 메타 통합** | 이미지/링크/카테고리/컨셉을 하나의 패턴으로 연결해 확장/근거 제시에 유리 |
| **Fused Search(BM25+Vector+BFS)** | 유사도만으로 비관련 문서가 섞이는 문제를 완화하고, 관계 기반으로 재확장하여 맥락 일관성 강화 |
| **Community 요약 제공** | “테마/군집” 단위의 상위 요약을 함께 제공해 탐색성과 설명력 개선 |

---

## 4. 데이터 저장 (Episodes)

### 4.1 전체 구조 (Updated Concept)

```
Group (site:{site_id})
└─ Episodic (episode_body = 원문)
└─ Extracted Entities
├─ Object / Procedure / Condition / Event ...
├─ Author / Actor
├─ Datetime ─ PART_OF ─ Day ─ PART_OF ─ Month ─ PART_OF ─ Year
├─ Location
└─ Image / Web / Concept / Category
```

### 4.2 Entity / Edge 예시 (Updated)

| Entity | 의미 | 예시(Name) |
| ---------- | --------- | ---------------------------- |
| `Object` | 공지/문서/대상 | Object:관리비 납부마감안내 |
| `Author` | 작성자(개인) | Author:홍길동(생활지원센터) |
| `Actor` | 주체(부서/기관) | Actor:생활지원센터 |
| `Datetime` | 시점 | Datetime:2025-03-31 00:00:00 |
| `Month` | 월 | Month:3 |
| `Year` | 연도 | Year:2025 |
| `Category` | 분류 | Category:공지사항 |
| `Web` | 링크 | Web:/post/1000001/... |
| `Image` | 이미지 | Image:PT1000001:1000020 |

| Edge | 의미 |
| ---------------------------------------------------- | ----------- |
| `Object -[:EXECUTED_BY]-> Author/Actor` | 작성자/주체 연결 |
| `Object -[:SCHEDULED_ON]-> Datetime` | 문서 시점 연결 |
| `Datetime -[:PART_OF]-> Day/Month/Year` | 시간 계층 구성 |
| `Object -[:HAS_DETAIL]-> Image/Web/Category/Concept` | 상세/메타 연결 |
| `Object/Procedure -[:DEPENDS_ON]-> Condition` | 규정/조건 근거 |
| `Event -[:TRIGGERS]-> Procedure/Event` | 사건 기반 유발 관계 |
| `Object/Event -[:LOCATED_IN]-> Location` | 장소 연결 |

---

## 5. 검색 Flow (Updated)

### 5.1 전체 흐름

```
질문
→ BM25(Text) Node 검색
→ Vector(Cosine) Node 검색 (min_score=0.6)
→ Vector seed 기반 BFS(Graph) 확장 (depth=2)
→ Fusion(가중 RRF)
→ 상위 N개 노드 반환
→ (선택) episode_body 원문 로딩 후 LLM 응답 생성
```

### 5.2 Fused Search 세부 (search-fused)

* 입력: `query`, `group_ids`, `max_nodes`
* 병렬:

* Text nodes(BM25)
* Vector nodes(Cosine)
* Graph 확장:

* Vector nodes 상위 N개 uuid를 seed로 BFS 탐색(depth=2)
* Fusion:

* text 0.2 / vector 0.4 / graph 0.4
* 각 소스별 랭킹 점수 누적 후 최종 정렬
* 출력:

* `nodes`: 최종 상위 N개
* `facts`: 현재 미사용(None)

---

## 6. 검증 포인트 (Updated)

* 관련 노드(문서/대상) 검색 정확도 (BM25 vs Vector vs Fusion 비교)
* 복합 질의(규정/절차/시점/주체)에서 BFS 확장 효과
* 기간 질의(올해/이번 달/몇 주차)에서 시간 계층(PART_OF) 활용 가능성
* 카테고리/링크/이미지 등 메타 근거(HAS_DETAIL) 연결 품질

---

## 7. 결과

공지·게시판 검색에서는 단순 문서 유사도 기반 검색보다 **(1) 도메인 엔티티 구조화(Object/Procedure/Condition 등), (2) 시간 계층 모델링(Year/Month/Week/Day + Datetime), (3) BM25+Vector+BFS를 결합한 Fused Search**가 더 정확하고 일관된 응답을 제공한다.