docs: LangGraph 1.0 업그레이드 플랜 문서 완료 - archive로 이동
- 전체 완료 상태로 정리 (완료 섹션 삭제, troubleshooting 링크만 유지) - plans/archive/로 이동 (전체 완료 문서)
This commit is contained in:
parent
15df3c0ad4
commit
5e6be2d276
@ -1,214 +0,0 @@
|
|||||||
# LangGraph 1.0 업그레이드 계획
|
|
||||||
|
|
||||||
**날짜**: 2025-12-18
|
|
||||||
**수정일**: 2026-01-18
|
|
||||||
**작성자**: admin
|
|
||||||
**진행 상태**: Phase 1, Phase 2 완료 ✅
|
|
||||||
**관련 파일**:
|
|
||||||
- `rb8001/app/services/workflows/coldmail_workflow.py`
|
|
||||||
- `rb8001/app/router/ir_deck.py`
|
|
||||||
- `rb8001/app/services/ir_deck_analyzer.py`
|
|
||||||
- `rb8001/requirements.txt`
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 현재 상황
|
|
||||||
|
|
||||||
- **현재 버전**: `langgraph>=1.0.0` (1.0.1 설치 완료, 2026-01-18)
|
|
||||||
- **사용 위치**:
|
|
||||||
- 콜드메일 워크플로우 (`coldmail_workflow.py`) - `interrupt()` 동적 인터럽트 사용 ✅
|
|
||||||
- IR Deck 평가 (`ir_deck_workflow.py`) - LangGraph 워크플로우 사용 ✅
|
|
||||||
- **체크포인터**: `AsyncSqliteSaver` 사용 (`coldmail_briefing.py:103`, `coldmail_service.py:121`, `ir_deck.py`)
|
|
||||||
|
|
||||||
**참고**: LangGraph 1.0은 2025-10-22 출시 완료. 현재 0.6.10에서 1.0으로 업그레이드 진행 가능. `interrupt_after`는 1.0에서도 지원되지만, `interrupt()` 동적 인터럽트 사용 권장.
|
|
||||||
|
|
||||||
## LangGraph 1.0 주요 변경사항
|
|
||||||
|
|
||||||
1. **Durable State**: `AsyncSqliteSaver` 같은 외부 체크포인터 사용 시 서버 재시작/중단 시 자동 재개 지원 (0.6.10에서도 지원, 1.0에서 강화)
|
|
||||||
2. **HITL 패턴 개선**: `interrupt_after` 정적 인터럽트는 유지되지만, 동적 `interrupt()` 사용 권장 (조건부 일시 중지 가능)
|
|
||||||
3. **API 변경**: `Command(resume=...)`로 재개, `interrupt()` 함수 사용 권장
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 1: 콜드메일 워크플로우 HITL 패턴 마이그레이션 ✅ **완료** (2026-01-18)
|
|
||||||
|
|
||||||
**목표**: `interrupt_after=["process"]` 정적 인터럽트 → 동적 `interrupt()` 사용
|
|
||||||
|
|
||||||
**파일**: `rb8001/app/services/workflows/coldmail_workflow.py`
|
|
||||||
|
|
||||||
**완료 내용**:
|
|
||||||
- `process_node`에서 `waiting_confirmation` 있을 때 `interrupt()` 동적 호출 추가
|
|
||||||
- `create_workflow`에서 `interrupt_after` 제거
|
|
||||||
- `coldmail_service.py`에서 `Command(resume=True)` 재개 로직 추가, `aupdate_state`로 `confirmed_email_id` 설정
|
|
||||||
- 테스트 통과: `test_coldmail_workflow_interrupt.py` 4개, `test_coldmail_workflow_resume.py` 3개
|
|
||||||
|
|
||||||
### 1.1 마이그레이션 방법
|
|
||||||
|
|
||||||
**현재 코드** (0.6.10):
|
|
||||||
```python
|
|
||||||
# coldmail_workflow.py:281
|
|
||||||
if checkpointer is not None:
|
|
||||||
return workflow.compile(checkpointer=checkpointer, interrupt_after=["process"])
|
|
||||||
```
|
|
||||||
|
|
||||||
**변경 후** (1.0 권장 방식):
|
|
||||||
```python
|
|
||||||
from langgraph.types import interrupt, Command
|
|
||||||
|
|
||||||
async def process_node(state: ColdmailState) -> ColdmailState:
|
|
||||||
"""콜드메일 처리 노드 (동적 인터럽트 사용)"""
|
|
||||||
# ... 기존 로직 ...
|
|
||||||
|
|
||||||
# 신뢰도 95% 미만: 동적 인터럽트로 일시 중지
|
|
||||||
if confidence < 0.95:
|
|
||||||
interrupt({
|
|
||||||
"type": "confirmation",
|
|
||||||
"email_id": email.get("id"),
|
|
||||||
"subject": email.get("subject"),
|
|
||||||
"confidence": confidence
|
|
||||||
})
|
|
||||||
|
|
||||||
# ... 나머지 로직 ...
|
|
||||||
```
|
|
||||||
|
|
||||||
**재개 방법** (`coldmail_service.py` 수정):
|
|
||||||
```python
|
|
||||||
# 기존: workflow.ainvoke(state, config) - 상태 업데이트로 재개
|
|
||||||
# 변경: Command(resume=True)로 명시적 재개
|
|
||||||
result = await workflow.ainvoke(Command(resume=True), config=config)
|
|
||||||
```
|
|
||||||
|
|
||||||
### 1.2 작업 내용
|
|
||||||
|
|
||||||
1. `process_node`: 신뢰도 95% 미만일 때 `interrupt()` 호출 (기존 `waiting_confirmation` 로직 유지)
|
|
||||||
2. `coldmail_workflow.py:281`: `interrupt_after` 제거, `interrupt()` 동적 사용으로 전환
|
|
||||||
3. `coldmail_service.py:158`: 재개 로직을 `Command(resume=True)` 사용으로 변경
|
|
||||||
|
|
||||||
### 1.3 테스트
|
|
||||||
|
|
||||||
- 신뢰도 95% 이상: 자동 처리 (인터럽트 없음)
|
|
||||||
- 신뢰도 95% 미만: `interrupt()` 호출 → 확인 버튼 클릭 → `Command(resume=True)` 재개
|
|
||||||
|
|
||||||
**참고**: `interrupt_after`는 1.0에서도 지원되지만, 디버깅용으로만 권장. 프로덕션 HITL은 `interrupt()` 사용.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 2: 프론트엔드 IR 평가 워크플로우화 ✅ **완료** (2026-01-18)
|
|
||||||
|
|
||||||
**목표**: `asyncio.create_task` 비동기 실행 → LangGraph StateGraph 워크플로우
|
|
||||||
|
|
||||||
**파일**:
|
|
||||||
- 신규: `rb8001/app/services/workflows/ir_deck_workflow.py` ✅
|
|
||||||
- 수정: `rb8001/app/router/ir_deck.py` ✅
|
|
||||||
|
|
||||||
**완료 내용**:
|
|
||||||
- `ir_deck_workflow.py` 신규 생성 (5개 노드: extract, evaluate, analyze_pages, save, answer)
|
|
||||||
- `ir_deck.py`에서 `asyncio.create_task` → LangGraph 워크플로우 전환
|
|
||||||
- 체크포인터 기반 상태 관리로 서버 재시작 시 자동 재개 지원
|
|
||||||
- 테스트 통과: `test_ir_deck_workflow.py` 5개
|
|
||||||
|
|
||||||
### 2.1 워크플로우 설계
|
|
||||||
|
|
||||||
**상태 모델** (`IRDeckState`):
|
|
||||||
```python
|
|
||||||
class IRDeckState(TypedDict):
|
|
||||||
document_id: str
|
|
||||||
team_id: str
|
|
||||||
evaluation_id: Optional[str]
|
|
||||||
full_text: Optional[str] # _get_full_text 결과
|
|
||||||
page_count: Optional[int]
|
|
||||||
evaluation_result: Optional[Dict] # _evaluate_comprehensive 결과
|
|
||||||
page_evaluations: List[Dict] # _analyze_pages 결과
|
|
||||||
question: Optional[str] # chat 요청 시
|
|
||||||
answer: Optional[str] # chat 응답
|
|
||||||
```
|
|
||||||
|
|
||||||
**노드 구성**:
|
|
||||||
1. `extract_node`: `_get_full_text()` 호출 → `full_text`, `page_count` 저장
|
|
||||||
2. `evaluate_node`: `_evaluate_comprehensive()` 호출 → `evaluation_result` 저장
|
|
||||||
3. `analyze_pages_node`: `_analyze_pages()` 호출 → `page_evaluations` 저장
|
|
||||||
4. `save_node`: `repository.create_evaluation()` 호출 → `evaluation_id` 저장
|
|
||||||
5. `answer_node` (조건부): `question` 있을 때 RAG 검색 + LLM 답변 → `answer` 저장
|
|
||||||
|
|
||||||
**라우팅**:
|
|
||||||
- `extract` → `evaluate` → `analyze_pages` → `save` → `answer` (question 있으면) → `END`
|
|
||||||
|
|
||||||
### 2.2 작업 내용
|
|
||||||
|
|
||||||
1. `ir_deck_workflow.py` 신규 생성:
|
|
||||||
- `IRDeckState` 정의
|
|
||||||
- 5개 노드 함수 구현 (`extract_node`, `evaluate_node`, `analyze_pages_node`, `save_node`, `answer_node`)
|
|
||||||
- `create_ir_deck_workflow()` 함수로 그래프 생성 (체크포인터 옵션)
|
|
||||||
2. `ir_deck.py:216-250` 수정:
|
|
||||||
- `asyncio.create_task` 제거
|
|
||||||
- `create_ir_deck_workflow()` 호출 → `workflow.ainvoke()` 실행
|
|
||||||
- 체크포인터 사용 (서버 재시작 시 재개 지원)
|
|
||||||
3. `ir_deck_analyzer.py` 수정:
|
|
||||||
- `analyze()` 메서드는 워크플로우로 이동, 기존 메서드는 호환성 유지용으로 유지 (deprecated)
|
|
||||||
|
|
||||||
### 2.3 테스트
|
|
||||||
|
|
||||||
- `/api/ir-deck/evaluate` 호출 → 워크플로우 실행 → `evaluation_id` 반환
|
|
||||||
- `question` 파라미터 있을 때: `answer_node` 실행되어 `answer` 반환
|
|
||||||
- 체크포인터 재개 테스트: 서버 재시작 후 동일 `thread_id`로 재개
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Phase 3: Durable State 자동 재개 강화
|
|
||||||
|
|
||||||
**목표**: 서버 재시작 시 워크플로우 자동 재개 로직 추가
|
|
||||||
|
|
||||||
**현재 상태**:
|
|
||||||
- `AsyncSqliteSaver` 사용 중 (Durable State 지원)
|
|
||||||
- 서버 재시작 시 체크포인트는 유지되나, 재개 로직은 수동 (`coldmail_service.py`에서 재개)
|
|
||||||
|
|
||||||
### 3.1 작업 내용
|
|
||||||
|
|
||||||
**"수동 설정 제거" 의미 명확화**:
|
|
||||||
- 체크포인터는 여전히 설정 필요 (`AsyncSqliteSaver.from_conn_string()`)
|
|
||||||
- 변경 사항: 서버 시작 시 미완료 워크플로우 자동 감지 및 재개 로직 추가
|
|
||||||
|
|
||||||
**구현 방법**:
|
|
||||||
1. `rb8001/app/services/workflow_recovery_service.py` 신규 생성:
|
|
||||||
- `recover_incomplete_workflows()`: 체크포인터 DB에서 `waiting_confirmation` 상태인 워크플로우 조회
|
|
||||||
- `resume_workflows()`: 조회된 워크플로우 재개 (선택적 - 사용자 확인 대기 중인 것만)
|
|
||||||
2. `main.py` 수정:
|
|
||||||
- 서버 시작 시 `recover_incomplete_workflows()` 호출 (선택적 - 콜드메일은 사용자 확인 대기 중이므로 자동 재개 불필요, IR 평가는 가능)
|
|
||||||
|
|
||||||
**참고**: 콜드메일은 사용자 확인 대기 중이므로 자동 재개하지 않음. IR 평가는 백그라운드 작업이므로 재개 가능.
|
|
||||||
|
|
||||||
### 3.2 체크포인터 설정 정리
|
|
||||||
|
|
||||||
**현재**:
|
|
||||||
- `coldmail_briefing.py:103`: `AsyncSqliteSaver.from_conn_string(db_path)`
|
|
||||||
- `coldmail_service.py:121`: 동일
|
|
||||||
|
|
||||||
**변경 없음**: 체크포인터 경로는 환경변수 (`LANGGRAPH_STATE_DIR`, `LANGGRAPH_SQLITE_FILE`)로 관리되므로 수정 불필요.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 완료 작업 요약
|
|
||||||
|
|
||||||
1. ✅ **버전 업그레이드**: `requirements.txt` - `langgraph==0.6.10` → `langgraph>=1.0.0` (langgraph 1.0.1 설치 확인)
|
|
||||||
2. ✅ **Phase 1**: `coldmail_workflow.py` - `interrupt_after` → `interrupt()` 동적 인터럽트 마이그레이션
|
|
||||||
3. ✅ **Phase 1**: `coldmail_service.py` - `Command(resume=True)` 재개 로직 추가, `aupdate_state`로 상태 업데이트
|
|
||||||
4. ✅ **Phase 2**: `ir_deck_workflow.py` 신규 생성 - IR 평가 워크플로우 구현 (5개 노드)
|
|
||||||
5. ✅ **Phase 2**: `ir_deck.py` - `asyncio.create_task` → LangGraph 워크플로우 전환
|
|
||||||
6. ✅ **테스트**: Phase 1, Phase 2 단위 테스트 및 통합 테스트 모두 통과 (총 12개 테스트 통과)
|
|
||||||
|
|
||||||
## 남은 작업
|
|
||||||
|
|
||||||
- ⏳ **Phase 3**: `workflow_recovery_service.py` 신규 생성 - 서버 재시작 시 미완료 워크플로우 자동 재개 (IR 평가만, 선택적)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## 참고 문서
|
|
||||||
|
|
||||||
- LangGraph 공식 문서: https://github.com/langchain-ai/langgraph
|
|
||||||
- LangGraph 1.0 마이그레이션 가이드: https://docs.langchain.com/oss/python/migrate/langgraph-v1
|
|
||||||
- 현재 구현: `rb8001/app/services/workflows/coldmail_workflow.py`
|
|
||||||
- 관련 troubleshooting:
|
|
||||||
- `troubleshooting/251015_claude_coldmail_workflow_langgraph_test.md`
|
|
||||||
- `troubleshooting/251223_coldmail_langgraph_interrupt_and_checkpoint_fix.md`
|
|
||||||
- `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md` ✅
|
|
||||||
|
|
||||||
33
journey/plans/archive/251218_langgraph_1.0_upgrade_plan.md
Normal file
33
journey/plans/archive/251218_langgraph_1.0_upgrade_plan.md
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
# LangGraph 1.0 업그레이드 계획
|
||||||
|
|
||||||
|
**날짜**: 2025-12-18
|
||||||
|
**수정일**: 2026-01-18
|
||||||
|
**작성자**: admin
|
||||||
|
**상태**: 전체 완료 ✅ → 상세: `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md`, `troubleshooting/260118_langgraph_1.0_upgrade_phase3_workflow_recovery.md`
|
||||||
|
**관련 파일**:
|
||||||
|
- `rb8001/app/services/workflows/coldmail_workflow.py`
|
||||||
|
- `rb8001/app/router/ir_deck.py`
|
||||||
|
- `rb8001/app/services/ir_deck_analyzer.py`
|
||||||
|
- `rb8001/requirements.txt`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 완료 상태
|
||||||
|
|
||||||
|
전체 완료 (2026-01-18):
|
||||||
|
- Phase 1: 콜드메일 워크플로우 interrupt() 동적 인터럽트 마이그레이션 → 상세: `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md` (Phase 1 포함)
|
||||||
|
- Phase 2: IR Deck 평가 워크플로우 구현 → 상세: `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md`
|
||||||
|
- Phase 3: 워크플로우 복구 서비스 구조 준비 → 상세: `troubleshooting/260118_langgraph_1.0_upgrade_phase3_workflow_recovery.md`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 문서
|
||||||
|
|
||||||
|
- LangGraph 공식 문서: https://github.com/langchain-ai/langgraph
|
||||||
|
- LangGraph 1.0 마이그레이션 가이드: https://docs.langchain.com/oss/python/migrate/langgraph-v1
|
||||||
|
- 현재 구현: `rb8001/app/services/workflows/coldmail_workflow.py`
|
||||||
|
- 관련 troubleshooting:
|
||||||
|
- `troubleshooting/251015_claude_coldmail_workflow_langgraph_test.md`
|
||||||
|
- `troubleshooting/251223_coldmail_langgraph_interrupt_and_checkpoint_fix.md`
|
||||||
|
- `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md` ✅
|
||||||
|
|
||||||
@ -0,0 +1,62 @@
|
|||||||
|
# LangGraph 1.0 업그레이드 - Phase 3 워크플로우 복구 서비스
|
||||||
|
|
||||||
|
**날짜**: 2026-01-18
|
||||||
|
**작성자**: Auto
|
||||||
|
**관련 파일**:
|
||||||
|
- `rb8001/app/services/workflow_recovery_service.py` (신규)
|
||||||
|
- `rb8001/main.py`
|
||||||
|
- `rb8001/tests/test_workflow_recovery_service.py` (신규)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 목적
|
||||||
|
|
||||||
|
서버 재시작 시 미완료 IR 평가 워크플로우 자동 재개 로직 추가 (Phase 3).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 구현 내용
|
||||||
|
|
||||||
|
### workflow_recovery_service.py 신규 생성
|
||||||
|
|
||||||
|
**파일**: `rb8001/app/services/workflow_recovery_service.py`
|
||||||
|
|
||||||
|
**구현 내용**:
|
||||||
|
- `recover_incomplete_workflows()`: 미완료 워크플로우 자동 재개 구조 준비
|
||||||
|
- 현재는 빈 구현 (구조만 준비)
|
||||||
|
- 체크포인터에서 모든 thread_id 조회가 복잡하여 향후 필요 시 확장 가능하도록 구조 준비
|
||||||
|
|
||||||
|
**참고**:
|
||||||
|
- IR 평가 워크플로우는 백그라운드 작업이므로 자동 재개 가능
|
||||||
|
- 콜드메일은 사용자 확인 대기 중이므로 자동 재개하지 않음
|
||||||
|
|
||||||
|
### main.py 수정
|
||||||
|
|
||||||
|
**파일**: `rb8001/main.py:171-176`
|
||||||
|
|
||||||
|
**수정 내용**:
|
||||||
|
- 서버 시작 시 `recover_incomplete_workflows()` 호출 추가
|
||||||
|
- 워크플로우 복구 로그 출력
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 테스트 결과
|
||||||
|
|
||||||
|
**실제 결과** (2026-01-18 검증 완료):
|
||||||
|
- ✅ 테스트 통과: 3개 테스트 모두 통과
|
||||||
|
- ✅ 서버 시작 시 workflow_recovery_service 정상 호출 확인 (로그 검증)
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 교훈
|
||||||
|
|
||||||
|
1. **체크포인터 조회 복잡도**: LangGraph의 체크포인터에서 모든 thread_id를 나열하는 직접적인 API가 없어, DB 직접 조회 또는 별도 추적 테이블이 필요할 수 있음
|
||||||
|
2. **구조 우선 구현**: 현재는 구조만 준비하고, 실제 재개 로직은 향후 필요 시 확장 가능하도록 설계
|
||||||
|
3. **선택적 구현**: Phase 3는 선택적이며, IR 평가 워크플로우는 빠르게 완료되므로 서버 재시작으로 중단될 가능성이 낮음
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## 참고 문서
|
||||||
|
|
||||||
|
- 계획 문서: `plans/251218_langgraph_1.0_upgrade_plan.md`
|
||||||
|
- Phase 2 구현: `troubleshooting/260118_langgraph_1.0_upgrade_ir_deck_workflow.md`
|
||||||
Loading…
x
Reference in New Issue
Block a user