Law-GPT

황연준·2025년 4월 10일

SKALA

목록 보기
2/5

LangGraph 기반 Law-GPT 프로젝트⚖️

생성형 AI를 법률 분야에 활용하기 위한 실험으로, LangGraph와 Pinecone, OpenAI API, SentenceTransformer 등을 조합하여 한국어 법률 조언 에이전트 파이프라인을 구축했습니다.


💡 프로젝트 개요

목표

  • 사용자가 자연어로 법률 고민을 입력하면,
  • 법률 문제의 유형 분류 → 유사한 법률 조항 및 승소 사례 검색 → 법률 조언 생성 → 승소 사례 기반 평가
  • 최종적으로 신뢰 가능한 한국어 법률 조언을 생성하는 파이프라인 구축

🛠 사용 기술

  • LangGraph – 멀티에이전트 흐름 제어
  • OpenAI GPT-4 / GPT-4o – 분류, 생성, 평가
  • SentenceTransformer – 한국어 임베딩 모델 (jhgan/ko-sroberta-multitask)
  • Pinecone – 벡터 DB로 법률 문서/사례 저장
  • Tavily – 법률 도메인에 한정된 실시간 웹 검색

시스템 구성 흐름


LangGraph 구성

LangGraph를 통해 각 에이전트를 node로 등록하고, 그 사이 흐름을 edge로 연결했습니다.

노드 (Node) 등록

g.add_node("filter", filter_agent)
g.add_node("retrieve", retrieve_ctx)
g.add_node("lawyer", lawyer_agent)
g.add_node("judge", judge_agent)

간선 (Edge) 구성

g.set_entry_point("filter")
g.add_edge("filter", "retrieve")
g.add_edge("retrieve", "lawyer")
g.add_edge("lawyer", "judge")
g.add_conditional_edges("judge", route, {
    "lawyer": "lawyer",  # 점수가 낮으면 다시 lawyer로 되돌림
    END: END              # 점수 통과 시 종료
})

⚙️ 분기 조건 함수

def route(state: LegalState) -> str:
    if state.score >= 80 or state.retry >= MAX_RETRY:
        return END
    state.retry += 1
    return "lawyer"

핵심 코드

SentenceTransformer 기반 검색

model = SentenceTransformer("jhgan/ko-sroberta-multitask")

def query_top_k(text: str, namespace: str, k: int):
    vector = model.encode(text).tolist()
    result = index.query(vector=vector, top_k=k, include_metadata=True, namespace=namespace)
    return [match["metadata"]["text"] for match in result["matches"]]

📂 에이전트 상태 정의

@dataclass
class LegalState:
    question: str
    category: str = "privacy"
    ctx_texts: List[str] = field(default_factory=list)
    advice: str = ""
    score: int = 0
    feedback: str = ""
    retry: int = 0

🛠️ 실행 예시 (with Gradio)


Trouble Shooting

langgraph에서 나오는 "recursive 25 limit" 오류는 LangGraph 내부에서 재귀적으로 노드(예: agent, 상태 등) 를 실행하는 과정이 최대 25번까지만 허용되기 때문에 발생하는 오류입니다.


왜 이 제한이 있는가?

LangGraph는 상태 기반 흐름을 순차적으로 따라가며 각 노드를 실행합니다.

하지만 특정 조건에서 루프(loop) 또는 재귀적인 분기가 설정되어 있을 경우, 실수로 무한 루프에 빠질 수 있습니다.

이를 방지하기 위해 LangGraph는 다음과 같은 제한을 둡니다:

  • 한 번의 실행에서 노드가 재귀적으로 호출되는 횟수: 최대 25회

📌 예시

python
복사편집
def route(state: LegalState) -> str:
    if state.score >= 80:
        return END
    return "lawyer"  # 다시 lawyer로 루프

이런 구조는 judge -> lawyer -> judge -> lawyer ... 순환을 만드는데, 점수가 계속 80 미만이면 25번까지 반복하다가 오류 발생:


RuntimeError: Recursive execution limit (25) reached.

해결 방법

  1. 재귀 루프를 적절히 제어하는 조건 추가
    • 예를 들어 MAX_RETRY를 설정하고 이를 기반으로 루프 중단:

MAX_RETRY = 2

def route(state: LegalState) -> str:
    if state.score is None:
        return "lawyer"
    if state.score >= 80 or state.retry >= MAX_RETRY:
        return END
    state.retry += 1
    return "lawyer"
  1. LangGraph 내에서 루프를 쓸 경우 retry를 명시적으로 제한

    이미 retry 필드를 두신 건 매우 좋은 구조예요! state.retry >= MAX_RETRY 조건은 반드시 넣어주세요.


🔗 관련 기술 참고:

0개의 댓글