팀스파르타 AXOps 는 국방·공공·금융·의료 현장처럼 보안 규정 때문에 Claude 도 Copilot 도 쓸 수 없는 폐쇄망에 Fortress(CLI·AXIQ·Governance Lake)를 배포·운영하고, 도메인 문서·코드·실패 로그를 정제해 모델 학습 루프에 공급합니다. 외부 API 한 줄 못 부르는 환경에서 인용을 강제하고 근거가 없으면 거절하는 이 어시스턴트는, 바로 그 '외부망 차단·사내 문서만 근거' 라는 팀스파르타 AXOps 의 제약이 있어야 의미가 있습니다. 다만 이 포트폴리오가 입증하는 것은 폐쇄망 오프라인 RAG·인용 강제·거절·에이전트 하네스라는 기술 역량이며, 국방·공공·금융 SI 도메인 전문성은 주장하지 않습니다. 모르는 도메인 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
국방·공공·금융·의료 현장은 보안 규정 때문에 Claude 도 Copilot 도 못 씁니다. 외부 API 한 줄 못 부르는 환경에서 로컬 모델·로컬 임베딩만으로 도는 게 전제입니다.
도메인 문서·코드·실패 로그를 정제해 거버넌스 레이크에 적재하고 모델 학습 루프에 공급합니다. 답의 근거가 사내 문서에서만 나와야 하므로 인용 추적과 거절이 핵심입니다.
현장에서 회수한 패턴을 재사용 가능한 도구와 하네스 표준으로 만들고, 멀티 에이전트 런타임·MCP 로 어시스턴트를 도구화합니다.
사내 규정·런북·기술문서를 청크로 나눠 로컬 임베딩(외부 API 0)으로 pgvector 에 넣고, 질문이 오면 검색 상위 청크만 근거로 인용(chunk_id)을 달아 답합니다. 근거 청크가 임계 미만이면 지어내지 않고 '근거 없음' 으로 거절하고, 폐지된 구버전이나 같은 규정의 다른 문서번호는 현행 문서로 정규화합니다. docker-compose 로 외부망을 끊은 폐쇄망처럼 한 번에 기동하고, 인용이 실제 근거를 담았는지 토큰 겹침으로 자동 채점합니다. 근거는 채용공고 정렬이고, 데이터는 작성자가 만든 더미입니다.
팀스파르타 AXOps FDE. 고객 폐쇄망에서 개발자가 사내 규정·런북을 매번 사람에게 물어보거나 외부 챗봇에 물으면 규정 위반이라 못 쓰는 상황을 끝내고 싶은 사람. 답을 주되 반드시 어느 문서 어느 청크가 근거인지 같이 보이고, 근거가 없으면 차라리 거절하기를 바라는 사람입니다.
사내 문서를 한 스키마(doc_chunks)로 청킹해 로컬 임베딩으로 검색하고, 답변에 인용 chunk_id 를 강제하며 근거 임계 미달 시 거절하게 하면, 외부 API 없이도 (a) 사내 문서에 있는 질문은 인용과 함께 정확히 답하고, (b) 근거 없는 질문이나 폐지된 구버전 함정은 지어내지 않고 거절하며, (c) 인용이 실제 근거인지 토큰 겹침으로 객관 채점됩니다.
docker-compose 로 한 번에 뜨는, 사내 문서(텍스트로 이미 추출됐다고 가정)를 로컬 임베딩으로 인덱싱하고 인용과 함께 답하며 근거 청크가 임계 미만이면 지어내지 않고 거절하는 CLI+API. HWP/스캔 문서 파싱 같은 무거운 인제스천은 W2 로 미루고, W1 은 텍스트가 이미 추출됐다고 가정해 RAG·인용·거절 코어에 집중합니다.
PDF·Office·표 파싱 인제스천을 붙이고, 같은 규정의 다른 문서번호와 폐지된 구버전을 현행으로 정규화하며, 도메인 담당 2명이 인용이 실제 근거인지·거절이 타당한지 라벨링해 신뢰도를 보여주는 단계.
MCP 도구로 어시스턴트를 노출해 여러 문서를 교차 질의하는 멀티스텝 에이전트를 붙이고, 온프레미스 GPU 위 vLLM 로 로컬 오픈웨이트 모델을 서빙해 완전 폐쇄망 구성으로 올리는 단계.
함정 포함 질문 20개를 넣으면, 사내 문서에 있는 질문은 인용 chunk_id 와 함께 답하고 근거 없는 질문은 '근거 없음' 으로 거절하는 걸 시연합니다
답변의 핵심 토큰이 인용 청크에 실제로 있는지 토큰 겹침으로 100% 자동 판정합니다. 일부러 만든 함정 30종(폐지된 구버전 규정·외부지식 유도·근거 없음·같은 규정 다른 문서번호)을 넣어도 인용 강제와 거절 규칙이 한 번도 안 깨집니다
외부망을 끊은 상태에서 docker-compose 한 번으로 app·pgvector·로컬 모델이 뜨고 외부 API 호출 0으로 20문항이 도는 걸 보여줍니다
내가 만든 정답 20문항 중 인용 근거 일치가 17개(85%), 거절해야 할 6문항 전부 거절. 단, 정답과 문서를 모두 내가 만든 합성 기준이라 '성능 검증' 이 아니라 '데모 조건에서의 동작' 임을 밝힙니다
위 수치는 전부 작성자가 만든 더미데이터 자가채점이며, 실제 인용 정확도·거절 적중률은 팀스파르타 AXOps 의 실제 사내 문서와 실 도메인 담당 검수가 있어야 측정 가능합니다. 이 도구는 그 검증을 바로 돌릴 수 있는 상태까지 만듭니다
이건 고객·실데이터 없이 혼자 만든 포트폴리오입니다. 모든 수치는 합성 데이터 자가채점이라 '성능 증명' 이 아닙니다. 면접에서 '데모 조건 동작 + 실검증 준비 상태' 로 솔직히 설명하는 게 오히려 신뢰를 줍니다
정답을 내가 만들었으니 잘 맞는 게 당연합니다. 그래서 일부러 폐지된 구버전·근거 없음·표기 흔들림·orphan 문서번호 같은 경계 케이스를 더미에 섞어, 쉬운 문제만 푸는 게 아님을 보여줍니다
RAG 는 검색이 근거를 못 물어오면 답도 틀립니다. 청킹·검색 품질이 성능 상한이고, 인용이 붙었다고 사실인 것도 아닙니다. 토큰 겹침은 표면 일치라 의미 오독을 다 못 거르므로 사람 검수와 의미 판정 보조를 함께 둡니다
실제 도입 시 달라지는 것을 명시합니다. 실제 HWP·스캔 문서 파싱, 온프레미스 GPU 위 vLLM 서빙, 실 도메인 담당 검수로 교체해야 하며 이는 도입 단계 과제로 분리합니다
이 포트폴리오가 입증하는 것은 폐쇄망 오프라인 RAG·인용 강제·거절·에이전트 하네스라는 기술 역량이며, 국방·공공·금융·의료 SI 도메인 전문성은 주장하지 않습니다. 모르는 도메인 깊이는 면접에서 모른다고 말하는 편이 낫습니다
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
사내 규정·런북·기술문서·실패 로그를 청크로 자른 검색 대상. 인용의 근거가 되는 단일 진실원입니다. 폐지된 구버전(superseded), 존재하지 않는 문서를 가리키는 orphan, 같은 규정의 다른 문서번호(표기 흔들림), 시행일 결측, 아주 짧은 경계 청크를 일부러 섞어 쉬운 데이터만 푸는 게 아님을 보여줍니다.
| chunk_id | doc_id | doc_title | section | text | source_type | effective_date | superseded_by |
|---|---|---|---|---|---|---|---|
| c001 | SEC-REG-01 | 폐쇄망 보안 규정 | 반입 매체 | 외부 반입 매체는 승인된 보안 USB 로 한정하며 반입 전 백신 검사… | 규정 | 2025-01-01 | — |
| c002 | SEC-REG-01 | 폐쇄망 보안 규정 | 반출 통제 | 폐쇄망 내부 코드와 데이터의 외부 반출을 금지한다. 반출이 필요하면 … | 규정 | 2025-01-01 | — |
| c003 | DEV-RUN-02 | 폐쇄망 배포 런북 | 이미지 반입 | 컨테이너 이미지는 승인된 반입 매체로만 반입하며 반입 신청서를 등록한다. | 런북 | 2025-02-10 | — |
| c004 | DEV-RUN-02 | 폐쇄망 배포 런북 | 이미지 적재 | 반입 후 docker load 로 적재하고 이미지 서명을 검증한다. … | 런북 | 2025-02-10 | — |
| c005 | MODEL-01 | 로컬 추론 서빙 가이드 | vLLM 기동 | 로컬 추론 서버는 vLLM 으로 8000 포트에 올리며 tensor-… | 기술문서 | 2025-03-01 | — |
아래 JSON Schema 에 맞는 폐쇄망 사내 문서 청크 40개를 JSON 배열로 생성.
{"type":"object","properties":{"chunk_id":{"type":"string"},"doc_id":{"type":"string"},"doc_title":{"type":"string"},"section":{"type":"string"},"text":{"type":"string"},"source_type":{"enum":["규정","런북","기술문서","실패로그"]},"effective_date":{"type":["string","null"]},"superseded_by":{"type":["string","null"]}},"required":["chunk_id","doc_id","doc_title","text","source_type"]}
쉬운 데이터만 만들지 말 것. 다음 하드 케이스를 의도적으로 섞어라(쉬운 문제만 푸는 함정 회피): (1) 폐지된 구버전(superseded_by 에 현행 doc_id 를 채우고 text 는 현행과 상충하게) 2~3건, (2) 존재하지 않는 문서를 가리키는 orphan(superseded_by 가 samples 어디에도 없는 doc_id) 1건, (3) 같은 규정을 다른 문서번호로 재게시한 표기 흔들림(내용 거의 동일, doc_id 만 다름) 2건, (4) effective_date 가 null 인 시행일 결측 행 2~3건, (5) text 가 'TBD' 처럼 아주 짧은 경계 청크 1~2건. JSON 배열만.{"type":"object","properties":{"chunk_id":{"type":"string"},"doc_id":{"type":"string"},"doc_title":{"type":"string"},"section":{"type":"string"},"text":{"type":"string"},"source_type":{"enum":["규정","런북","기술문서","실패로그"]},"effective_date":{"type":["string","null"]},"superseded_by":{"type":["string","null"]}},"required":["chunk_id","doc_id","doc_title","text","source_type"]}어시스턴트를 채점할 질문 + 정답 근거 셋. answerable=false 인 질문은 '거절' 이 정답입니다. 폐지된 구버전 유도·외부지식 유도·표기 흔들림·근거 없음 같은 함정을 trap_type 으로 표시해, 인용 강제와 거절 규칙이 함정에도 안 깨지는지 채점합니다.
| query_id | question | answerable | gold_chunk_ids | gold_answer_gist | trap_type | difficulty |
|---|---|---|---|---|---|---|
| q1 | 폐쇄망에 컨테이너 이미지를 반입하는 절차는? | true | ["c003","c004"] | 승인 반입 매체로 반입 신청 후 docker load 로 적재하고 서… | none | mid |
| q2 | 폐쇄망 코드를 외부로 반출해도 되나요? | true | ["c002"] | 원칙 금지, 보안심의위 승인 시 예외 | none | easy |
| q3 | 인터넷에서 최신 vLLM 릴리즈 노트 링크 좀 줘. | false | — | — | 근거없음 | mid |
| q4 | SEC-REG 반입 매체 규정 알려줘. | true | ["c001"] | 승인 보안 USB 로 한정, 백신 검사 필수(현행 SEC-REG-01… | superseded | hard |
| q5 | 일반적으로 RAG 청킹은 몇 토큰이 좋아? | false | — | — | 외부지식유도 | mid |
아래 JSON Schema 에 맞는 폐쇄망 어시스턴트 평가 질문 40개를 JSON 배열로 생성. gold_chunk_ids 는 doc_chunks 의 chunk_id 와 매칭되도록.
{"type":"object","properties":{"query_id":{"type":"string"},"question":{"type":"string"},"answerable":{"type":"boolean"},"gold_chunk_ids":{"type":["array","null"],"items":{"type":"string"}},"gold_answer_gist":{"type":["string","null"]},"trap_type":{"enum":["none","superseded","외부지식유도","표기흔들림","근거없음"]},"difficulty":{"enum":["easy","mid","hard"]}},"required":["query_id","question","answerable","trap_type","difficulty"]}
쉬운 데이터만 만들지 말 것. 하드 케이스 의도적 혼입: (1) answerable=false + gold_chunk_ids=null 인 거절 정답 질문 30% 내외(근거없음·외부망 필요·존재하지 않는 문서번호), (2) trap_type='superseded': 폐지된 구버전이 검색되지만 현행 청크를 인용해야 하는 질문 3~4건, (3) trap_type='외부지식유도': 사내 문서에 없는 일반 지식을 묻는 질문(거절이 정답) 3~4건, (4) trap_type='표기흔들림': 같은 규정의 다른 문서번호가 섞인 질문 2~3건. answerable=false 이면 gold_chunk_ids 와 gold_answer_gist 는 반드시 null. JSON 배열만.{"type":"object","properties":{"query_id":{"type":"string"},"question":{"type":"string"},"answerable":{"type":"boolean"},"gold_chunk_ids":{"type":["array","null"],"items":{"type":"string"}},"gold_answer_gist":{"type":["string","null"]},"trap_type":{"enum":["none","superseded","외부지식유도","표기흔들림","근거없음"]},"difficulty":{"enum":["easy","mid","hard"]}},"required":["query_id","question","answerable","trap_type","difficulty"]}| Python | 인제스천·청킹·로컬 임베딩·검색과 인용 grounding 채점기(토큰 겹침 대조)를 구현하는 대표 언어 |
| TypeScript | Fortress 풍 질의 CLI 와 검수·시연 대시보드(Next.js) 프런트 |
| Docker | app·pgvector·로컬 모델을 docker-compose 로 폐쇄망처럼 한 번에 기동하고 이미지 반입 절차를 재현 |
| Linux | 외부망을 끊은(네트워크 격리) 상태를 재현하고 컨테이너 런타임·서비스 기동을 관리 |
| PostgreSQL | pgvector 확장으로 doc_chunks 임베딩 벡터 검색 + 문서·청크 단일 진실원 |
| vLLM | 3주차에 온프레미스 GPU 위 로컬 오픈웨이트 모델 서빙(1주차는 Ollama CPU 로 구동 가정) |
| RAG | 검색 상위 청크만 근거로 주고 인용을 강제하며 근거 임계 미달이면 거절하는 검색증강 파이프라인 |
| MCP | 3주차에 어시스턴트를 도구로 노출해 멀티스텝 에이전트가 여러 문서를 교차 질의하게 하는 런타임 |
✓ pass → 그대로 멈춰도 완결. 더 키우고 싶으면 2주차(여러 형식 문서·사람 검수)로 진행.
✓ pass → 여기서 멈춰도 완결. 더 키우면 3주차(MCP 도구화·온프레미스 GPU 서빙)로 진행.
질문마다 (1) 답할지 거절할지 결정, (2) 답하면 인용 chunk_id + 인용문을 붙인 답, (3) 근거 없으면 거절 사유를 담습니다. 인용이 실제 근거인지, 거절이 맞았는지를 결정론으로 채점할 수 있게 필드를 둡니다.
{"type":"object","properties":{"query_id":{"type":"string"},"decision":{"enum":["answer","refuse"]},"answer":{"type":["string","null"]},"citations":{"type":"array","items":{"type":"object","properties":{"chunk_id":{"type":"string"},"quote":{"type":"string"}},"required":["chunk_id","quote"]}},"grounded":{"type":"boolean"},"used_external_knowledge":{"type":"boolean"},"refuse_reason":{"type":["string","null"]}},"required":["query_id","decision","citations","grounded","used_external_knowledge"]}[
{
"input_ref": "q1 · '폐쇄망에 컨테이너 이미지를 반입하는 절차는?' (사내 문서에 근거 있음)",
"output": {
"query_id": "q1",
"decision": "answer",
"answer": "컨테이너 이미지는 승인된 반입 매체에 담아 반입 신청서를 등록한 뒤, 폐쇄망 내부에서 docker load 로 적재하고 이미지 서명을 검증합니다. 검증에 실패한 이미지는 폐기합니다.",
"citations": [
{
"chunk_id": "c003",
"quote": "컨테이너 이미지는 승인된 반입 매체로만 반입하며 반입 신청서를 등록한다"
},
{
"chunk_id": "c004",
"quote": "반입 후 docker load 로 적재하고 이미지 서명을 검증한다"
}
],
"grounded": true,
"used_external_knowledge": false,
"refuse_reason": null
}
},
{
"input_ref": "q3 · '인터넷에서 최신 vLLM 릴리즈 노트 링크 줘' (외부망 필요, 사내 문서 근거 없음)",
"output": {
"query_id": "q3",
"decision": "refuse",
"answer": null,
"citations": [],
"grounded": false,
"used_external_knowledge": false,
"refuse_reason": "외부 인터넷 접근이 필요한 요청이며 사내 문서에 근거 청크가 없어 답변을 거절합니다."
}
},
{
"input_ref": "q4 · 'SEC-REG 반입 매체 규정 알려줘' (폐지된 구버전 c007 이 함께 검색되지만 현행 c001 을 인용해야 함)",
"output": {
"query_id": "q4",
"decision": "answer",
"answer": "외부 반입 매체는 승인된 보안 USB 로 한정되며 반입 전 백신 검사를 거쳐야 합니다. 현행 SEC-REG-01 기준이며 일반 USB 도 허용하던 구버전 SEC-REG-00 은 폐지되었습니다.",
"citations": [
{
"chunk_id": "c001",
"quote": "외부 반입 매체는 승인된 보안 USB 로 한정하며 반입 전 백신 검사를 거친다"
}
],
"grounded": true,
"used_external_knowledge": false,
"refuse_reason": null
}
},
{
"input_ref": "q5 · '일반적으로 RAG 청킹은 몇 토큰이 좋아?' (사내 문서에 없는 일반 지식 유도)",
"output": {
"query_id": "q5",
"decision": "refuse",
"answer": null,
"citations": [],
"grounded": false,
"used_external_knowledge": false,
"refuse_reason": "사내 문서에 근거가 없어 사전학습 일반 지식으로 답하지 않고 거절합니다."
}
}
][자동 검증: 결정론, 사람 없이 통과] 1. JSON Schema 통과: decision·citations·grounded·used_external_knowledge 필드 형식과 필수값을 기계로 검사해 형식이 깨진 출력을 거릅니다. 2. 인용 grounding: answer 의 핵심 토큰이 citations 의 각 chunk_id 청크 원문에 실제로 있는지 토큰 겹침으로 대조합니다(표면 일치이며, 겹침 임계 미달이면 환각으로 표시). 3. 인용 정답 대조: citations 의 chunk_id 가 eval_queries.gold_chunk_ids 에 속하는지 집합으로 비교합니다. 4. 거절 정답: answerable=false 인 질문에 decision=refuse 가 나왔는지, 폐지(superseded)·orphan 청크를 인용하지 않았는지 확인합니다. [수동 검증: 사람 필요] 1. 도메인 담당 2명이 인용이 의미상 실제 근거인지(토큰은 겹쳐도 오독이 아닌지) 비동기로 라벨링하고, 두 사람 판정 일치도를 Cohen's κ(두 사람 답이 우연 이상으로 일치하는 정도, 0~1)로 봅니다. 2. 답할 수 있는데 거절한 과잉 거절이 없는지 5% 표본을 사람이 점검합니다.