tags: [ideas, pydantic-ai, langgraph, llm, structured-output, ir-analysis]

# Pydantic AI 도입 기반 LLM 출력 안정화 아이디어

## 아이디어 한 줄
- `LangGraph`는 유지하고, 핵심 구조화 출력 경로에는 우선 `Pydantic` 기반 typed validation을 도입하고, 필요 시 다음 단계에서 `Pydantic AI`까지 확장하자는 아이디어입니다.

## 왜 이 아이디어를 떠올렸는가
- 현재 일부 평가 경로는 LLM이 반환한 구조화 결과를 거의 그대로 신뢰하고 있습니다.
- 오늘 IR Deck 분석에서는 회사소개서 자체는 제대로 선택됐지만, LLM이 `total_score=100`, `grade=B`처럼 서로 맞지 않는 값을 함께 반환했고, 이 값이 그대로 사용자에게 노출됐습니다.
- 그래서 지금 필요한 것은 워크플로우를 갈아엎는 것보다, `Pydantic` 계열 typed output 계층을 붙여 출력 계약을 더 강하게 만드는 방향이라고 봤습니다.

## 이 아이디어가 겨냥하는 현재 상태
- 지금 구조에서는 LLM이 JSON 비슷한 출력을 하면 파싱 후 일부 필드만 범위 제한하고 저장합니다.
- 그 결과:
  - 점수와 등급의 정합성이 깨져도 통과할 수 있습니다.
  - `story_scores` 평균과 `total_score`가 맞지 않아도 그대로 저장될 수 있습니다.
  - 사용자 메시지, DB 저장, 후속 의사결정이 모두 흔들릴 수 있습니다.
- 즉 현재 문제는 "LLM이 들쭉날쭉하다"보다, "들쭉날쭉한 출력을 막는 typed validation 계층이 약하다"에 가깝습니다.

## 핵심 아이디어
- `LangGraph`는 유지하되, LLM 출력이 중요한 구간에는 `Pydantic` 기반 typed validation 계층을 먼저 부분 도입합니다.
- 이후 retry, output validator, agent화가 더 필요해지면 `Pydantic AI`로 확장할 수 있게 경계를 잡습니다.
- 목표는 워크플로우를 갈아엎는 것이 아니라, **LLM이 반환하는 평가/분류/판정 결과를 검증 가능한 모델로 강제**하는 것입니다.
- 즉 이 아이디어의 중심 문장은 `Pydantic 계열 typed validation을 안정화 계층으로 도입하자`입니다.

## 왜 하필 Pydantic 계열인가

### 1. 지금 문제는 워크플로우보다 출력 계약 문제다
- 콜드메일처럼 `중단/재개`, `체크포인트`, `사람 확인 후 계속 진행`이 필요한 경로는 여전히 LangGraph가 잘 맞습니다.
- 하지만 IR 평가처럼 "점수/등급/요약/추천"을 구조화해서 내야 하는 경로는 LangGraph보다 출력 모델 검증이 더 중요합니다.

### 2. LangGraph는 괜찮지만, 복잡한 지점이 분명히 있다
- 장점:
  - 상태 저장
  - interrupt / resume
  - 장기 실행 흐름
  - 사람 확인 후 재개 같은 운영 흐름
- 복잡한 점:
  - 단순 구조화 응답 문제까지 워크플로우 문제처럼 보이게 만들 수 있습니다.
  - 출력 검증이 약하면, 그래프는 잘 돌아도 잘못된 값이 오래 살아남습니다.
- 따라서 지금 문제를 보고 `LangGraph가 나쁘다`고 결론내리는 것은 과도합니다.
- 더 정확한 해석은 `LangGraph는 유지할 가치가 있지만, typed output 안정화 계층이 별도로 필요하다`입니다.

## Pydantic 계열을 쓰면 기대할 수 있는 것

### 1. 출력 모델 강제
- 예: `IRDeckEvaluationResult` 같은 모델로 아래를 강제할 수 있습니다.
  - `total_score: int`
  - `grade: Literal["S", "A", "B", "C"]`
  - `story_scores: list[...]`
  - `summary: str`
  - `investment_opinion: ...`
- 구조가 맞지 않으면 바로 실패시킬 수 있습니다.

### 2. 후처리 검증을 명시적으로 둘 수 있음
- 예:
  - `total_score`와 `grade` 정합성 검증
  - `story_scores` 평균과 `total_score` 차이 제한
  - 필수 필드 길이/개수 검증
- 즉 "파싱만 성공하면 통과"가 아니라 "의미적으로도 맞아야 통과"가 가능합니다.

### 3. 실패를 성공처럼 포장하지 않기 쉬움
- 지금처럼 `100점인데 B등급` 같은 모순을 조용히 저장하는 대신,
  - 재질의
  - 재계산
  - 실패 가시화
  중 하나로 강제할 수 있습니다.

## 이 아이디어의 권장 방향

### 1. LangGraph 전면 교체는 하지 않는다
- 콜드메일, 브리핑, 인터럽트 워크플로우는 LangGraph가 계속 필요합니다.
- 장기 상태/체크포인트/사람 확인 흐름은 LangGraph의 실제 강점입니다.

### 2. 1차는 `Pydantic-only`, 2차 후보는 `Pydantic AI`로 둔다
- 우선 후보:
  - IR Deck 종합 평가 출력
  - 브리핑 인사이트 한 줄 출력
  - 콜드메일 후보 판정 이유 요약
  - 투자 의견 구조화 출력
- 즉 LLM이 말만 잘하면 되는 경로보다, **출력값이 제품 데이터가 되는 경로**에 먼저 붙입니다.
- 첫 단계는 기존 `call_llm()` 뒤에 `Pydantic model_validate()`와 semantic validator를 붙이는 방식이 가장 현실적입니다.
- 이후 재질의, output validator, retry를 경로 내부에 더 강하게 묶고 싶을 때 `Pydantic AI`로 확장합니다.

### 3. 점수는 LLM에게 전부 맡기지 않는다
- 이상적인 방향은:
  - LLM은 `story_scores`, 요약, 강점/약점 같은 해석을 반환
  - `total_score`, `grade`, `recommendation` 일부는 서버가 재계산 또는 재검증
- 이렇게 하면 LLM의 자유도는 유지하면서도 최종 사용자 값은 더 안정화할 수 있습니다.

## 이 아이디어가 답하려는 질문
1. `Pydantic-only`만으로도 현재 모순값 차단을 시작할 수 있는가?
2. `LangGraph`는 유지하면서 `Pydantic` 계열로 출력 안정화 계층만 강화할 수 있는가?
3. `Pydantic-only`로 시작한 뒤 필요하면 `Pydantic AI`로 확장하는 순서가 맞는가?

## 아직 아이디어 단계인 이유
- 실제로 `Pydantic-only`와 `Pydantic AI`의 경계를 어디까지 둘지 범위가 정해지지 않았습니다.
- 기존 FastAPI/Pydantic 모델과 어떤 경계로 겹칠지 설계가 필요합니다.
- 검증 실패 시 재질의, 서버 재계산, 실패 노출 중 어떤 정책을 기본으로 할지 아직 정하지 않았습니다.
- 비용과 지연 시간도 실제 경로에서 측정이 필요합니다.

## 바로 실행 결론으로 넘기지 않은 이유
- 이번 문서는 `Pydantic 계열 typed validation을 부분 도입하자`는 방향을 여는 아이디어 문서입니다.
- 다만 아이디어 단계에서는 `도입 범위`, `도입 경계`, `실패 정책`이 아직 열려 있으므로 바로 실행 결론으로 넘기지 않았습니다.
- 실제 계획에서는 `어느 경로부터`, `어떤 필드부터`, `어떤 실패 정책으로` 도입할지를 좁혀야 합니다.

## 한 줄 결론
- 방향은 `LangGraph 유지 + Pydantic-only 먼저`입니다. 현재 출력 검증이 약한 경로에 typed validation 계층을 먼저 붙이고, 필요하면 다음 단계에서 `Pydantic AI`로 확장하는 것이 이 아이디어의 핵심입니다.
