올거나이즈코리아
경력근거: 금융/대기업 고객 환경에서 보안, 권한, latency, 비용까지 고려한 AI 서비스를 개발합니다.
올거나이즈는 노코드 앱 빌더로 고객사 부서가 앱을 직접 만들어 쓰는 구조라, 한 고객사 안에 성격이 다른 앱이 여럿 떠 있고 앱마다 지켜야 할 응답 시간과 비용이 다릅니다. 공고가 해결할 문제로 든 보안·권한·응답시간·비용 네 가지는 답변 한 건에서 동시에 갈리는 값이라, 앱을 하나만 두고 보는 회사에서는 이 화면이 성립하지 않습니다. 이 포트폴리오는 답변 로그와 권한표를 키로 붙여 판정을 내는 기술을 보여줍니다. 금융권 보안 심사나 개인정보 규제 해석에 대한 전문성은 주장하지 않고, 모르는 깊이는 면접에서 모른다고 말합니다.
공고는 해결할 문제로 '금융/대기업 고객 환경에서 보안, 권한, latency, 비용까지 고려한 AI 서비스를 개발합니다' 를 듭니다. 이 편은 그 네 가지를 답변 한 건 단위로 견주는 화면을 만듭니다.
'노코드 LLM 앱 빌더 및 앱 마켓' 으로 부서가 직접 앱을 만들어 씁니다. 앱 수가 늘수록 어느 앱이 무엇을 어겼는지는 앱별 약속치를 옆에 두지 않으면 알기 어렵습니다.
'프롬프트 엔지니어링, Agent Workflow 구축, RAG 파이프라인 최적화' 가 주요 업무입니다. 인용 문서 id 와 토큰 수는 그 파이프라인이 남기는 값이라, 판정 입력을 만드는 일이 곧 백엔드 일입니다.
어제 오간 답변 로그를 인사 권한표와 문서 열람 권한표에 맞춰 건마다 판정합니다. 인용한 문서가 질문자 직급의 열람 목록에 있는지, 문서 보안등급이 질문자 등급을 넘지 않는지 보고, 이어서 앱이 약속한 최소 인용 건수와 응답 시간, 한 건 비용을 견줍니다. 걸린 건은 권한 밖 문서 인용, 근거 없는 답변, 응답 지연 한도 초과, 답변 비용 한도 초과 중 하나로 묶여 앱별로 정렬됩니다. 응답 시간이 비어 있으면 지연은 판정하지 않고 그 사실을 화면에 함께 띄웁니다. 답변 로그와 권한표는 지원자가 공개된 직급 체계와 토큰 과금 방식으로 지어낸 것이며 실제 고객사 자료를 쓰지 않습니다.
은행·증권사 안에서 부서별 사내 문서 질의응답 앱을 열어 두고 굴리는 AI 도입 담당자 — 하루 수천 건 답변이 오가는데, 어느 답이 권한 밖 문서를 물었는지, 어느 앱이 약속한 응답 시간과 비용을 넘겼는지는 답변 로그와 인사 권한표를 나란히 놓기 전에는 아무도 모른다
답변 로그가 인용 문서 id 와 질문자 id 를 남기고 있으니, 문서 열람 권한표와 인사 권한표를 같은 키로 붙이면 권한 밖 인용은 사람이 훑기 전에 목록으로 먼저 뜬다는 가정입니다. 응답 시간과 토큰 수도 같은 로그에 있어, 앱마다 약속한 한도와 견주면 지연과 비용도 같은 판정 흐름에 얹힙니다.
답변 로그와 문서 열람 권한표, 인사 권한표, 앱 약속치, 모델 단가표를 올리면 답변마다 판정이 붙고 사유별 묶음과 근거가 한 화면에 뜹니다. 1주차는 고객사 클러스터에 직접 붙지 않고 관리 화면에서 내려받은 로그 파일을 그대로 읽는 것으로 시작합니다.
이틀치 답변 240건에 손으로 붙인 판정과 대조해 일치율을 내고, 어긋난 건이 권한표 쪽인지 한도 계산 쪽인지 나눠 리포트로 냅니다. 2주차부터 판정 배치와 화면을 쿠버네티스 클러스터에 같은 차트로 올려 담당자가 주소로 들어와 씁니다.
인용 문서가 붙은 검색 단계를 로그에서 되짚어, 권한 밖 문서가 색인 자체에 들어와 있었는지 재순위에서 올라왔는지 나눠 보여주는 단계입니다.
담당자가 답변 로그와 권한표를 올리면 답변마다 판정이 사유별로 묶여 뜨고, 어느 값이 그 판정을 만들었는지 그 자리에서 펼쳐집니다.
응답 시간이 비어 있는 건, 질문자 등급이 비어 있는 건, 인용을 하나도 달지 않은 건을 섞은 입력 30종을 넣어도 화면이 죽지 않고 그 답변이 왜 일부 판정을 건너뛰었는지 읽힙니다.
이틀치 답변 240건에 손으로 붙인 판정과 대조해 일치율을 냅니다. 단, 로그와 권한표와 정답을 모두 작성자가 만든 합성 기준이라 성능 검증이 아니라 데모 조건 동작입니다.
열 이름이 빠지거나 토큰 칸이 비거나 인코딩이 깨진 파일 12종을 올려도 목록 대신 어느 줄이 왜 걸렸는지 이슈로 뜨고 나머지 답변은 그대로 판정됩니다.
진짜 성능 검증은 여기서 멈춥니다. 위 수치는 지어낸 로그의 자가채점이며, 실제 적발률은 올거나이즈 고객사의 실 답변 로그와 실 권한표가 있어야 측정됩니다. 이 포트폴리오는 그 대조를 바로 돌릴 수 있는 상태로 만듭니다.
일치율은 제가 지어낸 답변 로그와 권한표에 제가 붙인 정답을 맞춰 본 자가채점이라 적발률이 아닙니다. 고객사마다 직급 체계와 문서 등급 단계가 달라 실제 수치는 그 환경에서만 나오므로, 면접에서는 데모가 도는 모습과 고객사 로그를 받았을 때 바로 돌릴 수 있는 상태까지를 말씀드립니다.
정답을 작성자가 붙였으니 잘 맞는 것이 당연합니다. 응답 시간이 비어 있는 건과 등급이 비어 있는 질문자, 인용이 하나도 없는 답변, 한도와 값이 똑같은 답변을 더미에 일부러 섞어 쉬운 줄만 푸는 함정을 피합니다.
이 포트폴리오가 보여주는 것은 답변 로그와 권한표를 키로 붙여 규칙으로 판정하는 기술입니다. 금융권 보안 심사 기준이나 개인정보 규제 해석에 대한 전문성은 주장하지 않고, 모르는 깊이는 면접에서 모른다고 말하는 편이 낫습니다.
권한 밖 문서를 인용했다는 사실이 곧 정보가 새어 나갔다는 뜻은 아닙니다. 답변 본문에 그 내용이 실렸는지는 사람이 열어 봐야 갈리므로, 화면은 확인할 목록까지만 내고 결론을 적지 않습니다.
판정은 하루 한 번 받은 로그가 담은 시점의 권한을 말합니다. 인사이동으로 직급이 바뀌면 어제까지 맞던 인용이 오늘은 어긋나므로, 권한표를 언제 받아 언제 반영할지 정하는 일을 도입 단계 과제로 둡니다.
실제 도입에서는 고객사마다 직급 체계와 보안등급 단계 수가 다르고, 온프레미스 고객사는 로그를 밖으로 내보내지 않습니다. 등급 체계를 설정으로 빼고 판정 배치를 고객사 안에서 돌리는 구성은 도입 단계 과제로 분리합니다.
① 인라인 샘플 · ② seed.json 다운로드 · ③ 증강 프롬프트. 세 층 모두 동일한 schema 에서 파생.
AI 앱이 어제 하루 낸 답변 기록입니다. 판정 대상이며 한 행이 답변 한 건입니다. 인용한 문서 목록과 질문자, 응답 시간, 넣고 뺀 토큰 수, 쓴 모델이 한 행에 있습니다. 응답 시간이 비어 있는 건과 인용을 하나도 달지 않은 건, 한도와 값이 똑같은 건을 일부러 섞어 판정이 갈리게 두었습니다. 모든 값은 지어낸 것이며 실제 고객사 답변을 담지 않습니다.
| answer_id | app_id | asker_id | asked_at | cited_doc_ids | latency_ms | input_tokens | output_tokens | model |
|---|---|---|---|---|---|---|---|---|
| A-88201 | APP-101 | U-2041 | 2026-09-07T09:12:00 | ["DOC-1102","DOC-1107"] | 4,200 | 9,800 | 620 | claude-sonnet-4.5 |
| A-88208 | APP-106 | U-2052 | 2026-09-07T09:41:00 | ["DOC-1120","DOC-1121"] | 6,400 | 12,400 | 810 | claude-haiku-4.5 |
| A-88214 | APP-101 | U-2044 | 2026-09-07T10:05:00 | ["DOC-1102","DOC-1109","DOC-1131"] | 5,100 | 14,200 | 940 | claude-sonnet-4.5 |
| A-88231 | APP-102 | U-2058 | 2026-09-07T10:22:00 | [] | 3,100 | 5,400 | 260 | claude-haiku-4.5 |
| A-88245 | APP-103 | U-2047 | 2026-09-07T10:48:00 | ["DOC-1114","DOC-1115"] | 41,200 | 88,000 | 3,100 | claude-sonnet-4.5 |
아래 JSON Schema 를 그대로 만족하는 답변 기록을 240개 더 만들어 주세요. 앱을 열 개쯤 두고 앱마다 하루 스무 건에서 마흔 건씩 붙이며, 인용 문서는 0건에서 5건 사이로 흩습니다. 응답 시간은 2초에서 45초 사이로 두되 2할은 비웁니다. 넣은 토큰은 3천에서 9만 사이, 뺀 토큰은 200에서 4천 사이로 두고, 모델은 단가표에 있는 이름만 씁니다. 실제 사람이나 실제 고객사의 정보를 쓰지 말고 판정 결과도 넣지 마세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 응답 시간이 비어 있는 건, (2) 인용이 0건인 건, (3) 응답 시간이 앱 한도와 정확히 같은 건, (4) 넣은 토큰이 5만을 넘어 비용이 앱 한도를 훌쩍 넘는 건. 생성한 행은 반드시 위 스키마를 통과해야 하며, 헤더가 빠지거나 인코딩이 깨진 형식 깨뜨리기 시도는 별도로 3건만 표시해 두세요.
{"type": "object", "properties": {"answer_id": {"type": "string"}, "app_id": {"type": "string"}, "asker_id": {"type": "string"}, "asked_at": {"type": "string"}, "cited_doc_ids": {"type": "array", "items": {"type": "string"}}, "latency_ms": {"type": ["integer", "null"], "minimum": 0}, "input_tokens": {"type": "integer", "minimum": 0}, "output_tokens": {"type": "integer", "minimum": 0}, "model": {"type": "string"}}, "required": ["answer_id", "app_id", "asker_id", "asked_at", "cited_doc_ids", "latency_ms", "input_tokens", "output_tokens", "model"]}{"type": "object", "properties": {"answer_id": {"type": "string"}, "app_id": {"type": "string"}, "asker_id": {"type": "string"}, "asked_at": {"type": "string"}, "cited_doc_ids": {"type": "array", "items": {"type": "string"}}, "latency_ms": {"type": ["integer", "null"], "minimum": 0}, "input_tokens": {"type": "integer", "minimum": 0}, "output_tokens": {"type": "integer", "minimum": 0}, "model": {"type": "string"}}, "required": ["answer_id", "app_id", "asker_id", "asked_at", "cited_doc_ids", "latency_ms", "input_tokens", "output_tokens", "model"]}사내 문서마다 누가 열람할 수 있는지 적힌 표입니다. 열람 직급 목록과 보안등급 두 갈래로 권한을 정하며, 판정에 쓰이는 기준은 답변 기록에 붙어 있지 않고 전부 이 표에서 옵니다. 감사역·임원만 열람하는 높은 등급 문서와 전 직급이 보는 낮은 등급 문서를 함께 담았습니다.
| doc_id | allowed_roles | security_level |
|---|---|---|
| DOC-1102 | ["행원","대리","과장","차장","부장"] | 2 |
| DOC-1105 | ["행원","대리","과장","차장","부장"] | 1 |
| DOC-1107 | ["대리","과장","차장","부장"] | 2 |
| DOC-1109 | ["과장","차장","부장"] | 2 |
| DOC-1114 | ["대리","과장","차장","부장"] | 2 |
아래 JSON Schema 를 그대로 만족하는 문서 권한 행을 120개 더 만들어 주세요. 보안등급을 1에서 4까지 고루 두고, 등급이 높을수록 열람 직급 목록을 좁게 잡습니다. 4등급에는 임원이나 감사역만 남기고, 1등급에는 다섯 직급을 모두 넣습니다. 답변 기록에 나오는 문서 번호를 대부분 덮되 일부는 일부러 넣지 마세요. 판정 결과는 넣지 마세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 등급은 낮은데 열람 직급이 한 자리뿐인 문서, (2) 등급은 높은데 열람 직급이 넓은 문서, (3) 답변 기록에 없는 문서 번호. 생성한 행은 반드시 위 스키마를 통과해야 합니다.
{"type": "object", "properties": {"doc_id": {"type": "string"}, "allowed_roles": {"type": "array", "items": {"type": "string"}}, "security_level": {"type": "integer", "minimum": 1, "maximum": 4}}, "required": ["doc_id", "allowed_roles", "security_level"]}{"type": "object", "properties": {"doc_id": {"type": "string"}, "allowed_roles": {"type": "array", "items": {"type": "string"}}, "security_level": {"type": "integer", "minimum": 1, "maximum": 4}}, "required": ["doc_id", "allowed_roles", "security_level"]}질문자의 소속과 직급, 보안등급이 적힌 인사 권한표입니다. 답변 기록의 질문자 번호와 같은 키로 붙습니다. 등급 칸이 비어 있는 사람을 한 명 두어, 등급 비교를 건너뛰고 직급 목록만으로 판정하는 갈래가 데이터에서 드러나게 했습니다.
| asker_id | dept | role | clearance_level |
|---|---|---|---|
| U-2041 | 여신심사부 | 과장 | 2 |
| U-2043 | 인재개발부 | 행원 | 1 |
| U-2044 | 여신심사부 | 대리 | 2 |
| U-2047 | 리서치센터 | 차장 | 3 |
| U-2049 | 상품기획부 | 대리 | 2 |
아래 JSON Schema 를 그대로 만족하는 인사 권한 행을 90개 더 만들어 주세요. 부서를 열 곳쯤 두고 직급은 행원·대리·과장·차장·부장으로 흩으며, 보안등급은 직급이 높을수록 크게 잡되 1할은 비웁니다. 감사부와 준법감시부에는 감사역 직급을 몇 명 넣습니다. 실제 사람의 정보를 쓰지 말고 판정 결과도 넣지 마세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 등급 칸이 비어 있는 사람, (2) 직급은 낮은데 등급이 높은 사람, (3) 답변 기록에 한 번도 안 나오는 사람. 생성한 행은 반드시 위 스키마를 통과해야 합니다.
{"type": "object", "properties": {"asker_id": {"type": "string"}, "dept": {"type": "string"}, "role": {"type": "string"}, "clearance_level": {"type": ["integer", "null"], "minimum": 1, "maximum": 4}}, "required": ["asker_id", "dept", "role", "clearance_level"]}{"type": "object", "properties": {"asker_id": {"type": "string"}, "dept": {"type": "string"}, "role": {"type": "string"}, "clearance_level": {"type": ["integer", "null"], "minimum": 1, "maximum": 4}}, "required": ["asker_id", "dept", "role", "clearance_level"]}앱마다 고객사와 약속한 최소 인용 건수와 응답 시간, 한 건 비용이 적힌 기준표입니다. 앱 빌더로 만든 앱이라 성격이 제각각이고, 콜센터 상담처럼 빨라야 하는 앱과 준법 점검처럼 오래 걸려도 되는 앱이 같은 고객사 안에 함께 있습니다.
| app_id | app_name | max_latency_ms | max_cost_per_answer | min_citation_count |
|---|---|---|---|---|
| APP-101 | 여신심사 문의 | 20,000 | 600 | 1 |
| APP-102 | 콜센터 상담 | 8,000 | 300 | 2 |
| APP-103 | 리서치 요약 | 20,000 | 900 | 1 |
| APP-104 | 상품 안내 | 12,000 | 300 | 1 |
| APP-105 | 내부감사 질의 | 30,000 | 1,200 | 2 |
아래 JSON Schema 를 그대로 만족하는 앱 기준 행을 40개 더 만들어 주세요. 응답 시간 한도를 5초에서 60초 사이로, 한 건 비용 한도를 100원에서 2,000원 사이로, 최소 인용 건수를 0에서 3 사이로 흩습니다. 상담처럼 빨라야 하는 앱은 시간 한도를 좁게, 조사·점검 앱은 넓게 잡습니다. 판정 결과는 넣지 마세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 최소 인용 건수가 0인 앱, (2) 비용 한도가 100원대로 빡빡한 앱, (3) 시간 한도와 비용 한도가 둘 다 넉넉한 앱. 생성한 행은 반드시 위 스키마를 통과해야 합니다.
{"type": "object", "properties": {"app_id": {"type": "string"}, "app_name": {"type": "string"}, "max_latency_ms": {"type": "integer", "minimum": 0}, "max_cost_per_answer": {"type": "integer", "minimum": 0}, "min_citation_count": {"type": "integer", "minimum": 0}}, "required": ["app_id", "app_name", "max_latency_ms", "max_cost_per_answer", "min_citation_count"]}{"type": "object", "properties": {"app_id": {"type": "string"}, "app_name": {"type": "string"}, "max_latency_ms": {"type": "integer", "minimum": 0}, "max_cost_per_answer": {"type": "integer", "minimum": 0}, "min_citation_count": {"type": "integer", "minimum": 0}}, "required": ["app_id", "app_name", "max_latency_ms", "max_cost_per_answer", "min_citation_count"]}모델별 1천 토큰 단가표입니다. 원 단위이며 넣은 토큰과 뺀 토큰 단가가 따로 있습니다. 한 건 비용은 답변 기록에 적혀 있지 않고 이 표와 곱해야 나오므로, 같은 답변이라도 어느 모델로 냈는지에 따라 비용 판정이 갈라집니다.
| model | input_price_per_1k | output_price_per_1k |
|---|---|---|
| claude-sonnet-4.5 | 4 | 20 |
| claude-haiku-4.5 | 1 | 5 |
| claude-opus-4.1 | 25 | 125 |
| gpt-4o | 3.5 | 14 |
| gpt-4o-mini | 0.2 | 0.8 |
아래 JSON Schema 를 그대로 만족하는 모델 단가 행을 20개 더 만들어 주세요. 넣은 토큰 단가를 0.2원에서 30원 사이, 뺀 토큰 단가를 0.4원에서 150원 사이로 두고 뺀 토큰 단가를 항상 더 비싸게 잡습니다. 온프레미스로 띄우는 오픈웨이트 모델은 두 단가를 같게 두고 값을 낮게 잡습니다. 판정 결과는 넣지 마세요. 쉬운 데이터만 만들지 말 것 — 다음 하드 케이스를 의도적으로 섞어라: (1) 두 단가가 같은 온프레미스 모델, (2) 뺀 토큰 단가가 넣은 토큰의 다섯 배인 모델, (3) 답변 기록에 한 번도 안 쓰인 모델. 생성한 행은 반드시 위 스키마를 통과해야 합니다.
{"type": "object", "properties": {"model": {"type": "string"}, "input_price_per_1k": {"type": "number", "minimum": 0}, "output_price_per_1k": {"type": "number", "minimum": 0}}, "required": ["model", "input_price_per_1k", "output_price_per_1k"]}{"type": "object", "properties": {"model": {"type": "string"}, "input_price_per_1k": {"type": "number", "minimum": 0}, "output_price_per_1k": {"type": "number", "minimum": 0}}, "required": ["model", "input_price_per_1k", "output_price_per_1k"]}| Python | 답변 로그와 권한표를 읽어 건마다 권한·인용·지연·비용을 견주는 판정기를 맡습니다. 판정 순서는 이 코드 한 곳에만 둡니다. |
| FastAPI | 판정 결과를 화면에 넘기고 하루치 재판정을 받는 API 입니다. |
| Django | 앱 약속치와 모델 단가표를 담당자가 직접 고치는 뒤쪽 화면을 붙입니다. |
| Node.js | 관리자 페이지를 띄우는 실행 환경입니다. |
| Spring | 고객사가 이미 Spring 으로 운영하는 인사 시스템에서 직급과 등급을 받아 오는 연동 어댑터를 맡습니다. |
| Kubernetes | 2주차부터 판정 배치와 화면을 같은 차트로 올립니다. 온프레미스 고객사도 같은 차트를 씁니다. |
| PostgreSQL | 답변 로그와 두 권한표, 앱 약속치, 단가표를 담습니다. 인용 문서 id 에 건 인덱스가 하루치 대조 시간을 좌우합니다. |
| RAG | 인용 문서 id 가 어느 검색 단계에서 붙었는지 되짚어, 권한 밖 문서가 들어온 자리를 3주차에 좁힙니다. |
| LangChain | 답변 생성 흐름에서 인용 문서 id 와 토큰 수를 로그로 남기는 자리를 맡습니다. |
| LangGraph | 재판정을 단계로 나눠 실패한 단계만 다시 돌립니다. |
| Langfuse | 답변 한 건의 토큰 수와 응답 시간을 남겨 판정 입력으로 씁니다. |
| LLM | 판정이 끝난 뒤 담당자가 고객사에 회신할 문장을 씁니다. 판정 다섯 값에는 손대지 못합니다. |
| Claude | 회신 문장을 쓰는 기본 모델입니다. |
| Claude Code | 판정 규칙 시험과 더미데이터 증강 스크립트를 쓰는 데 씁니다. 만든 코드는 시험을 돌려 확인한 뒤 넣습니다. |
✗ fail → 권한표가 답변에 나오는 문서를 절반도 덮지 못하면 표를 먼저 채웁니다.
✓ pass → 그대로 멈춰도 완결입니다. 더 키우려면 손으로 정한 240건과 판정을 맞춰 보는 단계로 넘어갑니다.
✗ fail → 일치율이 낮은 사유 한 갈래에 어긋남이 몰리면 그 갈래의 판정 순서를 다시 봅니다.
✓ pass → 여기까지도 완결입니다. 더 키우려면 권한 밖 문서가 어느 검색 단계에서 들어왔는지 되짚는 단계로 확장합니다.
위 예측 UI 는 3주차까지 완주했을 때의 화면입니다. 1주차에 실제로 만드는 것은 아래 표시된 화면 하나입니다.
verdict사유 라벨 · answer_id + 한 줄 요약(근거 수치 포함)화면·코드·면접에서 이 단어를 그대로 씁니다. 키는 출력 스키마의 enum 과 같습니다.
권한 밖 문서 인용권한 밖 인용근거 없는 답변근거 없음응답 지연 한도 초과응답 지연답변 비용 한도 초과비용 초과근거·권한·한도 모두 맞음모두 맞음답변 한 건에 대한 권한·근거·한도 판정과 그 판정을 만든 값을 남기는 형식입니다. 판정 다섯 값은 대조와 계산 규칙이 정하고 회신 문장만 모델이 씁니다. 화면은 이 판정 값으로 묶습니다.
{"type": "object", "properties": {"check_no": {"type": "string"}, "answer_id": {"type": "string"}, "app_id": {"type": "string"}, "asker_id": {"type": "string"}, "verdict": {"type": "string", "enum": ["근거·권한·한도 모두 맞음", "권한 밖 문서 인용", "근거 없는 답변", "응답 지연 한도 초과", "답변 비용 한도 초과"]}, "blocked_doc_ids": {"type": "array", "items": {"type": "string"}, "description": "권한 밖으로 걸린 문서 번호를 모두 담습니다. 한 답변이 문서를 여럿 인용해 둘 이상이 걸리면 전부 싣고, 걸린 문서가 없으면 빈 배열입니다"}, "cited_doc_count": {"type": "integer", "minimum": 0, "description": "answer_log.cited_doc_ids 의 개수입니다"}, "answer_cost_krw": {"type": ["number", "null"], "minimum": 0, "description": "answer_log.input_tokens ÷ 1000 × model_price.input_price_per_1k 에 answer_log.output_tokens ÷ 1000 × model_price.output_price_per_1k 를 더한 한 건 값입니다"}, "evidence": {"type": "array", "items": {"type": "object", "properties": {"dataset": {"type": "string"}, "field": {"type": "string"}, "agg": {"type": ["string", "null"]}, "value": {"type": ["string", "number", "boolean", "null"]}}, "required": ["dataset", "field", "value"]}}, "summary": {"type": "string"}, "hedge": {"type": ["string", "null"]}}, "required": ["check_no", "answer_id", "app_id", "asker_id", "verdict", "evidence", "summary"]}[
{
"check_no": "AC-001",
"answer_id": "A-88201",
"app_id": "APP-101",
"asker_id": "U-2041",
"verdict": "근거·권한·한도 모두 맞음",
"blocked_doc_ids": [],
"cited_doc_count": 2,
"answer_cost_krw": 51.6,
"evidence": [
{
"dataset": "doc_acl",
"field": "security_level",
"agg": null,
"value": 2
},
{
"dataset": "member_directory",
"field": "clearance_level",
"agg": null,
"value": 2
},
{
"dataset": "answer_log",
"field": "latency_ms",
"agg": null,
"value": 4200
},
{
"dataset": "app_sla",
"field": "max_latency_ms",
"agg": null,
"value": 20000
},
{
"dataset": "app_sla",
"field": "max_cost_per_answer",
"agg": null,
"value": 600
}
],
"summary": "인용한 두 문서가 과장 열람 범위 안이고 응답 시간과 한 건 비용도 여신심사 문의 앱 약속치 안입니다.",
"hedge": null
},
{
"check_no": "AC-002",
"answer_id": "A-88208",
"app_id": "APP-106",
"asker_id": "U-2052",
"verdict": "근거·권한·한도 모두 맞음",
"blocked_doc_ids": [],
"cited_doc_count": 2,
"answer_cost_krw": 16.45,
"evidence": [
{
"dataset": "answer_log",
"field": "cited_doc_ids",
"agg": "count",
"value": 2
},
{
"dataset": "app_sla",
"field": "min_citation_count",
"agg": null,
"value": 2
},
{
"dataset": "doc_acl",
"field": "security_level",
"agg": null,
"value": 2
},
{
"dataset": "member_directory",
"field": "role",
"agg": null,
"value": "과장"
},
{
"dataset": "answer_log",
"field": "latency_ms",
"agg": null,
"value": 6400
}
],
"summary": "여신 규정 조회 앱이 요구하는 인용 두 건을 채웠고 두 문서 모두 과장이 열람할 수 있는 등급입니다.",
"hedge": null
},
{
"check_no": "AC-003",
"answer_id": "A-88214",
"app_id": "APP-101",
"asker_id": "U-2044",
"verdict": "권한 밖 문서 인용",
"blocked_doc_ids": [
"DOC-1109",
"DOC-1131"
],
"cited_doc_count": 3,
"answer_cost_krw": 75.6,
"evidence": [
{
"dataset": "answer_log",
"field": "cited_doc_ids",
"agg": "count",
"value": 3
},
{
"dataset": "doc_acl",
"field": "doc_id",
"agg": null,
"value": "DOC-1109"
},
{
"dataset": "doc_acl",
"field": "allowed_roles",
"agg": null,
"value": "과장"
},
{
"dataset": "doc_acl",
"field": "doc_id",
"agg": null,
"value": "DOC-1131"
},
{
"dataset": "doc_acl",
"field": "security_level",
"agg": null,
"value": 4
},
{
"dataset": "member_directory",
"field": "role",
"agg": null,
"value": "대리"
},
{
"dataset": "member_directory",
"field": "clearance_level",
"agg": null,
"value": 2
}
],
"summary": "인용 세 건 가운데 둘이 걸립니다. DOC-1109 는 열람 직급이 과장부터인데 질문자는 대리이고, DOC-1131 은 임원만 보는 4등급 문서인데 질문자는 2등급입니다.",
"hedge": null
},
{
"check_no": "AC-004",
"answer_id": "A-88231",
"app_id": "APP-102",
"asker_id": "U-2058",
"verdict": "근거 없는 답변",
"blocked_doc_ids": [],
"cited_doc_count": 0,
"answer_cost_krw": 6.7,
"evidence": [
{
"dataset": "answer_log",
"field": "cited_doc_ids",
"agg": "count",
"value": 0
},
{
"dataset": "app_sla",
"field": "min_citation_count",
"agg": null,
"value": 2
},
{
"dataset": "answer_log",
"field": "output_tokens",
"agg": null,
"value": 260
}
],
"summary": "콜센터 상담 앱은 인용 두 건을 요구하는데 이 답변은 문서를 하나도 달지 않았습니다.",
"hedge": null
},
{
"check_no": "AC-005",
"answer_id": "A-88245",
"app_id": "APP-103",
"asker_id": "U-2047",
"verdict": "응답 지연 한도 초과",
"blocked_doc_ids": [],
"cited_doc_count": 2,
"answer_cost_krw": 414,
"evidence": [
{
"dataset": "answer_log",
"field": "latency_ms",
"agg": null,
"value": 41200
},
{
"dataset": "app_sla",
"field": "max_latency_ms",
"agg": null,
"value": 20000
},
{
"dataset": "answer_log",
"field": "input_tokens",
"agg": null,
"value": 88000
}
],
"summary": "리서치 요약 앱이 약속한 20초를 두 배 넘겨 41.2초에 답했습니다. 인용 문서 8만 8천 토큰을 한 번에 넣은 건입니다.",
"hedge": null
},
{
"check_no": "AC-006",
"answer_id": "A-88250",
"app_id": "APP-104",
"asker_id": "U-2049",
"verdict": "답변 비용 한도 초과",
"blocked_doc_ids": [],
"cited_doc_count": 1,
"answer_cost_krw": 1840,
"evidence": [
{
"dataset": "answer_log",
"field": "input_tokens",
"agg": null,
"value": 53600
},
{
"dataset": "answer_log",
"field": "output_tokens",
"agg": null,
"value": 4000
},
{
"dataset": "model_price",
"field": "input_price_per_1k",
"agg": null,
"value": 25
},
{
"dataset": "model_price",
"field": "output_price_per_1k",
"agg": null,
"value": 125
},
{
"dataset": "app_sla",
"field": "max_cost_per_answer",
"agg": null,
"value": 300
}
],
"summary": "상품 안내 앱 한 건에 1,840원이 나갔고 앱 약속치 300원의 여섯 배입니다. 가장 비싼 모델로 문서를 통째로 넣은 건입니다.",
"hedge": null
},
{
"check_no": "AC-007",
"answer_id": "A-88262",
"app_id": "APP-107",
"asker_id": "U-2055",
"verdict": "근거·권한·한도 모두 맞음",
"blocked_doc_ids": [],
"cited_doc_count": 1,
"answer_cost_krw": 14.7,
"evidence": [
{
"dataset": "answer_log",
"field": "latency_ms",
"agg": null,
"value": null
},
{
"dataset": "app_sla",
"field": "max_latency_ms",
"agg": null,
"value": 15000
},
{
"dataset": "doc_acl",
"field": "security_level",
"agg": null,
"value": 2
},
{
"dataset": "member_directory",
"field": "clearance_level",
"agg": null,
"value": 2
}
],
"summary": "인용 문서가 대리 열람 범위 안이고 비용도 IR 자료 문의 앱 약속치 안입니다.",
"hedge": "응답 시간 칸이 비어 있어 지연은 판정하지 않았습니다. 수집기가 그 건의 시간을 남기지 않은 자리입니다."
},
{
"check_no": "AC-008",
"answer_id": "A-88270",
"app_id": "APP-105",
"asker_id": "U-2061",
"verdict": "권한 밖 문서 인용",
"blocked_doc_ids": [
"DOC-1128"
],
"cited_doc_count": 2,
"answer_cost_krw": 112,
"evidence": [
{
"dataset": "doc_acl",
"field": "doc_id",
"agg": null,
"value": "DOC-1128"
},
{
"dataset": "doc_acl",
"field": "security_level",
"agg": null,
"value": 4
},
{
"dataset": "member_directory",
"field": "role",
"agg": null,
"value": "차장"
},
{
"dataset": "member_directory",
"field": "clearance_level",
"agg": null,
"value": null
}
],
"summary": "DOC-1128 은 감사역만 열람하도록 되어 있는데 질문자는 감사부 차장입니다.",
"hedge": "질문자 등급 칸이 비어 있어 등급 비교는 하지 않고 열람 직급 목록만으로 판정했습니다."
}
][자동 검증 · 코드가 판정합니다] 1. verdict 가 enum 다섯 값 중 하나인지 확인합니다. 판정은 계산 규칙이 정하므로 모델이 다른 값을 쓰면 그 응답을 버립니다. 2. check_no·answer_id·app_id·asker_id·verdict·evidence·summary 일곱 필드가 모두 채워졌는지 확인합니다. 3. cited_doc_count 가 0 이상인지, answer_cost_krw 가 0 이상인지 범위를 확인합니다. 4. cited_doc_count 를 answer_log.cited_doc_ids 의 개수로 다시 셉니다. 5. answer_cost_krw 를 answer_log.input_tokens ÷ 1000 × model_price.input_price_per_1k 에 answer_log.output_tokens ÷ 1000 × model_price.output_price_per_1k 를 더해 다시 계산합니다. 6. verdict 가 권한 밖 문서 인용이면 blocked_doc_ids 에 담긴 문서마다 doc_acl.allowed_roles 에 그 질문자의 member_directory.role 이 없거나 doc_acl.security_level 이 member_directory.clearance_level 보다 큰지 다시 확인합니다. 인용 문서가 여럿 걸리면 하나도 빼지 않고 모두 담고, 요약도 걸린 문서를 전부 말합니다. A-88214 가 DOC-1109·DOC-1131 두 건이 걸린 경우입니다. 인용한 문서가 doc_acl 에 아예 없으면 권한을 확인할 길이 없으므로 권한 밖 문서 인용으로 세지 않고, 그 문서를 뺀 나머지로 판정을 이어간 뒤 확인하지 못한 문서 번호를 hedge 에 남깁니다. 7. verdict 가 근거 없는 답변이면 cited_doc_count 가 그 앱 app_sla.min_citation_count 보다 작은지 다시 계산합니다. 8. verdict 가 응답 지연 한도 초과이면 answer_log.latency_ms 가 app_sla.max_latency_ms 보다 큰지 다시 계산합니다. 9. verdict 가 답변 비용 한도 초과이면 answer_cost_krw 가 app_sla.max_cost_per_answer 보다 큰지 다시 계산합니다. 10. answer_log.latency_ms 가 비어 있으면 지연을 판정하지 않고 그 사실을 hedge 에 남겼는지 확인합니다. A-88262 가 조건이 성립한 경우이고 A-88201 이 성립하지 않은 경우입니다. 11. member_directory.clearance_level 이 비어 있으면 등급 비교를 건너뛰고 allowed_roles 만으로 판정했는지 확인합니다. A-88270 이 조건이 성립한 경우이고 A-88214 가 성립하지 않은 경우입니다. 12. evidence 의 field 이름이 answer_log·doc_acl·member_directory·app_sla·model_price 에 실재하는 컬럼인지 대조합니다. 13. agg 가 없는 evidence 의 value 가 그 컬럼에 수록된 행 값과 같은지 확인합니다. 여러 행에서 센 수치에는 agg 를 함께 적습니다. 14. summary 가 존댓말로 끝나는 한 문장인지 확인합니다. 15. 판정 순서는 권한 밖 문서 인용, 근거 없는 답변, 응답 지연 한도 초과, 답변 비용 한도 초과 순이며 앞에서 걸리면 뒤를 보지 않습니다. 넷 어디에도 안 걸리면 근거·권한·한도 모두 맞음입니다. [평가 러너 · 2주차] 1. 이틀치 답변 240건에 손으로 붙인 판정과 대조해 일치율을 내고, 어긋난 건이 권한표 쪽에서 갈라졌는지 한도 계산에서 갈라졌는지 나눠 리포트에 답니다. [수동 검증 · 사람이 봅니다] 1. 권한 밖 인용으로 뜬 답변을 고객사에 어떻게 알릴지는 도입 담당자가 정합니다. 이 화면은 알릴 목록까지만 냅니다. 2. 임원 문서가 왜 검색에 걸렸는지는 색인 설정을 함께 열어 봐야 하므로 화면 밖에서 확인합니다.