렛서
경력근거: 고객사 현장(데이터·프로세스·조직)에 들어가 진짜 문제를 진단하고 정의합니다
※ 실제 산출물이 아닌 AI 예측 시안입니다.
렛서 AX Partners 의 FDE 는 제조·유통·헬스케어 등 매번 다른 고객사 현장에 들어가, 요구사항이 정리되지 않은 상태에서 며칠 만에 작동하는 걸 만들어 보여주고 그걸 근거로 다음 범위를 정합니다. 사내 문서를 근거로 답하고 근거 없으면 현장 확인으로 넘기는 이 사슬은, 고객사마다 문서·프로세스가 다르고 '작동하는 것부터 만들어 범위를 정하는' 렛서식 진행이 있어야 의미가 있습니다. 이 포트폴리오가 보여주는 것은 RAG 어시스턴트를 혼자 설계·배포하는 웹 풀스택 구현과 근거 인용을 결정론으로 검증하는 능력이며, 제조나 유통 같은 특정 산업의 도메인 전문성은 주장하지 않습니다. 모르는 도메인 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
렛서의 프로젝트는 요구사항이 정리되지 않은 채 시작하고, 며칠 만에 작동하는 걸 만들어 보여준 뒤 그걸 근거로 다음 범위를 정합니다. 그래서 추상 기획이 아니라 실무자가 바로 써보는 작동 산출물이 1주 안에 나와야 직무와 맞물립니다.
FDE 는 웹 풀스택·데이터·RAG·에이전트를 가리지 않고 설계부터 배포·운영까지 끝냅니다. 사내 문서를 검색해 근거로 답하는 RAG 어시스턴트는 그 스택을 장식이 아니라 제품의 골조로 씁니다.
현장에서 만든 솔루션을 일회성으로 끝내지 않고 플레이북과 재사용 자산으로 정리해 다음 고객으로 확장합니다. 도메인 무관 코어와 고객사 문서셋을 분리한 설계가 이 확장 원리와 그대로 맞물립니다.
고객사 현장의 사내 운영 문서(반품 정책·출고 마감·창고 구역·보관 기준 등)를 마크다운·CSV 로 넣습니다. 클로드가 실무자 질문에 관련 문단을 검색해 그 문단을 그대로 인용하며 답하고, 문서에 근거가 없으면 답을 지어내지 않고 '문서에 근거 없음, 현장 확인'으로 넘깁니다. 문서끼리 상충하면(예: 구버전 반품 14일 vs 신버전 7일) 임의로 하나를 고르지 않고 상충을 알려 사람에게 넘깁니다. 1주차만으로 한 고객사용 어시스턴트가 Vercel 에 배포돼 돌고, 인용이 실제 문단인지 결정론 검증과 다음 고객사 문서셋 교체로 이어집니다. 근거는 채용공고 정렬이고, 데이터는 작성자가 만든 더미입니다.
렛서 FDE. 고객사 현장에 들어가 실무자에게 '이건 어느 문서에 있어요'를 매번 손으로 찾아주고, 문서에 없는 질문에도 감으로 답하다 틀리던 상황을 끝내고, 답이 실제 사내 문서 근거에서 나왔는지 확인한 뒤 어시스턴트를 배포하고 싶은 사람입니다.
고객사 사내 문서를 한 스키마로 모으고 질문에 근거 문단을 검색해 붙이면, (a) 실무자 질문에 인용 근거로 답하고, (b) 근거가 없는 질문은 지어내지 않고 '현장 확인'으로 넘기며, (c) 인용 문단이 실제 문서에 있는지 결정론으로 채점할 수 있습니다.
고객사 사내 문서를 넣으면 실무자 질문에 관련 문단을 인용해 답하고, 근거가 없거나 상충하면 지어내지 않고 '현장 확인'으로 넘기는, Vercel 에 배포돼 로그인 없이 바로 써보는 한 고객사용 어시스턴트입니다. 입력은 실 사내시스템 연동이 아니라 문서를 내보낸 마크다운·CSV(메타데이터)를 가정해, 사내망·문서관리시스템 연동 없이 1주에 혼자 완결합니다.
답의 인용 문단이 실제 사내 문서의 부분 문자열인지 결정론으로 검증하고, 답변 가능·근거 없음·상충 세 분류가 직접 만든 정답 라벨과 맞는지 채점하며, 현장 검수자 2명이 답이 타당한지 라벨링해 신뢰도를 붙인 대시보드입니다.
제조 고객사 문서셋을 유통·헬스케어 문서셋으로 갈아끼워 다음 고객사 온보딩을 반나절로 줄이는 플레이북·템플릿을 만들고, 검색 인용 임계값과 '현장 확인' 넘김 기준을 실측 분포로 다시 맞추는 단계입니다.
고객사 현장 질문 20건을 넣으면, 근거 문단을 인용한 답과 근거가 없을 때의 '현장 확인' 넘김이 몇 초 안에 나오는 걸 시연합니다.
직접 만든 정답 라벨 20건과 대조해, 답변 가능·근거 없음·상충 세 분류가 18건 일치했고 인용 문단은 전부 실제 문서의 부분 문자열이었습니다. 단, 문서·정답을 모두 작성자가 만든 합성 기준이라 '성능 검증'이 아니라 '데모 조건에서의 동작'입니다.
일부러 만든 근거 없는 질문·구버전과 신버전이 상충하는 질문·빈 질문 30종을 넣어도 답변 형식(JSON Schema)이 한 번도 안 깨지고, 근거 없는 질문에 답을 지어내지 않고 no_evidence 로 넘깁니다.
위 수치는 전부 작성자가 만든 더미 문서·정답 자가채점이며, 실제 인용 정확도와 환각율은 렛서 고객사 실 사내 문서 + 실무자 검수가 있어야 측정 가능합니다. 이 어시스턴트는 그 검증을 바로 돌릴 수 있는 상태로 만듭니다.
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 문서 자가채점이라 '성능 증명'이 아닙니다. 면접에서는 '데모 조건 동작 + 실검증 준비 상태'로 솔직히 설명합니다
정답 라벨을 제가 만들었으니 잘 맞는 게 당연합니다. 근거 없는 질문·구버전과 신버전 상충·표기 흔들림·빈 질문 같은 헷갈리는 케이스를 문서와 질문에 일부러 섞어, 쉬운 문제만 푸는 게 아님을 보여줘야 합니다.
환각(문서에 없는 답을 지어냄)이 이 도구의 최대 사고입니다. 답의 근거를 검색된 문단으로 제한하고, 인용 문단이 실제 문서의 부분 문자열인지 결정론으로 검증하며, 근거가 부족하면 답 대신 현장 확인으로 넘깁니다.
사내 문서는 구버전과 신버전이 함께 남아 상충합니다. 임의로 최신본을 단정하지 않고 상충을 알려 사람에게 넘기며, 문서 별칭·미등록 카테고리는 추측하지 않고 미매핑으로 표시합니다.
실제 도입 시 달라지는 것을 명시합니다. 고객사별 실 사내 문서 분포·표기·문서관리시스템 연동이 더미와 달라 검색 임계값과 별칭 사전을 다시 맞춰야 하고, 자가 라벨도 실무자 검수로 교체해야 합니다(도입 단계 과제로 분리).
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
한 고객사(제조·유통 복합 현장)의 사내 운영 문서입니다. RAG 검색 대상이고 답변의 인용 근거입니다. 같은 주제가 다른 표기로 들어오거나(정규화 필요), 구버전과 신버전이 상충하거나, 구체 수치가 빠져 근거로 못 쓰는 문서를 일부러 섞어, 쉬운 문서만 푸는 게 아님을 보여줍니다.
창고 재고 실사는 매월 말일에 전수로 진행합니다. 실사 중 발견된 차이는 재고조정 전표로 당일 반영합니다.
실사는 분기별로 표본 실사를 원칙으로 합니다. 표본은 A존 상위 품목을 우선합니다.
아래 JSON Schema 에 맞는 제조·유통 복합 현장의 사내 운영 문서 30건을 JSON 배열로 생성하되, 각 항목은 {title, body} 형태로.
{"type":"object","properties":{"doc_id":{"type":"string"},"title":{"type":"string"},"category_id":{"type":["string","null"]},"body":{"type":"string"},"updated_at":{"type":["string","null"]}},"required":["doc_id","title","body"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞으세요: (1) 구버전과 신버전이 상충하는 문서 쌍 2세트(예: 반품 14일 vs 7일, 실사 전수 vs 표본), 답변 시 상충으로 넘겨야 함, (2) 같은 주제의 별칭 표기(안전재고/안전 재고 등 정규화 대상), (3) 구체 수치가 빠져 근거로 못 쓰는 애매 문서 2건(예: '마감 시간은 별도 공지'), (4) body 는 실무자가 질문할 만한 사실(시간·기한·기준·구역)을 담되 문장 그대로 인용 가능하게. JSON 배열만.{"type":"object","properties":{"doc_id":{"type":"string"},"title":{"type":"string"},"category_id":{"type":["string","null"]},"body":{"type":"string"},"updated_at":{"type":["string","null"]}},"required":["doc_id","title","body"]}고객사 실무자가 던진 질문과, 그 질문의 정답 라벨입니다. 결정론 채점의 정답 기준으로, 근거 문서 제목(supporting_doc_title)과 원문 인용(answer_span)을 참조합니다. 근거 없는 질문·상충 질문·빈 질문·표기 흔들림을 일부러 섞어, 어시스턴트가 쉬운 질문만 푸는 게 아님을 보여줍니다.
| question_id | asker_role | category_raw | category_id | question | supporting_doc_title | answer_span | label_status | note |
|---|---|---|---|---|---|---|---|---|
| q01 | 창고관리자 | 재고실사 | c_inventory | 재고 실사는 얼마나 자주 하나요? | — | — | conflict | '재고 실사 주기'는 매월 전수, '재고 실사 방법(구 안내)'는 분… |
| q02 | 고객응대 | 반품 | c_return | 반품 신청은 며칠 이내에 해야 하나요? | — | — | conflict | 2024년판 14일과 2026년 개정 7일이 상충. 최신본 우선이라도… |
| q03 | 출고담당 | 출고 | c_shipping | 당일 출고 마감 시간이 언제인가요? | 출고 마감 시간 | 당일 출고 마감은 오후 3시입니다. | answered | — |
| q04 | 입고검수 | 보관 | c_storage | 냉장 품목 온도 기준이 어떻게 되나요? | 냉장 보관 기준 | 냉장 품목은 0도에서 10도 사이로 유지합니다. | answered | — |
| q05 | 신입 | 창고구역 | c_location | Q존이 무슨 구역인가요? | 창고 구역 코드 | Q존은 격리 구역입니다 | answered | — |
아래 JSON Schema 에 맞는 고객사 실무자 질문 30건을 JSON 배열로 생성하세요. asker_role 은 창고관리자·출고담당·입고검수·정산담당 등, category 는 kb_docs 주제와 맞물리게. answered 인 경우 supporting_doc_title 은 kb_docs 의 실제 title, answer_span 은 그 문서 body 의 부분 문자열(공백 포함 그대로)이어야 합니다.
{"type":"object","properties":{"question_id":{"type":"string"},"asker_role":{"type":"string"},"category_raw":{"type":"string"},"category_id":{"type":["string","null"]},"question":{"type":"string"},"supporting_doc_title":{"type":["string","null"]},"answer_span":{"type":["string","null"]},"label_status":{"type":"string","enum":["answered","conflict","no_evidence"]},"note":{"type":["string","null"]}},"required":["question_id","question","label_status"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞으세요: (1) 근거 없는 질문, 문서셋에 없는 주제(label_status=no_evidence, supporting/answer 는 null), (2) 상충 질문, 구버전과 신버전이 다른 답을 주는 질문(label_status=conflict, note 에 두 문서 사유), (3) 표기 흔들림, 질문과 문서 제목·표기가 다른 경우(정규화 필요), (4) 근거 부족, 문서에 주제는 있으나 구체 수치가 없어 답 못 하는 질문(no_evidence), (5) 빈 질문(question="") 1건. answered 의 answer_span 은 반드시 해당 문서 body 의 실제 부분 문자열. JSON 배열만.{"type":"object","properties":{"question_id":{"type":"string"},"asker_role":{"type":"string"},"category_raw":{"type":"string"},"category_id":{"type":["string","null"]},"question":{"type":"string"},"supporting_doc_title":{"type":["string","null"]},"answer_span":{"type":["string","null"]},"label_status":{"type":"string","enum":["answered","conflict","no_evidence"]},"note":{"type":["string","null"]}},"required":["question_id","question","label_status"]}| TypeScript | 대표 언어입니다. 문서 적재·임베딩 검색 연결, 근거 인용 답변 파이프라인, 인용 결정론 검증기, 배포되는 웹 어시스턴트까지 전 계층을 한 언어로 구현합니다. |
| RAG | 사내 문서를 임베딩으로 색인하고, 질문마다 관련 문단만 검색해 컨텍스트에 붙입니다. 인용 근거를 이 검색 결과 문단으로 제한해 답이 문서 밖으로 벗어나지 못하게 합니다. |
| LLM | 질문 + 검색된 문단을 받아 근거 인용 답변과 '근거 없음·상충' 판단을 한 호출에 묶는 추론 엔진입니다. 인용 문단 검증은 LLM 이 아니라 결정론 규칙이 합니다. |
| Claude | 답변 생성 모델은 Claude Sonnet 을 씁니다. 어시스턴트 골격과 배포 스크립트는 렛서식으로 Claude Code·Cursor 로 빠르게 생성합니다. |
| Next.js | 실무자가 질문하고 인용 문단과 함께 답을 보는 웹 어시스턴트와, 검수자용 인용 검증 대시보드를 App Router 로 만들어 Vercel 에 배포합니다. |
| PostgreSQL | kb_docs·field_questions·인용 검증 결과·검수 라벨의 단일 진실원입니다. 문단 검색을 위한 임베딩 인덱스(pgvector)도 함께 둡니다. |
| AI Gateway | (우대) 렛서 자체 AI Gateway 를 가정해 모델 호출을 한 곳으로 통일합니다. Claude·다른 모델 교체, 호출 로그, 비용 집계를 게이트웨이 계층에서 다룹니다. |
✓ pass → 그대로 멈춰도 완결입니다. 더 키우고 싶으면 2주차(인용이 실제 문단인지 결정론 검증)로 진행합니다.
✓ pass → 여기서 멈춰도 완결입니다. 더 키우면 3주차(다음 고객사 문서셋 교체 플레이북 + 인용 임계값 보정)로 진행합니다.
실무자 질문에 대한 어시스턴트 응답입니다. answer_status 로 답변 가능·근거 없음·상충 확인 필요를 나누고, citations 에 인용한 문서 제목과 원문 구절(quoted_span)을 담아 근거를 추적합니다. quoted_span 은 LLM 이 자유 생성한 문장이 아니라 검색된 문단의 실제 구절이어야 하며, 이 값이 원문 문단의 부분 문자열인지로 채점합니다. 근거가 부족하면 답을 지어내지 않고 no_evidence·needs_field_check 로 넘깁니다.
{"type":"object","properties":{"question_id":{"type":"string"},"answer_status":{"type":"string","enum":["answered","no_evidence","needs_field_check"]},"answer_text":{"type":["string","null"]},"citations":{"type":"array","items":{"type":"object","properties":{"doc_title":{"type":"string"},"quoted_span":{"type":"string"}},"required":["doc_title","quoted_span"]}},"unsupported_flag":{"type":"boolean"},"confidence":{"type":"number"}},"required":["question_id","answer_status","citations","unsupported_flag"]}[
{
"question_id": "q03",
"answer_status": "answered",
"answer_text": "당일 출고 마감은 오후 3시입니다. 3시 이후 접수된 주문은 익영업일에 출고됩니다.",
"citations": [
{
"doc_title": "출고 마감 시간",
"quoted_span": "당일 출고 마감은 오후 3시입니다."
}
],
"unsupported_flag": false,
"confidence": 0.91
},
{
"question_id": "q08",
"answer_status": "no_evidence",
"answer_text": null,
"citations": [],
"unsupported_flag": true,
"confidence": 0.24
},
{
"question_id": "q02",
"answer_status": "needs_field_check",
"answer_text": "반품 기한이 문서마다 다릅니다. '반품 처리 절차(2024년판)'는 14일, '반품 정책 개정 안내(2026년 적용)'는 7일로 상충해 현장 확인이 필요합니다.",
"citations": [
{
"doc_title": "반품 처리 절차(2024년판)",
"quoted_span": "반품은 수령 후 14일 이내 신청 가능하며"
},
{
"doc_title": "반품 정책 개정 안내(2026년 적용)",
"quoted_span": "반품 신청 기한이 수령 후 7일로 단축됩니다"
}
],
"unsupported_flag": false,
"confidence": 0.44
}
][자동 검증, 규칙·결정론으로 채점] 1. JSON Schema 통과: 응답이 형식(question_id·answer_status·citations·unsupported_flag)을 지키는지. 깨지면 배포 차단. 2. 인용 실재: citations 의 각 quoted_span 이 해당 doc_title 문서 body 의 실제 부분 문자열인지(공백 정규화 후) 대조. 문단에 없는 구절을 지어내면 탈락. 3. 분류 일치: answer_status 를 정답 라벨과 대조. label_status=answered → answered, no_evidence → no_evidence, conflict → needs_field_check. 근거 없는 질문에 answered 를 내면(환각) 질문 단위로 집계. 4. no_evidence 규율: answer_status=no_evidence 이면 answer_text 는 null 이고 citations 는 비어야 함. 답을 채우면 위반. [수동 검증, 사람이 판단] 1. answered 로 채점된 답이 실제로 질문에 맞는지 현장 검수자 2명이 라벨링(bootstrap Cohen's κ(우연 이상 일치도) 하한 확인). 2. needs_field_check 로 넘긴 상충 건은 현장 담당자가 최신본을 확정해야 답 확정. confidence 는 합성 기준 추정이라 검증 수치가 아닙니다.