헤르메스(Hermes) 명리학 에이전트 — 3대 자료 계통을 근거로 스스로 검증하는 LangGraph 파이프라인 구축기 (큰그림 확정본 v2.0)

소개 - 시도하고자 했던 것과 그 이유

38년의 IT·공직 경험과 10년의 명리학 연구를 결합해 온 한바둑 MegaAI 프로젝트에서, 저는 오래 미뤄 온 한 가지를 시작했습니다.

탈XX 선구자의 4관법 저작 PPT와 박청화 강의 자료를 근거로, 헤르메스(Hermes)라 이름 붙인 명리학 에이전트를 만드는 것. 이것이 남은 여생의 꿈입니다.

문제의식은 단순합니다. 지금까지 축적한 지식(gwanbeop_ppt 누적 9,733건 이상, 박청화 시리즈 다수 등재 완료)은 훌륭한 "재료"지만, LLM에게 그냥 질문을 던지면 세 가지 병이 생깁니다.

첫째, 계통 오염입니다. 상리철학(象理哲學) 계통의 우주변화 논리와, 4관법의 실전 통변, 박청화의 직업론이 한 답변 안에서 뒤섞입니다.

둘째, 근거 없는 단정입니다. LLM은 그럴듯하게 지어냅니다. 특히 격국·용신을 처방형으로 단정("용신은 OO")하는 순간, 4관법의 관점과 충돌합니다.

셋째, 환각을 사후에야 발견하는 구조입니다. 사람이 매번 검수해야 한다면 에이전트라 부를 수 없습니다.

그래서 목표를 이렇게 정했습니다. "스스로 근거(slide 번호)를 대지 못하면 답하지 않는" 에이전트. 지피터스 헤르메스반에서 배운 Agent Harness 개념을 골격으로 삼았고, 이 골격을 스킬 3계층(규율 / 판단 / 조립)으로 다시 정리했습니다.

이 큰그림본과 12편 시리즈의 관계: 본 글은 헤르메스 전체 아키텍처를 한 장으로 보여주는 큰그림본입니다. 이 아키텍처를 23기 커리큘럼 순서(WEEK1 Skill → WEEK2 엄브렐러 → WEEK3 Harness → WEEK4 Growth Loop)에 정렬해 12편의 순차 사례글로 쪼갠 것이 별도 로드맵입니다.

다양한 한국어 유형을 보여주는 다이어그램

진행 방법 - 어떤 도구를 어떻게 활용했나

3-1. 사용 스택

계층

도구

오케스트레이션

LangGraph (기존 11노드 + 헤르메스 6노드)

지식 검색

Dify RAG (hybrid_search)

추론

Claude Opus 4.5 API (claude-opus-4-5-20251101)

저장소

PostgreSQL (hanbadook_production)

서버

DigitalOcean (152.42.240.248)

다양한 유형의 기술 스택을 보여주는 다이어그램

3-2. 큰 그림 — 3대 자료 계통을 색으로 못 박다

먼저 아키텍처 전체를 한 장으로 시각화했습니다. 핵심은 3대 자료 계통을 절대 섞지 않는 것이고, 역법의원리분석(이은성)과 우주변화의원리(한동석)를 상리철학 계통(③)으로 분류했습니다.

계통

source 예시

대표 자료

① 탈XX 4관법

gwanbeop_ppt

4관법 PPT 정리본

② 박청화 강의

박청화_운의해석 등

운의해석·정진반·제트엔진·청화비전 등

③ 상리철학(象理哲學)

sangni_*

역법의원리분석·우주변화의원리, 조명언·김동화

현재 등재 상태(계획값 — 게시 전 COUNT 확정 대상)

  • 운의해석 4편 460섹션: 春(6001~6119)·冬(6201~6335)·夏(6401~6481)·秋(6601~6725)

  • 정진반 上下 49강 196섹션: 上(7001~7098), 下(9636~9733, 2026-06-15 신규 등재)

  • 제트엔진 上中下 등재 완료(slide 7001~7630)

  • RAG 시맨틱 유사도 0.5395(목표 0.80), Dify 활성 문서 ~84건

3-3. 상태 그래프 노드 설계 (핵심 구현) — 스킬 3계층 매핑

Agent Harness의 본령은 "한 프롬프트에 다 밀어넣지 않고, 노드마다 단일 책임을 주는 것"입니다. 6개 노드로 나누고, 각 노드를 스킬 3계층으로 분류했습니다.

노드

책임

fail 조건

스킬 계층

N1 명식 파싱

사주 4주 확정 + 질의 분해

명식 불완전 → 중단

판단

N2 계통 라우팅

source 메타 필터 강제

계통 미지정 → 중단

판단

N3 RAG 검색

계통별 병렬 검색, slide 근거 회수

근거 0건 → 재검색

판단

N4 GuardrailAgent

문맥 기반 차단

처방형 단정 감지 → 차단

규율

N5 통변 합성

근거 인용 필수 스키마로 합성

인용 누락 → N6에서 반려

조립

N6 검증

fail-closed 최종 게이트

근거 미달 → 답변 차단·재검색

규율

세 계층의 역할: 판단층(N1·N2·N3)은 근거를 갖고 처리하되 "근거불충분 탈출구"를 반드시 두고, 규율층(N4·N6)은 금기어·근거 강제를 부탁이 아니라 코드로 보장하며, 조립층(N5 및 그래프 조립)은 하위 스킬을 재작성하지 않고 호출로만 엮습니다.

GuardrailAgent 설계가 이 프로젝트의 신뢰성을 좌우합니다. 핵심 전환은 "무조건 차단 → 문맥 기반 차단"이며, 현재 정밀화 착수 가능 상태입니다.

  • 차단: 격국·용신·기신·희신을 처방형으로 단정하는 출력("당신의 용신은 OO입니다")

  • 허용: 희기동소(喜忌同所), 격청격탁, 재정립·비교 맥락의 언급

  • 판단 전거: 박청화 신사주학 春夏秋冬 통합본 §3.4

3-4. 상태 정의 코드 (LangGraph State)

python

from typing import TypedDict, Literal, Optional
from langgraph.graph import StateGraph, END

# 3대 자료 계통 - 절대 혼용 금지
Lineage = Literal["sangni", "gwanbeop", "parkcheonghwa"]

class HermesState(TypedDict):
    # 입력
    saju: dict            # 시주|일주|월주|연주 (오른쪽→왼쪽)
    question: str
    # 라우팅
    lineage: Optional[Lineage]        # N2가 확정
    # 검색 근거 (slide 번호 필수)
    evidence: list[dict]              # [{"source":..., "slide":..., "text":...}]
    # 합성 결과
    draft: Optional[str]
    # 검증
    guardrail_flag: Optional[str]     # 처방형 단정 감지 시 사유
    verified: bool                    # N6 통과 여부
    retry_count: int                  # 3회 실패 시 멈춤 (반성문 원칙 1)

def n2_route_lineage(state: HermesState) -> HermesState:
    """source 메타 필터를 강제로 확정. 미지정이면 중단. (판단층)"""
    q = state["question"]
    if any(k in q for k in ["우주변화", "역법", "황경", "절기 원리"]):
        state["lineage"] = "sangni"          # 상리철학 계통
    elif any(k in q for k in ["직업", "운의 해석", "정진반"]):
        state["lineage"] = "parkcheonghwa"
    else:
        state["lineage"] = "gwanbeop"        # 4관법 기본
    return state

GUARD_BLOCK = ["격국", "용신", "기신", "희신"]
GUARD_ALLOW_CONTEXT = ["희기동소", "격청격탁", "재정립", "비교", "관점"]

def n4_guardrail(state: HermesState) -> HermesState:
    """문맥 기반 차단: 처방형 단정만 차단, 희기동소 등은 허용. (규율층)"""
    draft = state.get("draft", "")
    for term in GUARD_BLOCK:
        # 처방형 단정 패턴: "용신은 OO" / "OO이 용신"
        if f"{term}은" in draft or f"{term}이" in draft:
            if any(ctx in draft for ctx in GUARD_ALLOW_CONTEXT):
                continue                      # 허용 맥락이면 통과
            state["guardrail_flag"] = f"처방형 단정 감지: {term}"
            return state
    state["guardrail_flag"] = None
    return state

def n6_verify(state: HermesState) -> HermesState:
    """fail-closed: 근거(slide) 없으면 답변 차단. (규율층)"""
    if not state["evidence"]:
        state["verified"] = False
    elif not all("slide" in e for e in state["evidence"]):
        state["verified"] = False
    elif state.get("guardrail_flag"):
        state["verified"] = False
    else:
        state["verified"] = True
    return state

def route_after_verify(state: HermesState) -> Literal["retry", "output"]:
    if state["verified"]:
        return "output"
    if state["retry_count"] >= 3:            # 반성문 원칙: 3회 실패 시 멈춤
        return "output"                       # (사용자에게 "근거 부족" 고지 후 종료)
    state["retry_count"] += 1
    return "retry"

# 그래프 조립 (조립층 — 하위 스킬을 호출로만 엮는다)
g = StateGraph(HermesState)
g.add_node("N1_parse",  n1_parse_saju)
g.add_node("N2_route",  n2_route_lineage)
g.add_node("N3_rag",    n3_rag_search)     # 계통별 병렬 검색
g.add_node("N4_guard",  n4_guardrail)
g.add_node("N5_synth",  n5_synthesize)
g.add_node("N6_verify", n6_verify)

g.set_entry_point("N1_parse")
g.add_edge("N1_parse", "N2_route")
g.add_edge("N2_route", "N3_rag")
g.add_edge("N3_rag",   "N5_synth")   # 합성 먼저
g.add_edge("N5_synth", "N4_guard")   # 합성문에 대해 가드레일
g.add_edge("N4_guard", "N6_verify")
g.add_conditional_edges("N6_verify", route_after_verify, {
    "retry":  "N3_rag",   # 재검색 루프
    "output": END,
})
app = g.compile()

N1 결정적 처리부: 명식 파싱의 8글자 검증·2글자 분할·표기 순서 뒤집기(時|日|月|年)는 W1 과제로 만든 myeongsik-normalizer 스킬(v0.2.0, Hermes native)이 담당합니다. apply gate는 Hermes 미설치로 현재 hold 상태입니다.

3-5. RAG 검색 시 계통 필터 강제 (SQL)

DB에 데이터가 있으므로 파일 업로드 없이 직접 조회하는 방식을 택했습니다. 계통 혼용을 막는 종합 쿼리입니다.

sql

-- 상리철학 계통만 조회 (역법·우주변화 분류 반영)
SELECT source, slide, content
FROM gwanbeop_ppt
WHERE source IN ('역법의원리분석', '우주변화의원리', '상리철학_조명언', '상리철학_김동화')
  AND content IS NOT NULL              -- 스텁(빈칸) 배제
  AND char_length(content) > 0
ORDER BY source, slide;

-- 계통별 실제 등재 건수 검증 (문서 아닌 사실 확인)
SELECT
  CASE
    WHEN source LIKE '박청화%' THEN '② 박청화'
    WHEN source IN ('역법의원리분석','우주변화의원리') THEN '③ 상리철학'
    ELSE '① 4관법'
  END AS lineage,
  COUNT(*) AS cnt
FROM gwanbeop_ppt
WHERE content IS NOT NULL AND char_length(content) > 0
GROUP BY 1
ORDER BY 1;

3-6. 실제 사용한 프롬프트 전문 (N5 통변 합성 노드)

아래는 Claude Opus 4.5 API에 넘긴 시스템 프롬프트 전문입니다.

text

당신은 한바둑 헤르메스 명리학 에이전트의 통변 합성기입니다.

[절대 규칙]
1. 아래 <evidence>에 주어진 근거만 사용한다.
   근거에 없는 내용은 절대 지어내지 않는다.
2. 모든 통변 문장 끝에 근거 slide 번호를 [source:slide] 형식으로 반드시 표기한다.
   근거를 댈 수 없는 문장은 아예 쓰지 않는다.
3. 3대 자료 계통을 섞지 않는다. 이번 질의의 계통은 {lineage} 이다.
   다른 계통의 논리를 끌어오지 않는다.
4. 격국·용신·기신·희신을 처방형으로 단정하지 않는다("용신은 OO입니다" 금지).
   단, 희기동소·격청격탁·재정립·비교 맥락의 언급은 허용한다.
5. 사주 표기는 시주|일주|월주|연주 순서(오른쪽→왼쪽)를 지킨다.
6. 모르면 "근거가 부족하다"고 밝힌다. 아는 척하지 않는다.

[출력 형식]
- 각 문단: 통변 내용 + [source:slide]
- 마지막 줄: 사용한 근거 slide 목록

<saju>{saju}</saju>
<lineage>{lineage}</lineage>
<question>{question}</question>
<evidence>{evidence}</evidence>

(활용 이미지 자리 — LangGraph 실행 로그 캡처 및 아키텍처 다이어그램 이미지를 삽입하세요.)

결과와 배운 점

배운 점과 꿀팁

꿀팁 1 — 합성보다 검증 노드를 먼저 설계하라. 처음엔 "잘 답하는 프롬프트"에 매달렸습니다. 그런데 헤르메스의 신뢰성을 만든 건 N6 검증 노드였습니다. 근거 slide가 없으면 답을 막는 fail-closed 구조 하나가, 프롬프트 열 번 손보는 것보다 환각을 줄였습니다. 이것이 규율층의 핵심입니다 — 규율은 부탁이 아니라 코드로 보장합니다.

꿀팁 2 — 가드레일은 단어가 아니라 문맥으로 막아라. "용신"이라는 단어를 무조건 차단했더니, 정작 필요한 "희기동소" 설명까지 막혔습니다(과잉 차단). 처방형 단정만 차단하고 비교·재정립 맥락은 허용하도록 §3.4 전거에 맞춰 조건을 바꾼 뒤에야 쓸 만해졌습니다.

꿀팁 3 — 문서의 숫자를 믿지 말고 COUNT(*)를 믿어라. 로드맵상 누적 건수와 실제 DB 건수가 어긋난 적이 있습니다. 그 뒤로는 INSERT 실행을 서버에서 확인하기 전엔 누적 건수를 갱신하지 않습니다.

시행착오

  • 계통 라우팅 누락: N2 없이 바로 검색하니 상리철학과 4관법이 한 답변에 섞였습니다. → 라우팅을 첫 관문으로 강제.

  • 스텁 데이터 오염: content가 빈칸인 등재분(무엇이든물어보세요 108강 스텁 등)이 근거로 잡혔습니다. → 검색 쿼리에서 content IS NOT NULL 강제 배제.

  • 무한 재검색: 근거가 없을 때 계속 재검색을 돌았습니다. → 3회 실패 시 멈추고 "근거 부족" 고지(반성문 원칙).

도움이 필요한 부분

  • N4 가드레일의 "처방형 단정" 판별을 단순 문자열 매칭에서 문맥 분류기(소형 LLM)로 고도화하는 방법

  • 무엇이든물어보세요 108강 스텁 content 채우기(서버 UPDATE 대기 중) 후 재색인 전략


< 앞으로의 계획 >

  • N4 GuardrailAgent 문맥 기반 차단 정식 구현 (박청화 §3.4 근거) — 최우선 착수

  • 무엇이든물어보세요 108강 스텁 content UPDATE 및 재색인

  • 로드투프로 8~28강 RAG/SQL 등재 (server-side slide 범위 점유 확인 후)

  • 우주변화의원리·역법원리 상리철학 계통 재색인 검증 (SELECT COUNT(*))

  • LangGraph Phase 10 스트리밍 파이프라인(Rails SSE)에 헤르메스 6노드 통합

  • 최종 목표: UNESCO 디지털 문화유산 등재(2027) 및 POD 출판 — 헤르메스 출력이 등재 서류 규격으로 바로 흐르도록 표준화

도움 받은 글 (옵션)

  • 지피터스 헤르메스반 Agent Harness 사례글 (지아코모 제공 1주차 pptx)

  • 박청화 신사주학 春夏秋冬 통합본 §3.4 (가드레일 전거)

  • LangGraph 공식 문서 (StateGraph, conditional_edges)

9
11개의 답글
밀어주고 끌어주는

온·오프라인 AI 스터디

AI로 어디까지 할 수 있는지
직접 확인하실 분만 신청하세요.