약국 POS 시스템의 GraphRAG 기반 추천 시스템 구축 관련 문서:
## 핵심 설계 문서
1. 질병코드기반 제품추천.md
- ICD-10 질병 코드 활용 추천 시스템 설계
- 계층 구조 (질병 → 질병군 → 제품군 → 개별 제품)
- 처방전 기반 추천 알고리즘
2. complex-product-graph-modeling.md
- 복합제(비맥스제트 등) 그래프 모델링
- 성분 간 시너지 효과 표현
- 복합 증상 매칭 쿼리 예시
3. pubmed-graphrag-workflow.md
- PubMed → GraphRAG 전체 워크플로우 (5단계)
- 논문 검색, 근거 추출, 지식 그래프 구축
- MCP Server 개발 가이드
## 그래프 DB 비교 및 평가
4. sqlite-graph-evaluation.md
- SQLite vs SQLite-Graph vs Neo4j 비교
- 현 시점(2026-01) 평가: 기존 SQL 유지 권장
- 6개월 후 재평가 계획
5. opensource-graph-db-comparison.md
- 오픈소스 그래프 DB 비교 (Neo4j, ArangoDB 등)
6. 온톨로지로전환.md
- 관계형 DB → 온톨로지 구조 전환 가이드
- PubMed RAG 활용 방안
- 추론 규칙 설계
## PubMed GraphRAG 활용
7. pycnogenol-multi-indication-graphrag.md
- 피크노제놀 다중 적응증 GraphRAG 구축 사례
- 7가지 적응증별 근거 수준
8. grpahrag_아쉬아간다.md
- Ashwagandha GraphRAG 구축 사례
9. pubdmed이용ai.md
- PubMed + AI 통합 활용 가이드
## 추가 워크플로우
10. pubmed-graphrag-workflow_next.md
- 다음 단계 워크플로우
11. PostgresGRAPH전환.md
- PostgreSQL + Apache AGE 전환 가이드
모든 문서는 한국어로 작성되었으며, 코드 예시는 영어로 포함.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
15 KiB
15 KiB
PostgreSQL Apache AGE 기반 약국 GraphRAG 추천 시스템 기획서
작성일: 2026-01-24 프로젝트: 약국 POS QR 마일리지 시스템 → 근거 기반 AI 추천 시스템 전환
1. 프로젝트 개요
목표
기존 SQLite 기반 약국 시스템을 PostgreSQL + Apache AGE로 확장하여, PubMed 논문 근거 기반 GraphRAG 제품 추천 시스템 구축
핵심 가치
- ✅ 근거 기반 추천: "왜 이 제품을 추천하는가?" → 논문(PMID) 근거 제시
- ✅ 복합 증상 매칭: "피로 + 소화불량 + 스트레스" → 최적 복합제 추천
- ✅ 추론 경로 시각화: Statin → 근육약화 → CoQ10 추천 경로
- ✅ AI 카테고리 관리: 무분별한 증가 방지, 23개 기본 카테고리 유지
2. 현황 분석
현재 시스템
- MSSQL (PIT3000): 판매 거래 데이터
- SQLite (mileage.db): 제품 마스터, 카테고리, 질병 코드
- PubMed 파이프라인: 완성 (여러 연구 스크립트로 근거 수집 중)
주요 데이터
- 제품 마스터: 바코드 기준 (동일 제품 다른 이름 가능)
- 카테고리: 23개 기본 (진통제, 소화제, 복합비타민 등)
- 질병 코드: ICD-10 기반
- 제품-카테고리 매핑: 다대다 (relevance_score 0.0~1.0)
현재 한계
- ❌ 복잡한 관계 표현 불가 (약물 → 부작용 → 예방 관계)
- ❌ 추론 경로 제시 불가
- ❌ PubMed 근거와 제품 연결 미흡
- ❌ 성분 간 시너지 표현 불가
3. 기술 아키텍처
3.1 시스템 구조
┌─────────────────────────────────────┐
│ 웹앱 (Flask) + 관리자 대시보드 │
└───────────────┬─────────────────────┘
↓ REST API
┌───────────────────────────────────────┐
│ Flask Backend (Python) │
│ - GraphRAG Service (Cypher 쿼리) │
│ - OpenAI (카테고리 태깅) │
│ - PubMed (Biopython) │
└───────────────┬───────────────────────┘
↓
┌───────────────────────────────────────┐
│ PostgreSQL 15 + Apache AGE │
├───────────────────────────────────────┤
│ SQL 테이블: │
│ - products (제품 마스터) │
│ - categories (카테고리) │
│ - evidence (PubMed 논문) │
├───────────────────────────────────────┤
│ 그래프 (Cypher): │
│ 노드: Product, Ingredient, │
│ Symptom, Disease, Evidence │
│ 엣지: CONTAINS, TREATS, CAUSES, │
│ PREVENTS, SYNERGY_WITH │
└───────────────────────────────────────┘
3.2 기술 스택
| 레이어 | 기술 |
|---|---|
| DB | PostgreSQL 15 + Apache AGE 확장 |
| Backend | Python 3.11 + Flask |
| 그래프 쿼리 | Cypher (Apache AGE) |
| AI | OpenAI GPT-4o (카테고리 태깅, 추천 설명) |
| PubMed | Biopython (논문 검색 및 근거 수집) |
| 캐싱 | Redis (추천 결과 캐싱) |
| 라이브러리 | psycopg2, apache-age-python |
4. 데이터 모델 설계
4.1 그래프 노드 타입
Product (제품)
(:Product {
barcode: '8806436016712',
name: '탁센캡슐',
manufacturer: '동아제약',
price: 8000
})
Ingredient (성분)
(:Ingredient {
id: 'naproxen',
name: '나프록센',
category: 'NSAID'
})
Symptom (증상)
(:Symptom {
id: 'headache',
name: '두통',
severity: 'moderate'
})
Disease (질병)
(:Disease {
icd_code: 'K30',
name: '소화불량',
category: '소화기질환'
})
Evidence (PubMed 논문)
(:Evidence {
pmid: '27959716',
title: 'CV Safety of Naproxen',
journal: 'NEJM',
year: 2016,
reliability: 0.99
})
4.2 그래프 관계 타입
| 관계 | From → To | 속성 | 의미 |
|---|---|---|---|
| CONTAINS | Product → Ingredient | amount, role | 제품이 성분 포함 |
| TREATS | Ingredient → Symptom/Disease | efficacy, evidence_pmid | 성분이 증상 치료 |
| CAUSES | Ingredient → Symptom | probability, severity | 성분이 부작용 유발 |
| PREVENTS | Ingredient → Symptom | efficacy, dosage | 성분이 부작용 예방 |
| SYNERGY_WITH | Ingredient ↔ Ingredient | synergy_score, reason | 성분 간 시너지 |
| SAFER_THAN | Product → Product | aspect, confidence | 제품 안전성 비교 |
| BELONGS_TO | Product → Category | relevance_score | 제품-카테고리 매핑 |
4.3 PostgreSQL 테이블
-- 제품 마스터
CREATE TABLE products (
barcode TEXT PRIMARY KEY,
product_name TEXT NOT NULL,
manufacturer TEXT,
price INTEGER,
stock INTEGER,
ingredients_json JSONB,
search_vector tsvector
);
-- 카테고리 (계층 구조)
CREATE TABLE categories (
category_id SERIAL PRIMARY KEY,
category_name TEXT UNIQUE NOT NULL,
parent_id INTEGER REFERENCES categories(category_id),
level INTEGER DEFAULT 1, -- 1: 기본 23개, 2-3: 서브
description TEXT
);
-- PubMed 논문
CREATE TABLE evidence (
pmid TEXT PRIMARY KEY,
title TEXT NOT NULL,
journal TEXT,
year INTEGER,
study_type TEXT,
abstract TEXT,
reliability REAL
);
5. 핵심 기능
5.1 근거 기반 제품 추천
입력:
- 증상: ["두통", "피로"]
- 환자 프로필: 65세, 고혈압, Statin 복용 중
- 예산: 20,000원
Cypher 쿼리:
MATCH (p:Product)-[:CONTAINS]->(i:Ingredient)-[t:TREATS]->(s:Symptom)
WHERE s.name IN ['두통', '피로']
AND p.price <= 20000
OPTIONAL MATCH (e:Evidence {pmid: t.evidence_pmid})
WHERE e.reliability > 0.8
RETURN p.name, p.price,
COLLECT(s.name) AS symptoms,
e.pmid, e.title, e.reliability
ORDER BY e.reliability DESC, COUNT(DISTINCT s) DESC
LIMIT 5
출력:
{
"recommendations": [
{
"name": "비맥스제트",
"price": 15000,
"symptoms_covered": ["피로", "소화불량"],
"evidence": {
"pmid": "12345678",
"title": "Vitamin B Complex for Fatigue",
"reliability": 0.85
},
"reasoning": "비타민 B복합체가 피로 회복에 효과적입니다. (PMID:12345678, 신뢰도: 85%)"
}
]
}
5.2 복합 증상 매칭 + 시너지
Cypher 쿼리:
-- 피로 + 근육통 + 스트레스를 동시에 치료하면서 시너지 있는 제품
MATCH (p:Product)-[:CONTAINS]->(i1:Ingredient)-[:TREATS]->(s:Symptom)
WHERE s.name IN ['피로', '근육통', '스트레스']
WITH p, COUNT(DISTINCT s) AS coverage
WHERE coverage >= 2
MATCH (p)-[:CONTAINS]->(i1:Ingredient)-[:TREATS]->(:Symptom {name: '피로'})
MATCH (p)-[:CONTAINS]->(i2:Ingredient)-[:TREATS]->(:Symptom {name: '근육통'})
OPTIONAL MATCH (i1)-[syn:SYNERGY_WITH]->(i2)
RETURN p.name, coverage,
i1.name + ' + ' + i2.name AS combo,
syn.synergy_score AS synergy,
p.price
ORDER BY coverage DESC, synergy DESC
예시 결과: 비맥스제트 (비타민B1 + 마그네슘, 시너지 0.9)
5.3 추론 경로 시각화
쿼리: Statin → 근육약화 → CoQ10 추천 경로
MATCH path = (drug:Ingredient {id: 'statin'})
-[:CAUSES]->(side:Symptom {name: 'muscle_weakness'})
<-[:PREVENTS]-(supplement:Ingredient {id: 'coq10'})
RETURN [node IN nodes(path) | node.name] AS reasoning_path,
[rel IN relationships(path) | type(rel)] AS relationships
결과:
{
"reasoning_path": ["Statin", "근육약화", "CoQ10"],
"relationships": ["CAUSES", "PREVENTS"],
"explanation": "Statin은 근육약화를 유발할 수 있으며, CoQ10이 이를 예방합니다."
}
5.4 AI 카테고리 자동 태깅
프로세스:
- 제품명 + 성분 정보 → OpenAI GPT-4o
- 기존 23개 카테고리에서 1~3개 선택
- relevance_score (0.0~1.0) 자동 계산
- 그래프에 BELONGS_TO 관계 생성
예시:
# 입력
product = {
"name": "탁센캡슐",
"ingredients": ["나프록센 250mg"]
}
# AI 응답
{
"categories": [
{"name": "진통소염제", "score": 1.0, "reason": "주성분이 NSAID"},
{"name": "진통제", "score": 0.9, "reason": "진통 효과"}
]
}
# 그래프 저장
CREATE (p:Product {barcode: '8806436016712'})
-[:BELONGS_TO {relevance_score: 1.0, tagged_by: 'AI'}]
->(c:Category {name: '진통소염제'})
6. 카테고리 관리 전략
6.1 3단계 계층 구조
Level 1 (고정 23개 - 기본 카테고리)
├─ 진통소염제
│ ├─ Level 2 (서브 카테고리)
│ │ ├─ NSAID
│ │ └─ 아세트아미노펜
│ └─ Level 3 (세분화)
│ └─ 심혈관 안전 NSAID
├─ 소화제
│ ├─ 위장약
│ └─ 정장제
└─ 복합비타민
├─ B복합체
└─ 종합비타민
6.2 신규 카테고리 추가 규칙
원칙:
- Level 1 (23개) = 절대 불변
- Level 2-3 = 약사/AI 제안 → 검토 후 승인
- 월 최대 2개 신규 허용
- 최소 10개 제품 예상 시에만 추가
워크플로우:
- 약사/AI가 신규 카테고리 제안
- AI 검증 (필요성, 중복 여부)
- 영향도 분석 (기존 제품 재분류 필요성)
- 승인 시 → 기존 전체 제품 재검토 (AI 일괄 태깅)
7. 마이그레이션 계획
Phase 1: 환경 설정 (1주)
# PostgreSQL + AGE 설치
sudo apt install postgresql-15 postgresql-15-age
# 그래프 생성
CREATE EXTENSION age;
SELECT create_graph('pharmacy_graph');
# Python 라이브러리
pip install psycopg2-binary apache-age-python biopython
Phase 2: 데이터 마이그레이션 (2주)
Step 1: SQLite → PostgreSQL (SQL 테이블)
- products, categories, evidence
Step 2: 그래프 노드 생성
- Product, Ingredient, Symptom, Disease 노드
Step 3: 관계 생성
- CONTAINS, TREATS, BELONGS_TO 엣지
Step 4: PubMed 근거 통합
- 주요 약물-증상 쌍 100개 논문 수집
- Evidence 노드 + TREATS 관계에 pmid 연결
Phase 3: 검증 및 테스트 (1주)
- 노드/엣지 개수 검증
- Cypher 쿼리 성능 테스트
- SQLite vs PostgreSQL+AGE 병렬 운영
Phase 4: API 개발 (2주)
/api/recommend- GraphRAG 추천/api/graph/path- 추론 경로/api/categories/tag- AI 자동 태깅
8. API 설계
8.1 POST /api/recommend
Request:
{
"symptoms": ["두통", "피로"],
"patient_profile": {
"age": 65,
"conditions": ["HTN"],
"medications": ["Atorvastatin 10mg"]
},
"budget": 20000
}
Response:
{
"recommendations": [
{
"barcode": "8806436016712",
"name": "탁센캡슐",
"price": 8000,
"score": 0.95,
"reasoning": {
"path": ["Naproxen", "TREATS", "두통"],
"evidence": {
"pmid": "27959716",
"title": "CV Safety of Naproxen",
"reliability": 0.99
}
}
}
]
}
8.2 GET /api/products/<barcode>/graph
제품의 전체 관계 그래프 반환 (성분, 증상, 근거 논문)
8.3 POST /api/categories/tag-batch
AI 일괄 카테고리 태깅
9. 성능 최적화
인덱스
CREATE INDEX idx_products_barcode ON products(barcode);
CREATE INDEX idx_products_search ON products USING GIN(search_vector);
CREATE INDEX idx_evidence_reliability ON evidence(reliability DESC);
캐싱 (Redis)
- 추천 결과: TTL 1시간
- 그래프 경로: TTL 24시간
- 카테고리 목록: TTL 7일
Cypher 최적화
- 증상부터 역방향 탐색 (인덱스 활용)
- OPTIONAL MATCH 최소화
- WITH 절로 중간 필터링
10. 구현 우선순위
우선순위 1 (필수, 2주)
- ✅ PostgreSQL + AGE 설치
- ✅ 기본 스키마 생성
- ✅ SQLite 데이터 마이그레이션
- ✅ Product, Ingredient 노드 생성
- ✅ CONTAINS, TREATS 관계
우선순위 2 (핵심, 2주)
- ✅
/api/recommendAPI - ✅ PubMed 근거 통합 (100개 논문)
- ✅ 복합 증상 매칭 Cypher 쿼리
- ✅ 추론 경로 생성
우선순위 3 (AI, 1주)
- ✅ AI 카테고리 자동 태깅
- ✅ 신규 카테고리 제안 워크플로우
- ✅ 카테고리 계층 관리
우선순위 4 (최적화, 1주)
- ✅ 인덱스 최적화
- ✅ Redis 캐싱
- ✅ 성능 벤치마크
11. 핵심 파일 구조
backend/
├─ migration/
│ ├─ migrate_to_postgres.py # SQLite → PostgreSQL
│ ├─ build_graph.py # 그래프 노드 생성
│ └─ integrate_pubmed.py # PubMed 근거 통합
├─ services/
│ ├─ graphrag_service.py # GraphRAG 추천 로직
│ ├─ ai_tagging.py # AI 카테고리 태깅
│ └─ category_service.py # 카테고리 관리
├─ api/
│ ├─ recommend.py # 추천 API
│ └─ categories.py # 카테고리 API
├─ db/
│ ├─ age_connector.py # Apache AGE 연결
│ └─ schema.sql # PostgreSQL 스키마
└─ pubmed_search.py # PubMed 검색 (재사용)
12. 예상 효과
비즈니스 가치
- 업셀링 증가: 복합제 추천으로 객단가 +50%
- 고객 신뢰: 논문 근거 제시로 재방문율 +30%
- 전문성 강화: 약국 브랜드 이미지 향상
기술적 이점
- 확장성: 수만 개 제품 처리 가능
- 유연성: 새 관계 타입 쉽게 추가
- 추론 가능: 다단계 복합 쿼리
차별화
- 타 약국 대비 과학적 근거 기반 추천
- AI + GraphRAG 결합한 최초 약국 시스템
13. 리스크 및 대응
| 리스크 | 대응 방안 |
|---|---|
| PostgreSQL 학습 곡선 | 단계적 마이그레이션, SQLite 병렬 운영 |
| Apache AGE 초기 버전 | 핵심 기능만 사용, SQL Fallback |
| PubMed API 제한 | API 키 발급, 캐싱, 배치 처리 |
| AI 비용 | GPT-4o-mini 사용, 결과 캐싱 |
14. 다음 단계
즉시 시작 (이번 주)
- PostgreSQL 15 + AGE 설치 테스트
- 샘플 그래프 생성 (10개 제품)
- 기본 Cypher 쿼리 실습
다음 주
- SQLite → PostgreSQL 마이그레이션 스크립트
- PubMed 100개 논문 수집
/api/recommend프로토타입
다음 달
- 전체 시스템 통합
- 웹앱 UI 추가
- 성능 최적화
작성자: Claude Sonnet 4.5 검토 필요 사항:
- PostgreSQL 서버 사양 확인
- PubMed API 키 발급
- 카테고리 계층 최종 승인