graphify → 품아이 RAG 백본 통합 설계
작성: 2026-04-29 배경: 위키 86개 .md, ~56K 단어를 graphify로 분석. 390 노드 / 724 엣지 / 16개 커뮤니티 산출. 이를 품아이 엔진에 어떻게 통합할지 설계.
1. 현황 — 지금 vs 통합 후
지금 (v현재)
사용자 질문
→ _route() ← 키워드 매칭 (약 40개 키워드)
├─ chroma → ChromaDB 유사도 검색 → Gemini 답변
├─ supabase → Gemini SQL 생성 → Supabase 조회
└─ direct → Gemini 직접 답변
ChromaDB에는 Q&A 쌍이 들어 있다. “이런 질문엔 이런 답” 형식의 선언적 지식. 약점: 개념 간 관계를 모른다. “품아이와 사회지능 운동이 왜 연결되어 있는가”를 물으면 답 없음.
통합 후 (목표 상태)
사용자 질문
→ _route()
├─ chroma → 기존 그대로 (Q&A 유사도)
├─ supabase → 기존 그대로 (실시간 데이터)
├─ graph → [신규] graphify 관계 쿼리 (개념·맥락·이유)
└─ hybrid → [신규] graph 맥락 + chroma Q&A 병합
2. 아키텍처 — 두 엔진의 역할 분담
ChromaDB: 벡터 유사도 검색
- 형식: Q&A 쌍 문서 (site_qa_, poomasi_qa_ 접두사)
- 강점: “비슷한 질문 찾기”. 어떤 표현으로 물어도 유사도로 매칭
- 약점: 관계 구조 없음. “A가 B와 왜 연결되는가”를 모름
- 적합한 질문: “품아이 이용시간은?”, “로컬푸드 직매장 위치는?”, “조합원 가입 방법은?“
graphify graph.json: 구조 관계 쿼리
- 형식: 노드(개념) + 엣지(관계 유형) + 커뮤니티(군집)
- 강점: 개념 간 연결 경로, 커뮤니티 소속, 허브 노드 파악
- 약점: Q&A 형식 아님. 직접 답변 불가 → Gemini 프롬프트 보강용
- 적합한 질문: “품아이가 사회지능 운동과 어떻게 연결되는가?”, “5법인 컨소시엄 구조는?”, “로컬의 반격-마을이 뭔가?”, “도메인특화AI 사업의 위키 맥락은?”
어떤 질문에 어떤 엔진?
| 질문 패턴 | 엔진 |
|---|---|
| ”~가 뭐야”, “~는 어디야”, “~가 몇 시야” | ChromaDB |
| ”왜”, “어떻게 연결”, “맥락은”, “배경은” | graph |
| ”~와 ~의 관계”, “~가 ~에 어떤 영향” | graph |
| ”어제 매출”, “이번 달 거래”, “재고” | Supabase |
| ”정체성”, “우리 조직이 추구하는” | graph (god node 탐색) |
3. 통합점 — 어디에 박을지
통합 위치: engine.py _route() + _chroma_generate()
신규 라우트 graph를 추가하고, _graph_context() 함수를 신설한다.
의사코드 (Python)
# engine.py _route() 확장 — 신규 키워드 감지
GRAPH_KW = {
"왜", "어떻게", "연결", "관계", "맥락", "배경", "이유",
"구조", "컨소시엄", "운동", "비전", "미션", "전략"
}
def _route(self, query: str) -> str:
# ... 기존 라우팅 ...
has_graph = any(kw in query for kw in GRAPH_KW)
if has_graph and not has_data:
return "graph"
if has_graph and has_data:
return "hybrid" # graph 맥락 + supabase 데이터
# 기존 chroma 기본값 유지
return "chroma"
# engine.py 신규 함수
def _graph_context(self, query: str, depth: int = 2) -> str:
"""graphify graph.json에서 BFS로 관련 노드 추출 → 프롬프트 컨텍스트 반환"""
import json, networkx as nx
from networkx.readwrite import json_graph
GRAPH_PATH = "/home/haeory/poomasi/poomasi-notes/graphify-out/graph.json"
G = json_graph.node_link_graph(json.loads(open(GRAPH_PATH).read()), edges="links")
# 1. 쿼리 텀에서 매칭 노드 찾기
terms = [t for t in query.split() if len(t) >= 2]
scored = sorted(
[(sum(1 for t in terms if t in G.nodes[n].get("label","").lower()), n)
for n in G.nodes()],
reverse=True
)
start_nodes = [nid for score, nid in scored[:2] if score > 0]
if not start_nodes:
return ""
# 2. BFS depth=2 서브그래프 추출
subgraph_nodes = set(start_nodes)
frontier = set(start_nodes)
for _ in range(depth):
next_f = set()
for n in frontier:
for nb in G.neighbors(n):
if nb not in subgraph_nodes:
next_f.add(nb)
subgraph_nodes.update(next_f)
frontier = next_f
# 3. 관계 텍스트화 → Gemini 프롬프트 컨텍스트
lines = []
for n in subgraph_nodes:
label = G.nodes[n].get("label", n)
src = G.nodes[n].get("source_file", "")
lines.append(f"개념: {label} (출처: {src})")
for u, v in G.edges(subgraph_nodes):
if v in subgraph_nodes:
rel = G.edges[u, v].get("relation", "")
conf = G.edges[u, v].get("confidence", "")
lu = G.nodes[u].get("label", u)
lv = G.nodes[v].get("label", v)
lines.append(f"관계: {lu} --{rel}[{conf}]--> {lv}")
return "\n".join(lines[:80]) # 토큰 예산 ~2000자graph 컨텍스트를 Gemini 프롬프트에 주입하는 방식 — ChromaDB를 대체하지 않고 추가 레이어로 작동.
4. 데이터 흐름 — 위키 갱신 → 그래프 갱신
현재 흐름
후니님이 wiki/*.md 작성
→ git push (poomasi-notes 레포)
→ graph.json은 수동 업데이트 필요
자동화 옵션
Option A — git post-commit hook (권장 Phase 1)
# poomasi-notes/.git/hooks/post-commit
cd /home/haeory/poomasi/poomasi-notes/graphify-out
graphify /home/haeory/poomasi/poomasi-notes/wiki --update- 장점: 커밋 직후 자동 갱신, 토큰 절약 (
--update는 변경 파일만 재추출) - 단점: LLM 호출 포함 → 커밋 후 10~30초 지연
- 적합: 후니님이 위키를 자주 편집하는 경우
Option B — 수동 (Phase 0, 지금)
cd /home/haeory/poomasi/poomasi-notes
graphify wiki --update주 1회 또는 큰 위키 작업 후 지미가 실행. 현재 graph.json(2026-04-29 기준)으로 설계 검증 가능.
Option C — cron (Phase 2)
0 4 * * 1 cd /home/haeory/poomasi/poomasi-notes && graphify wiki --update
매주 월요일 새벽 4시 자동 실행. seed_server.py 재시작 없이 graph.json만 갱신되면 됨 (파일 읽기 방식이면 재시작 불필요).
5. MCP 옵션
graphify —mcp 동작 방식
python3 -m graphify.serve graphify-out/graph.jsonstdio MCP 서버로 실행. 제공 도구: query_graph, get_node, get_neighbors, get_community, god_nodes, graph_stats, shortest_path.
품아이가 MCP 클라이언트로 부르는 방식
현재 품아이 엔진(engine.py)은 Python 프로세스 내에서 동기 함수 호출로 동작. MCP는 subprocess stdio 통신 — 동기 통합이 어색함.
장점
- engine.py 코드 변경 최소화 (MCP 클라이언트 래퍼만 추가)
- graphify 버전 업그레이드 시 engine.py 영향 없음
- 다른 에이전트(지미, 팀원)도 같은 MCP 서버 공유 가능
단점
- subprocess 레이턴시 추가 (매 질문마다 ~50ms)
- seed_server.py 시작 시 MCP 서버도 같이 띄워야 함 (systemd unit 추가)
- Python 인프라 복잡도 증가
판단: Phase 0~1은 직접 graph.json 파일 읽기가 더 단순. MCP는 여러 에이전트가 동시에 그래프를 쿼리하는 Phase 2 이후에 의미 있음.
6. 단계별 로드맵
Phase 0 — 지금 (검증, 코드 변경 없음)
- graph.json 그대로 두고 지미가 수동으로
graphify query "질문"실행 - 품아이 답변 품질 개선에 graphify 결과를 수동으로 활용
- 목표: graph가 실제로 유용한지 검증. 어떤 질문 유형에서 ChromaDB를 보완하는지 데이터 수집
Phase 1 — 1~2주: engine.py 통합
작업: _graph_context() 함수 신설 + _route()에 graph 브랜치 추가
- graph.json을 서버 시작 시 한 번 로드, 메모리에 상주 (390 노드는 가벼움)
_route()키워드 기준: “왜”, “어떻게”, “관계”, “맥락”, “배경” 등 5~10개- Gemini 프롬프트에 graph 컨텍스트 prefix로 주입
- 승인 필요: engine.py 수정이므로 후니님 / 지미 승인 후 진행
Phase 2 — 1개월+: 자동 갱신 + 심화 통합
- git hook 또는 cron으로
graphify --update자동화 - god node (품아이, 품앗이생협, 품아이 전체 지도) 중심의 맥락 우선순위 로직
- MCP 서버 옵션 검토 (여러 에이전트 공유 필요 시)
- graphify 커뮤니티 레이블을 품아이 의도 분류에 활용 (“이 질문은 어느 커뮤니티 영역인가”)
7. 미해결 질문 / 후니님 결정 필요
Q1. graph 라우팅 키워드 범위 “왜”, “어떻게”, “맥락” 같은 키워드가 일상 질문(“왜 오늘 문 닫아요?“)에도 걸릴 수 있다. 허용 오탐 수준을 어디까지 볼 것인가.
Q2. graph.json 갱신 주기 위키는 지금도 계속 자라는 중. 갱신 안 된 graph는 오래된 지식 제공. Phase 1 시점에 수동 vs 자동 중 선택.
Q3. engine.py 수정 시점 설계 문서는 완성. 실제 코드 작업은 별도 승인 프로세스 필요. 지금 바로 할지, Phase 0 검증 후 할지.
Q4. ChromaDB에 위키 Q&A 추가 vs graph 별도 경로 위키 내용을 ChromaDB Q&A 형식으로 변환해 기존 경로에 넣는 방안(간단)과 graph 전용 경로를 신설하는 방안(정밀) 중 선택. 트레이드오프:
- ChromaDB 추가: 기존 코드 그대로, 관계 정보는 잃음
- graph 신설: 관계 유지, engine.py 수정 필요
Q5. graph 커뮤니티 “품아이 엔진·인프라”(65 노드) 우선 통합 여부 graphify가 추출한 커뮤니티 0번이 engine.py, ChromaDB, seed_server, Supabase 등 기술 스택을 모두 포함. 이 커뮤니티를 품아이 자기지식(내부 구조 인지) 용도로 먼저 통합하면 “품아이야, 네 엔진 어떻게 돼?” 질문에 답할 수 있게 됨.
요약
graphify graph.json은 ChromaDB를 대체하지 않는다. 두 엔진은 서로 다른 질문에 답한다.
- ChromaDB: “이거 뭐야?” (사실 조회)
- graph: “이게 왜 중요하고 어떻게 연결돼?” (맥락·관계·이유)
- Supabase: “어제 얼마 팔렸어?” (실시간 데이터)
브레인맵 기준으로 graph 통합은 현재 “없음”으로 표시된 **두정엽(감각 통합)**을 채우는 작업이다. 여러 커뮤니티에서 온 지식을 하나의 답변으로 통합하는 능력.
연결
- 품아이 브레인맵 — 두정엽(감각 통합) 강화가 목표
- 품아이 전체 지도 — ChromaDB·Supabase 위치
- 모델은 부품, 데이터가 본체 — graph.json도 데이터 자산