69일차 자료 갱신: flow.py test -v, 개요 그림·데이터 예시, Lab 03 예제 1 지금 결과 (정답본 제외)

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
mcchaeandClaude Opus 5.5 committed 2026-10-20 22:59:34 +09:00
1 parent 17242dc34a
commit 160967b005
10 files changed
+133 -36

No files matched your search

+73 -4
View File
@@ -75,14 +75,82 @@ flowchart LR
```mermaid
flowchart LR
W(["request · facts"]) --> A{{"작성자<br/>my-writer"}} --> R{{"검토자<br/>my-reviewer"}} --> P{"통과?"}
W(["공지 팀 my-notice<br/>request · facts"]) --> A{{"작성자 워크플로우<br/>my-writer · LLM 1"}} --> R{{"검토자 워크플로우<br/>my-reviewer · 규칙 3 + LLM 1"}} --> P{"통과?<br/>(If)"}
P -->|예| OK["게시 가능"]
P -->|아니오| A2{{"작성자<br/>고쳐 쓰기"}} --> R2{{"검토자"}} --> P2{"통과?"}
P -->|아니오| A2{{"작성자 워크플로우<br/>고쳐 쓰기"}} --> R2{{"검토자 워크플로우"}} --> P2{"통과?<br/>(If)"}
P2 -->|예| OK2["수정 후 게시 가능"]
P2 -->|아니오| H["담당자 확인"]
OK & OK2 --> E1["제목"] & E2["메신저 글"] --> J["모으기"]
OK & OK2 --> E1["정리자: 제목<br/>LLM 1"] & E2["정리자: 메신저 글<br/>LLM 1"] --> J["모으기"]
```
> 육각형 하나 = **역할 하나 = 웹훅 하나인 n8n 워크플로우**입니다. 역할 자체가 LLM은 아니고, 그 안에 AI Agent(LLM) 노드가 들어 있습니다. 공지 팀(`my-notice`)은 LLM 없이 역할들을 **HTTP로 부르고 If로 갈림**을 정합니다 (68일차 라우터의 Switch와 같은 자리).
### 데이터로 따라가기 · 연락처가 든 프린터 공지 (수업 준비 때 실제 실행 기록)
그림의 왼쪽부터, 각 상자가 **받은 것**과 **내놓은 것**입니다. 상자 사이로는 이 JSON만 오갑니다.
**① 요청** → 공지 팀 `my-notice` (`requests/notice-phone.json`)
```json
{"request": "프린터 드라이버 업데이트 공지를 써 주세요. 문의처 연락처도 꼭 넣어 주세요.",
"facts": "10월 30일(목) 18:00~19:00 사내 프린터 드라이버 일괄 업데이트. 업데이트 중에는 출력이 안 됨. 문의는 IT팀 김민지(010-1234-5678, minji.kim@example.com).",
"author": "김민지"}
```
**② 작성자** `my-writer` · 받음: `request`, `facts` → 내놓음: 초안
```json
{"draft": "[프린터 드라이버 업데이트 안내]\n\n- 10월 30일(목) 18:00~19:00 사내 프린터 드라이버 일괄 업데이트 진행\n- 업데이트 시간 동안 프린터 출력 불가\n- 문의: IT팀 김민지 (010-1234-5678, minji.kim@example.com)"}
```
요청("연락처도 꼭")대로 개인 연락처를 넣었습니다. 작성자는 요청을 따르고, **회사 규칙은 검토자가** 지킵니다.
**③ 검토자** `my-reviewer` · 받음: `facts`(①의 것), `draft`(②) → 내놓음: 판정
```json
{"passed": false, "codes": ["personal_info"],
"issues": [{"code": "personal_info", "detail": "010-1234-5678, minji.kim@example.com"}]}
```
전화번호 · 메일 주소는 **규칙(Code)** 이 찾았습니다. `passed: false` → 공지 팀의 If가 "아니오" 길로 보냅니다.
**④ 작성자 · 고쳐 쓰기** · 받음: `request`, `facts`(①), `previous_draft`(②), `feedback`(③의 `issues`를 "code: detail" 줄로)
```json
{"feedback": "personal_info: 010-1234-5678, minji.kim@example.com"}
```
```json
{"draft": "[프린터 드라이버 업데이트 안내]\n\n- 10월 30일(목) 18:00~19:00 사내 프린터 드라이버 일괄 업데이트 진행\n- 업데이트 시간 동안 프린터 출력 불가\n- 문의: IT팀 김민지"}
```
연락처만 빠지고 날짜 · 시간 · 나머지는 그대로입니다. (다른 실행에서는 여기서 "(내선 1234)"를 지어낸 적이 있어, 작성자 지시문에 "고칠 때 새 정보 금지"를 넣었습니다.)
**⑤ 검토자 · 다시** · 받음: `facts`(**①의 것**, 고쳐 쓴 작성자가 전한 것이 아님), `draft`(④)
```json
{"passed": true, "codes": [], "issues": []}
```
**⑥ 정리자 둘** · 받음: 통과한 공지(④) → 내놓음: 메일 제목, 메신저 글
```json
{"title": "10월 30일 프린터 드라이버 업데이트 안내",
"chat": "10/30(목) 18:00~19:00 프린터 드라이버 업데이트로 출력 불가. 문의: IT팀 김민지."}
```
**⑦ 공지 팀 응답** (5.9초, LLM 6번: 작성 2 · 검토 2 · 정리 2)
```json
{"route": "수정 후 게시 가능", "published": true, "rounds": 2,
"notice": "[프린터 드라이버 업데이트 안내]\n\n- 10월 30일(목) 18:00~19:00 … 진행\n- … 출력 불가\n- 문의: IT팀 김민지",
"codes": [], "first_codes": ["personal_info"],
"title": "10월 30일 프린터 드라이버 업데이트 안내",
"chat": "10/30(목) 18:00~19:00 프린터 드라이버 업데이트로 출력 불가. 문의: IT팀 김민지."}
```
`first_codes`는 ③에서 무엇이 걸렸는지, `codes`는 ⑤의 결과입니다. 메일 점검 공지처럼 ③에서 바로 `passed: true`면 ④ · ⑤ 없이 `게시 가능`, `rounds: 1`입니다.
> Lab 01(역할 하나씩) → Lab 02(이어 붙이기, 정리자) → Lab 03(기록, 검토자 장애, 비교) 순서로 완성합니다.
---
@@ -95,6 +163,7 @@ flowchart LR
| 내놓는 것 | `draft` | `passed`, `codes`, `issues` |
| **하지 않는 일** | 스스로 통과 판정 | 초안 고쳐 쓰기 |
| LLM · 규칙 | LLM | 규칙 3 (날짜·시간, 연락처, 길이) + LLM 1 (없는 약속) |
| n8n 워크플로우 안 | Webhook → If → **AI Agent**(LLM) → Code → 응답 | Webhook → If → **Code**(규칙 3) → **AI Agent**(LLM, 없는 약속) → Code(합치기 · LLM 판단 재확인) → 응답 |
> 역할을 나누면 **역할마다 따로 테스트**할 수 있습니다: 검토자에게 일부러 틀린 초안 5종 (`lab01-challenge` 6/6).
@@ -135,7 +204,7 @@ flowchart LR
| 수업 준비 측정 | 결과 |
| --- | --- |
| `lab02-challenge` | 4/4 (두 번) |
| 요청 하나 | 정리자 없이 2.0~4.1초 → 정리자 붙이고 4.1~5.9초 |
| 요청 하나 | 정리자 없이 2.0~4.1초 → 정리자 붙이고 4.1~6.5초 |
> 설계는 "서로 기다릴 필요 없음". n8n이 실제로 동시에 돌리는지는 Executions의 노드 시각으로 함께 확인합니다.
+1 -1
View File
@@ -87,7 +87,7 @@ flowchart LR
| 정리자마다 chat model 노드 따로 | model 노드 하나는 Agent 하나에 연결 |
| 정리자의 "하지 않는 일": 새 정보, 날짜 바꾸기 | 검토를 통과한 뒤 바뀌면 안 됨 |
수업 준비 때 결과: `lab02-challenge` 4/4 (두 번 실행). 요청 하나가 정리자 없이 2.0~4.1초 → 정리자 붙이고 4.1~5.9초.
수업 준비 때 결과: `lab02-challenge` 4/4 (두 번 실행). 요청 하나가 정리자 없이 2.0~4.1초 → 정리자 붙이고 4.1~6.5초.
> Fork-Join은 **설계**에서 "서로 기다릴 필요 없음"입니다. n8n이 두 갈래를 실제로 동시에 돌리는지는 실행 방식에 따라 다릅니다. Lab 02 과제에서 Executions의 노드 시각으로 확인합니다.
+1 -1
View File
@@ -23,7 +23,7 @@ flowchart LR
- `steps`는 LLM이 쓰지 않습니다. 어느 길로 왔는지는 **워크플로우가** 알기 때문에, 결과를 만드는 노드에 정해진 값으로 넣습니다.
- 역할마다 웹훅이 따로라서 n8n **Executions**에 역할별 실행이 남습니다. 결과의 기록 + 역할별 실행 = 협업의 감사 기록.
수업 준비 때 Lab 02 예제 정답에 `cases/lab03.json`: 1/3 (`steps` 없음, 그중 하나는 고쳐 쓰기에서 "(내선 1234)"를 지어내 `담당자 확인`). 기록을 더하고 검토자를 고친 뒤 3/3.
수업 준비 때 Lab 02 예제 정답에 `cases/lab03.json`: 1/3 (`steps` 없음. 10/18에는 그중 하나가 고쳐 쓰기에서 "(내선 1234)"를 지어내 `담당자 확인`, 작성자 · 검토자를 다듬은 수업 전날 10/20에는 `steps`만 없음). 기록을 더한 뒤 3/3.
## 2. fail-open과 fail-closed