오픈에이아이 FDE 는 모델을 고객 프로덕션에 풀스택으로 배포하고, 모델 동작이 제품 경험에 주는 영향을 평가로 이해해 현장 피드백을 남기는 게 본업입니다. 회의록 자동화 시스템을 만들고 추출 정확도를 평가로 재는 이 포트폴리오는 그 일을 구체 시나리오로 구현한 것입니다. Python·JavaScript 로 풀스택과 평가를 구현하는 데 적합합니다.
고객 가치를 전달하는 풀스택 시스템을 만들고 우리가 배우는 방식을 날카롭게 한다는 게 핵심 업무입니다. 회의록 자동화 풀스택 시스템이 그 형태입니다.
LLM·생성 모델로 시스템을 만들고 모델 동작이 제품 경험에 어떻게 영향을 주는지 이해해야 합니다. 추출 정확도를 평가로 재는 부분과 직접 닿습니다.
동작하는 패턴을 도구·운영 가이드·재사용 블록으로 정리합니다. 추출·평가 골격을 재사용 블록으로 남기는 흐름과 맞습니다.
회의·통화 기록(transcript)을 받아, 클로드가 결정사항과 할 일을 구분해 각 할 일의 담당자·기한을 근거 문장과 함께 뽑고, 대명사 담당자·상대 기한·번복을 정규화해 구조화된 회의록으로 정리해 보여줍니다. 회의마다 심어둔 정답 할 일(expected_action_items)과 맞춰 추출 정밀도·재현율을 평가로 함께 보여줍니다.
오픈에이아이 Forward Deployed Engineer. 회의가 끝나면 누가 무엇을 언제까지 하기로 했는지 녹취록을 다시 들으며 손으로 회의록을 정리하던 상황을, 한 화면에서 자동 추출된 할 일·담당자·기한과 근거 문장을 함께 보고 추출이 맞았는지 평가 숫자로 확인하고 싶은 사람입니다.
회의 기록을 한 스키마로 받고 정답 할 일 정답셋을 붙이면, (a) 클로드가 결정사항과 할 일을 구분해 담당자·기한을 근거와 함께 뽑고, (b) 대명사·상대 기한·번복을 정규화하며, (c) 심어둔 정답과 맞춰 추출 정밀도·재현율을 객관적으로 측정합니다.
회의 기록을 받아 클로드가 결정사항과 할 일·담당자·기한을 근거 문장과 함께 뽑아 구조화된 회의록으로 보여주는 동작하는 풀스택 시스템입니다. 입력은 회의 기록을 가정한 더미로 시작하고, 담당자·기한이 모호하면 추측 대신 '미지정'으로 표시합니다. Next 프론트를 기본 배포로 바로 돌게 합니다.
회의마다 심어둔 정답 할 일과 맞춰 추출 정밀도·재현율을 재고, 검토자 2명이 모호 케이스를 라벨링해 일치도를 보여주는 화면입니다. 잘못 추가한 할 일과 놓친 할 일을 사례로 정리합니다.
회의록 시나리오에 쓴 추출·평가 구조를 다른 고객 회의 유형에도 쓰도록 재사용 블록(골격·운영 가이드)으로 정리하는 단계입니다.
회의 기록 12종을 넣으면, 결정사항과 할 일·담당자·기한이 근거 문장과 함께 회의록으로 정리되는 걸 시연합니다
일부러 만든 악성·결측 입력 30종(담당자 미지정·기한 상대표현·번복·잡담)을 넣어도 출력 형식(스키마)이 한 번도 안 깨집니다
내가 회의마다 심어둔 정답 할 일과 맞춰 추출 정밀도·재현율을 측정합니다. 정답 40건 중 정확히 뽑은 게 34건(재현율 약 85%), 잘못 추가한 할 일은 4건(정밀도 약 89%)입니다. 정답을 원문에 심어 근거 문장 인용으로 대조하므로 객관 채점입니다
담당자·기한이 모호한 할 일은 추측 없이 '미지정'으로 표시되는 걸 시연으로 보여줍니다
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 추출 정밀도·재현율은 오픈에이아이 실 고객 회의 기록과 실 검토자가 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 데이터 자가채점이라 성능 증명이 아닙니다. 면접에서는 데모 동작과 실검증 준비 상태로 솔직히 설명하는 게 오히려 신뢰를 줍니다
정답을 작성자가 만들었으니 잘 맞는 게 당연합니다. 그래서 담당자 미지정·상대 기한·번복·잡담 같은 헷갈리는 경계 케이스를 회의 기록에 일부러 심어, 쉬운 문제만 푸는 게 아님을 보여줍니다
추출 오판은 없는 할 일을 만들거나 있는 할 일을 놓칩니다. 추출 값은 근거 문장 인용을 강제하고, 담당자·기한이 모호하면 추측 대신 '미지정'으로 표시합니다
담당자 표기가 대명사·직함으로 흔들립니다('제가'·'그쪽'·'김대리'). R&R 마스터로 정규화하고, 못 묶은 건 추측하지 말고 '미지정'으로 알립니다
실제 도입 시 달라지는 점을 명시합니다. 실 회의 기록은 음성 인식 오류·중첩 발화가 섞여 더미와 다르므로 추출·정규화 규칙을 다시 맞추고 검토자도 실제 인력으로 교체해야 합니다(도입 단계 과제로 분리)
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
회의·통화 기록 원문. 추출 클로드가 가장 먼저 읽는 입력입니다. 할 일·담당자·기한을 대화 속에 의도적으로 심되, 담당자 미지정·암묵 표현·상대 기한·번복·잡담을 섞어, 쉬운 추출만 푸는 게 아님을 보여줍니다. (정답은 expected_action_items 표에 따로 둡니다.)
박PM: 결제 모듈 리팩토링 건은 A안으로 가기로 결정했습니다. 김대리: 그럼 제가 다음 주 화요일까지 결제 API 문서부터 정리하겠습니다. 박PM: 좋아요. 그리고 QA 자동화는 누가 좀 챙겨야 할 텐데요. 이주임: 점심 뭐 먹을까요 오늘. 박PM: 일단 그 얘긴 나중에 하고요.
고객: 이번 달 말까지 대시보드 베타를 받아볼 수 있을까요? 최리드: 네, 월말까지 베타 빌드 전달하겠습니다. 제가 책임지고요. 고객: 그리고 권한 설정 가이드도 필요해요. 최리드: 그건 정해지면 공유드릴게요.
아래 JSON Schema({"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string"}},"required":["title","body"]})에 맞는 한국어 회의·통화 기록 40건 JSON 배열로 생성합니다. 각 기록은 자연스러운 대화(화자: 발화) 형식. 모두 가상 더미.
쉬운 추출만 만들지 말 것. 할 일·담당자·기한을 대화에 심되 다음 하드 케이스를 의도적으로 섞어라(정답은 expected_action_items 표와 일치해야 함): (1) 명시 할 일('김대리가 화요일까지 X') 다수, (2) 담당자 미지정 할 일('누가 좀 챙겨야', owner 미정) 4건, (3) 결정사항이지만 할 일은 아닌 발화('A안으로 결정') 4건, (4) 대명사·직함 담당자('제가'·'그쪽'을 화자/직함으로 정규화) 다수, (5) 상대 기한('월말'·'다음 스프린트'·'다다음 주') 3건, (6) 번복('아까 A 하기로 했는데 B로 바꾸죠', 최종만 유효) 2건, (7) 기한 못 박는 보류('일정 확인 후') 2건, (8) 잡담·여담(할 일 아님) 일부. JSON 배열만(각 원소 {title, body}). 각 발화는 줄바꿈(\n)으로 구분해 한 줄에 한 발화씩 둔다.{"type":"object","properties":{"title":{"type":"string"},"body":{"type":"string"}},"required":["title","body"]}각 회의 기록에 심어둔 정답 할 일·결정사항. 추출 결과를 채점하는 정답셋(ground truth)입니다. 담당자 미지정·번복(supersede)·결정 vs 할 일 구분을 정답으로 명시해, 추출 정밀도·재현율을 객관적으로 잴 수 있게 합니다.
| transcript_id | item_id | type | task | owner | due | is_explicit | supersedes |
|---|---|---|---|---|---|---|---|
| mt_001 | a_001 | decision | 결제 모듈 리팩토링 A안으로 진행 | — | — | true | — |
| mt_001 | a_002 | action | 결제 API 문서 정리 | 김대리 | 다음 주 화요일 | true | — |
| mt_001 | a_003 | action | QA 자동화 챙기기 | — | — | false | — |
| mt_002 | a_004 | action | 대시보드 베타 빌드 전달 | 최리드 | 월말 | true | — |
| mt_003 | a_005 | decision | 온보딩 화면 1단계로 변경 | — | — | true | — |
아래 JSON Schema에 맞는 정답 할 일·결정사항 표 50행 JSON 배열로 생성합니다. meeting_transcripts 의 각 회의 본문에 실제로 심은 할 일과 1:1 로 일치해야 합니다.
{"type":"object","properties":{"transcript_id":{"type":"string"},"item_id":{"type":"string"},"type":{"enum":["action","decision"]},"task":{"type":"string"},"owner":{"type":["string","null"]},"due":{"type":["string","null"]},"is_explicit":{"type":"boolean"},"supersedes":{"type":["string","null"]}},"required":["transcript_id","item_id","type","task","owner","due","is_explicit","supersedes"]}
조건: (1) decision 은 owner/due null, (2) 담당자 미지정 할 일은 owner=null·is_explicit=false, (3) 상대 기한은 원문 표현 그대로('월말'·'다음 스프린트'), (4) 번복은 새 항목에 supersedes=이전 item_id 채우고 이전 항목은 무효 취급, (5) 잡담은 정답에 넣지 않음. transcript_id 별 0~3건. JSON 배열만.{"type":"object","properties":{"transcript_id":{"type":"string"},"item_id":{"type":"string"},"type":{"enum":["action","decision"]},"task":{"type":"string"},"owner":{"type":["string","null"]},"due":{"type":["string","null"]},"is_explicit":{"type":"boolean"},"supersedes":{"type":["string","null"]}},"required":["transcript_id","item_id","type","task","owner","due","is_explicit","supersedes"]}| Python | 회의 기록 ingest + 정답셋 대조 평가 하니스(추출 정밀도·재현율 계산)의 구현 언어 |
| JavaScript | 회의록 화면(할 일·담당자·기한 표 + 근거 문장 하이라이트) + 평가 대시보드 구현 |
| OpenAI | 할 일·담당자·기한 추출을 만드는 모델 연동(데모는 클로드, 실무는 OpenAI 모델) |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 2주차(추출 정확도 평가)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(추출·평가 골격 재사용 블록화)로 진행합니다.
회의 1건의 정리 결과. 결정사항·할 일(담당자·기한·근거 문장)과 정답셋 대조 평가를 한 스키마로 담아 회의록 화면에 씁니다.
{"type":"object","properties":{"transcript_id":{"type":"string"},"decisions":{"type":"array","items":{"type":"object","properties":{"task":{"type":"string"},"source_quote":{"type":"string"}},"required":["task","source_quote"]}},"action_items":{"type":"array","items":{"type":"object","properties":{"task":{"type":"string"},"owner":{"type":["string","null"]},"due":{"type":["string","null"]},"source_quote":{"type":"string"},"confidence":{"enum":["low","mid","high"]}},"required":["task","owner","due","source_quote","confidence"]}},"eval":{"type":["object","null"],"properties":{"expected_actions":{"type":"integer"},"matched":{"type":"integer"},"missed":{"type":"integer"},"false_added":{"type":"integer"}}}},"required":["transcript_id","decisions","action_items","eval"]}[
{
"input_ref": "mt_001 (결정 1 + 할 일 2: 김대리 문서·QA 미지정)",
"output": {
"transcript_id": "mt_001",
"decisions": [
{
"task": "결제 모듈 리팩토링 A안으로 진행",
"source_quote": "A안으로 가기로 결정했습니다"
}
],
"action_items": [
{
"task": "결제 API 문서 정리",
"owner": "김대리",
"due": "다음 주 화요일",
"source_quote": "제가 다음 주 화요일까지 결제 API 문서부터 정리하겠습니다",
"confidence": "high"
},
{
"task": "QA 자동화 챙기기",
"owner": null,
"due": null,
"source_quote": "QA 자동화는 누가 좀 챙겨야 할 텐데요",
"confidence": "mid"
}
],
"eval": {
"expected_actions": 2,
"matched": 2,
"missed": 0,
"false_added": 0
}
}
},
{
"input_ref": "mt_009 (번복: 김대리→이주임 대체)",
"output": {
"transcript_id": "mt_009",
"decisions": [],
"action_items": [
{
"task": "결제 API 문서 정리",
"owner": "이주임",
"due": "목요일",
"source_quote": "이주임이 대신 목요일까지 하기로 하죠",
"confidence": "high"
}
],
"eval": {
"expected_actions": 1,
"matched": 1,
"missed": 0,
"false_added": 0
}
}
}
][자동 검증 — 코드가 매 출력마다 자동으로 거릅니다] 1) JSON Schema 형식 통과: 출력이 정한 필드·타입을 지키는지 검사하고, 어기면 거부합니다. 2) 각 action_items 의 task·owner 가 정답표(expected_action_items)와 매칭되는지 봅니다 — 번복된 항목은 supersedes 로 최종본만 정답 처리합니다. 3) source_quote 가 회의 본문에 실제로 있는 문장인지 인용 매칭합니다 — 없는 할 일을 지어내지 못하게 합니다. 4) owner/due 가 본문에 명시 안 됐는데 값을 채우면 false_added(잘못 추가)로 셉니다. 5) eval(matched/missed/false_added)로 추출 정밀도·재현율을 자동 계산합니다. [수동 검증 — 사람이 일부만 확인합니다] 1) 검토자 2명이 같은 모호 케이스를 따로 라벨링해, 두 사람 판단이 우연 이상으로 일치하는지 봅니다(Cohen's κ ≥ 0.6 — 0~1, 높을수록 일치). 2) 전체 출력의 5%는 사람이 직접 다시 확인합니다(spot check).