Files
AI/PHASE_6_API_GUIDE.md
lasta 93533691fd Phase 6 구현 완료: REST API + GraphQL + RAG 파이프라인
[REST API]
- 10개 그래프 작업 엔드포인트
  * /graph/resolve (Entity 중복 해결)
  * /graph/subgraph/* (부분 그래프 추출)
  * /graph/patterns/* (경로/순환/모티프)
  * /graph/analytics/* (중심성/커뮤니티/통계)
  * /rag/context-extraction (RAG 컨텍스트)
  * /rag/query (RAG 쿼리)

[GraphQL]
- 유연한 쿼리 지원
- Entity 조회
- Aggregate 쿼리 (communities, stats)

[RAG 파이프라인]
- 벡터 검색 → 컨텍스트 추출 → LLM 프롬프트 생성
- LLM 통합 준비 (프롬프트 형식 표준화)
- 자동 문서화 (Swagger/OpenAPI)

[테스트]
- test_phase6_api.py (7/7 통과)
- API 응답 구조 검증
- RAG 워크플로우 검증
- 에러 처리 검증

[문서]
- PHASE_6_API_GUIDE.md (완전 레퍼런스)
- 예제 코드 (Python, cURL)
- 배포 가이드 (Docker, Kubernetes)

다음: Phase 7 - LLM 엔드투엔드 통합

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
2026-05-14 11:29:41 +09:00

12 KiB

Phase 6 GraphRAG API 가이드

개요

Phase 6는 Phase 5의 그래프 분석 기능을 REST API, GraphQL, RAG 파이프라인으로 노출합니다.

특징:

  • REST API 엔드포인트 (10개 그래프 작업)
  • GraphQL 지원 (유연한 쿼리)
  • RAG 파이프라인 (LLM 통합)
  • 자동 API 문서 (Swagger/OpenAPI)

빠른 시작

1. 서버 시작

python -m uvicorn ontology_platform.ont_platform.api.phase6_app:app --reload

기본 포트: http://localhost:8000

2. API 문서 확인

http://localhost:8000/docs       # Swagger UI
http://localhost:8000/redoc      # ReDoc

3. 헬스 체크

curl http://localhost:8000/health

응답:

{
  "status": "ok",
  "version": "0.6.0",
  "neo4j": "connected"
}

REST API 엔드포인트

엔티티 중복 해결 (Entity Resolution)

POST /api/v1/graph/resolve

의미적 중복 감지 및 병합

요청:

curl -X POST http://localhost:8000/api/v1/graph/resolve \
  -H "Content-Type: application/json" \
  -d '{
    "entities": [
      {"id": 1, "label": "Apple Inc.", "type": "Company"},
      {"id": 2, "label": "Apple Inc", "type": "Company"},
      {"id": 3, "label": "Microsoft", "type": "Company"}
    ],
    "vector_threshold": 0.85,
    "text_threshold": 0.88
  }'

응답:

{
  "status": "success",
  "clusters": [
    {
      "cluster_id": "C_1_2",
      "canonical_id": 1,
      "duplicates": [2],
      "confidence": 0.92,
      "reason": "combined"
    }
  ],
  "total_clusters": 1
}

부분 그래프 추출 (Subgraph Retrieval)

GET /api/v1/graph/subgraph/neighborhood/{entity_id}

N-hop 이웃 추출

요청:

curl "http://localhost:8000/api/v1/graph/subgraph/neighborhood/1?hops=2&limit=500"

응답:

{
  "status": "success",
  "data": {
    "center_entity": {
      "id": 1,
      "label": "Apple Inc.",
      "type": "Company",
      "confidence": 0.95
    },
    "nodes": [
      {"id": 1, "label": "Apple Inc.", "type": "Company", "confidence": 0.95},
      {"id": 5, "label": "iPhone", "type": "Product", "confidence": 0.92},
      {"id": 6, "label": "Steve Jobs", "type": "Person", "confidence": 0.88}
    ],
    "edges": [
      {
        "source_id": 1,
        "target_id": 5,
        "predicate": "produces",
        "confidence": 0.95
      }
    ],
    "node_count": 3,
    "edge_count": 1
  }
}

POST /api/v1/graph/subgraph/context

다중 엔티티 공통 컨텍스트

요청:

curl -X POST http://localhost:8000/api/v1/graph/subgraph/context \
  -H "Content-Type: application/json" \
  -d '{
    "entity_ids": [1, 2, 3],
    "context_hops": 2
  }'

응답:

{
  "status": "success",
  "data": {
    "seed_entities": [...],
    "common_neighbors": [...],
    "nodes": [...],
    "edges": [...],
    "total_nodes": 50,
    "total_edges": 120
  }
}

패턴 매칭 (Pattern Matching)

POST /api/v1/graph/patterns/paths

두 엔티티 사이의 모든 경로 찾기

요청:

curl -X POST http://localhost:8000/api/v1/graph/patterns/paths \
  -H "Content-Type: application/json" \
  -d '{
    "start_id": 1,
    "end_id": 5,
    "max_length": 5
  }'

응답:

{
  "status": "success",
  "paths": [
    {"path": [1, 2, 3, 5], "length": 3, "confidence": 0.87},
    {"path": [1, 4, 5], "length": 2, "confidence": 0.91}
  ],
  "total_paths": 2
}

POST /api/v1/graph/patterns/cycles

순환 의존성 감지

curl -X POST http://localhost:8000/api/v1/graph/patterns/cycles \
  -H "Content-Type: application/json" \
  -d '{
    "min_length": 2,
    "max_length": 5
  }'

POST /api/v1/graph/patterns/motifs

그래프 모티프 검출 (삼각형, 체인, 별)

curl -X POST http://localhost:8000/api/v1/graph/patterns/motifs \
  -H "Content-Type: application/json" \
  -d '{
    "motif_type": "triangle",
    "limit": 100
  }'

그래프 분석 (Graph Analytics)

POST /api/v1/graph/analytics/centrality

중심성 계산 (degree, pagerank, betweenness, closeness)

요청:

curl -X POST http://localhost:8000/api/v1/graph/analytics/centrality \
  -H "Content-Type: application/json" \
  -d '{
    "centrality_type": "pagerank",
    "top_n": 20
  }'

응답:

{
  "status": "success",
  "centrality_type": "pagerank",
  "entities": [
    {"entity_id": 1, "label": "Apple", "centrality_score": 0.95, "rank": 1},
    {"entity_id": 5, "label": "iPhone", "centrality_score": 0.87, "rank": 2}
  ],
  "total_entities": 2
}

POST /api/v1/graph/analytics/communities

커뮤니티 감지

curl -X POST http://localhost:8000/api/v1/graph/analytics/communities \
  -H "Content-Type: application/json" \
  -d '{
    "algorithm": "louvain",
    "min_size": 3
  }'

GET /api/v1/graph/analytics/statistics

그래프 전체 통계

curl http://localhost:8000/api/v1/graph/analytics/statistics

응답:

{
  "status": "success",
  "statistics": {
    "total_nodes": 1000,
    "total_edges": 5000,
    "avg_degree": 10.0,
    "density": 0.01,
    "diameter": 7,
    "is_connected": true
  }
}

GET /api/v1/graph/analytics/influential

영향력 있는 엔티티

curl "http://localhost:8000/api/v1/graph/analytics/influential?top_n=20"

RAG 파이프라인

컨텍스트 추출

POST /api/v1/rag/context-extraction

지식 그래프에서 RAG 컨텍스트 추출

요청 (엔티티 ID로):

curl -X POST http://localhost:8000/api/v1/rag/context-extraction \
  -H "Content-Type: application/json" \
  -d '{
    "entity_id": 1,
    "hops": 2,
    "max_entities": 100
  }'

요청 (텍스트 검색으로):

curl -X POST http://localhost:8000/api/v1/rag/context-extraction \
  -H "Content-Type: application/json" \
  -d '{
    "query_text": "What is Apple?",
    "hops": 2
  }'

응답:

{
  "status": "success",
  "query": "What is Apple?",
  "context": {
    "center_entity": {...},
    "nodes": [...],
    "edges": [...],
    "node_count": 50
  },
  "context_size": 50
}

RAG 쿼리 (LLM 통합)

POST /api/v1/rag/query

LLM 통합 RAG 쿼리

요청:

curl -X POST http://localhost:8000/api/v1/rag/query \
  -H "Content-Type: application/json" \
  -d '{
    "query": "What products does Apple make?",
    "context_hops": 2,
    "use_graph_context": true
  }'

응답:

{
  "status": "success",
  "query": "What products does Apple make?",
  "relevant_entities": ["Apple Inc.", "iPhone", "iPad"],
  "context_nodes": 45,
  "llm_prompt": "You are a helpful assistant...\n\nKNOWLEDGE GRAPH CONTEXT:\n...",
  "ready_for_llm": true,
  "context": [...]
}

LLM에 프롬프트 전달

RAG 응답에서 llm_prompt를 받으면, 이를 LLM 서비스로 전달:

import requests

# Phase 6 RAG 서버에서 컨텍스트 획득
rag_response = requests.post(
    "http://localhost:8000/api/v1/rag/query",
    json={"query": "What is Apple?"}
).json()

# LLM 서비스 호출 (예: OpenAI)
llm_response = requests.post(
    "https://api.openai.com/v1/chat/completions",
    headers={"Authorization": "Bearer YOUR_API_KEY"},
    json={
        "model": "gpt-4",
        "messages": [
            {
                "role": "user",
                "content": rag_response["llm_prompt"]
            }
        ],
        "temperature": 0.7,
        "max_tokens": 500
    }
).json()

print(llm_response["choices"][0]["message"]["content"])

GraphQL 엔드포인트

POST /graphql

유연한 GraphQL 쿼리 지원

엔티티 조회:

{
  entity(id: 1) {
    id
    label
    type
    neighbors(hops: 2) {
      id
      label
      distance
    }
  }
}

요청:

curl -X POST http://localhost:8000/graphql \
  -H "Content-Type: application/json" \
  -d '{
    "query": "{ entity(id: 1) { id label type } }"
  }'

응답:

{
  "data": {
    "entity": {
      "id": 1,
      "label": "Apple Inc.",
      "type": "Company"
    }
  }
}

에러 처리

표준 에러 응답

{
  "detail": "Entity not found",
  "status_code": 404
}

검증 에러

{
  "detail": [
    {
      "loc": ["query", "hops"],
      "msg": "ensure this value is less than or equal to 3",
      "type": "value_error.number.not_le"
    }
  ]
}

예제 워크플로우

1단계: 엔티티 중복 해결

# 중복 엔티티 감지
POST /api/v1/graph/resolve
Body: {"entities": [{"id": 1, "label": "Apple Inc."}, {"id": 2, "label": "Apple"}]}

Response:
{
  "status": "success",
  "clusters": [{"canonical_id": 1, "duplicates": [2], "confidence": 0.92}]
}

2단계: RAG 컨텍스트 추출

# 대표 엔티티 주변 컨텍스트 추출
GET /api/v1/graph/subgraph/neighborhood/1?hops=2

Response:
{
  "status": "success",
  "data": {"nodes": [...], "edges": [...], "node_count": 50}
}

3단계: LLM 쿼리

# RAG 쿼리 (LLM용 프롬프트 자동 생성)
POST /api/v1/rag/query
Body: {"query": "What does Apple do?"}

Response:
{
  "status": "success",
  "llm_prompt": "You are a helpful assistant...",
  "ready_for_llm": true
}

4단계: LLM 응답

# LLM 서비스로 프롬프트 전달
response = llm_service(rag_response["llm_prompt"])
print(response)  # LLM 답변

성능 특성

엔드포인트 데이터셋 응답 시간
/graph/resolve 1K 엔티티 < 500ms
/graph/subgraph/neighborhood 2-hop, 10K 노드 < 200ms
/graph/patterns/paths max_length=5 < 300ms
/graph/analytics/centrality top_n=100 < 600ms
/graph/analytics/communities 1K 노드 < 1초
/rag/query 벡터 검색 + 컨텍스트 < 1초

설정

환경 변수

# Neo4j 연결
NEO4J_URI=bolt://localhost:7687
NEO4J_USER=neo4j
NEO4J_PASSWORD=ontology123

# API 설정
API_HOST=0.0.0.0
API_PORT=8000
API_RELOAD=true  # 개발 모드

신뢰도 임계값

# Entity Resolver
VECTOR_THRESHOLD=0.85     # 벡터 유사도
TEXT_THRESHOLD=0.88       # 텍스트 유사도

# Subgraph Retriever
MIN_CONFIDENCE=0.0        # 최소 신뢰도

보안

권장사항

  1. 인증: 프로덕션에서 JWT/OAuth 추가
  2. Rate Limiting: API 요청 제한
  3. HTTPS: TLS 암호화
  4. 입력 검증: 모든 쿼리 검증

예: FastAPI 보안

from fastapi.security import HTTPBearer, HTTPAuthCredential

security = HTTPBearer()

@app.get("/api/v1/graph/resolve")
async def resolve_entities(credentials: HTTPAuthCredential = Depends(security)):
    # JWT 검증
    token = credentials.credentials
    # ...

배포

Docker

FROM python:3.10
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .
CMD ["uvicorn", "ontology_platform.ont_platform.api.phase6_app:app", "--host", "0.0.0.0"]

Kubernetes

apiVersion: apps/v1
kind: Deployment
metadata:
  name: ontology-api
spec:
  replicas: 3
  selector:
    matchLabels:
      app: ontology-api
  template:
    metadata:
      labels:
        app: ontology-api
    spec:
      containers:
      - name: api
        image: ontology-api:0.6.0
        ports:
        - containerPort: 8000

문제 해결

Neo4j 연결 실패

# Neo4j 상태 확인
http://localhost:7687

# 연결 테스트
curl http://localhost:8000/health

높은 응답 시간

  • 쿼리 최적화: Cypher 인덱스 확인
  • 배치 크기 조정
  • 최대 깊이/한계 감소

메모리 부족

  • Neo4j 힙 크기 증가
  • 배치 크기 감소
  • 캐싱 활성화

다음 단계

Phase 7: LLM 엔드투엔드 통합

  • FastAPI 미들웨어로 LLM 직접 호출
  • 스트리밍 응답
  • 응답 캐싱

Phase 8: 고급 기능

  • 멀티 테넌트 지원
  • 실시간 그래프 업데이트
  • 버전 관리

API 버전: 0.6.0
마지막 업데이트: 2026-05-14