2026-10-27 (화)¶
오늘 요약 - Gemma 어시스턴트 실패의 원인이 모델이 아니라 vLLM의 Gemma 전용 도구 호출 파서라는 걸 알았다. 파서는 따옴표 없는 값을 일단 문자열로 두고, 스키마에 타입이 적힌 칸만 되돌린다. - 가장 오래 헷갈린 건 "누가 무엇을 하는가"였다. 도구를 고르는 건 모델, 문자열로 바꾸는 건 파서, 스키마를 보내는 건 우리 쪽이다.
🗂️ 오늘의 세션 (2개)¶
| 시간 | 프로젝트 | 무엇을 했나 |
|---|---|---|
| 08:59~14:13 | disaster | (기술 질문 없음) 재난 데이터 판정 검증·연구노트 정리 |
| 13:52~17:46 | bench | Gemma 어시스턴트 실패 원인 분석 |
🛠️ 오늘 한 작업¶
1. 재난 데이터 '공개' 판정 재검증과 엑셀 수정 (disaster · 08:59~11:30)¶
- 배경: 지난 조사(10/22 지반함몰, 10/26 교량·터널 등)에서 '공개'로 판정한 데이터를 실제로 받아 봤는지 의심이 들어 다시 물었다.
- 진행:
- 적재 시험은 10/21 강원대 건만 했고, 이번 조사는 내려받아 행 수를 세는 데까지였다는 걸 확인했다.
- '공개'가 붙었는데 실제로 안 받은 항목이 5건 나왔고, 그중 4건은 데이터가 아니라 방법론 출처로 적힌 참고문헌이었다.
- 참고문헌 행은 판정 대상이 아니라서 엑셀에서 지웠다. 이제 '공개' 12건은 모두 실제로 받은 것이다.
- 다시 확인한 두 가지: 공개 항목을 실제로 요청했는지, 근거 문서가 진짜 있는지. 판정은 그대로였고, 근거 칸 숫자·문구 10곳만 원문과 달랐다.
- 그 10곳과 원문 목차·md·README까지 고쳤다.
- 결과: 판단 자료로 써도 되는 상태가 됐다. 바뀐 판정은 없다.
2. 리서치 자료 전달 준비와 zip 호환 문제 (disaster · 11:38~13:41)¶
- 배경: 검토를 마친
재난 데이터 리서치폴더를 담당자에게 보내야 했다. - 진행:
- 원문 폴더는 용량이 커서 빼고, 리서치 폴더(444KB)만 압축하기로 했다. 개인정보 검사에서 걸린 건 모두 원문 쪽이었다.
- 담당자에게 보낼 메일 초안을 검토받았다. "공개 항목은 적재까지 확인했다"처럼 사실과 다른 문장 두 곳을 지적받았다(실제로는 내려받아 행 수 확인까지).
- 보낸 zip이 윈도우에서 안 풀린다는 연락을 받았다. 원인을 찾고 윈도우용 zip을 새로 만들었다(→ 문제 2).
- 매번 부탁하지 않아도 되도록 맥에서 직접 하는 방법을 물었고, 맥용 반디집을 쓰라는 답을 받았다.
- 결과: 윈도우용 zip을 만들었다. 실제 윈도우 PC에서는 확인하지 못했다.
3. 연구노트 자료 정리 (disaster · 13:13~13:54)¶
- 배경: 국가 R&D 연구노트 MD(
2026_연구개발_수행내용_디토닉.md)를 채우던 작업을 이어서 했다. - 진행:
- 오늘 한 일까지 채워 588줄이 632줄이 됐다.
- 실제 개발·적재 기록이 부족해 보여서, 날짜를 옮기거나 안 한 적재를 했다고 쓰자고 요청했다. Claude는 실적 위조에 해당하고, hub-dev에 생성 시각과 적재 기록이 남아 있어 확인될 수 있다며 거절했다.
- 기관 요청 문구("개발 범위에 해당하는 내용으로 한정")는 개발 범위만 쓰라는 뜻이 맞다고 확인했다.
- 파이프라인 개수 대신 실제로 모은 데이터 목록을 나열하는 방식으로 바꿨다. hub-dev 기록과 원천 카탈로그로 확인된 것만 넣었다.
- 결과: 632줄에서 889줄로 늘었다. 나머지는 뒤로 미뤘다.
4. Gemma 어시스턴트 실패 원인 분석 (bench · 13:53~16:40)¶
- 배경: 'gemma 어시스턴트 테스트' 결과를 보니 어시스턴트에서 Gemma가 잘 안 됐다. 원인을 찾아 고치기로 했다.
- 진행:
- 로그를 보니 422로 끝난 10건 중 7건이
nullable,precision타입 오류였다. Gemma는 구조 오류는 고치는데 타입 오류만 반복했다. - vLLM의 Gemma 4 파서가 따옴표 없는 값을 문자열로 두고, 스키마의
properties가 없는payload안쪽은 되돌리지 못한다는 걸 확인했다(→ 문제 1). - 처음엔 manager 카탈로그를 고치자는 답을 받았다. 다시 물어 보니 어시스턴트만 고쳐도 된다로 범위가 정정됐다.
- LLM·에이전트 기초, 도구 정의, 파서의 역할, 흐름 순서를 여러 번 바꿔 물으며 이해를 맞췄다(→ 개념 1, 2).
- "Gemma 에이전트는 잘 되는데?"라는 의문은 세 조건(vLLM Gemma 파서, 타입 없는 객체 인자, 엄격한 검증)이 동시에 맞을 때만 터진다는 설명으로 풀렸다.
- 결과: 원인을 정리했다. Gemma + vLLM 조합에서는 앱·파이프라인·온톨로지 생성이 지금 구조로는 사실상 실패한다(이번 테스트 8번 모두 실패).
5. 문서 산출물 재요청 확인 (disaster · 14:12~14:13)¶
- 배경: 예전에 작성한 산출물(국토부 시설물 관리시스템 분석 보고서, 데이터 수집·통합 프로토타입 설계서)에 대해 다시 요청이 왔다.
- 진행: 두 문서의 현재 판을 확인하는 데서 세션이 끝났다.
- 결과: 어떻게 고쳐 쓸지는 아직 정하지 않았다.
6. 이슈 등록과 로컬 수정 시험 (bench · 15:04~17:10)¶
- 배경: 타입은 결국 manager 패키지 모델에서 정해지니까 manager 쪽에 기록을 남기기로 했다.
- 진행:
- 로컬 manager
models.py의payload에Field(json_schema_extra=...)로 스키마 힌트만 넣어 봤다(브랜치·커밋 없음). 양식에 타입이 실려 나갔고 기존 테스트 761개도 통과했다. - 타입 자체를 바꾸는 것과
Field에 덧붙이는 것의 차이를 물었다(→ 개념 3). - dhub2-manager에 이슈 #3561을 올리고 어시스턴트 #154와 연결했다. 해결 위치(manager냐 어시스턴트냐)는 미정으로 적었다.
- 이슈의 B안(검증 전 값 변환)을
model_validator(mode="before")로 로컬에 넣어 봤다. 타입 정의와 strict 검증은 그대로 둔다. - ADR-0349(리소스 플랜으로 온톨로지 모델·수집 경로를 끝까지 만든다는 설계 결정)가 무엇인지 확인했다.
- 결과: 로컬 시험만 했고, 실제 Gemma로는 아직 돌려 보지 않았다.
7. Gemma·Claude 비교 벤치마크 준비 (bench · 17:12~17:46)¶
- 배경: SOTA·기준 코드를 참고해서 Gemma와 Claude(Opus, Sonnet)를 비교 테스트하고, 가장 나은 안으로 PR을 올리고 싶었다.
- 진행:
- 계획에 장기 유지보수성을 평가 축으로 넣었더니 후보가 하나 늘었다.
- Claude 토큰이 꽤 든다는 것과 줄이는 방법을 확인한 뒤, 권장안으로 진행했다.
- 배포된 인프라는 절대 바꾸지 않는다는 조건을 걸었다.
- 벤치 인증 토큰이 폐기돼 있어서 새로 받아 갱신했다. demo 토큰 갱신에 성공했다.
- 결과: 준비 작업과 토큰 갱신까지 끝냈다. 실제 모델 비교 실행은 남았다.
🔧 오늘 해결한 문제¶
1. vLLM Gemma 도구 인자가 문자열로 바뀌어 422 (→ 작업 4, 6)¶
- 증상: Gemma로 계획을 만들면
nullable: Input should be a valid boolean같은 오류가 반복되다가422 "The assistant repeated a failing tool call."로 끝났다. - 원인 → 해결: vLLM Gemma 4 파서가 따옴표 없는 값을 문자열로 두는데,
payload가dict[str, Any]라서 스키마로 되돌릴 근거가 없었다. 스키마 힌트나 검증 전 값 변환을 로컬에서 시험하는 중이다. - 👉 vLLM Gemma 도구 인자 문자열 변환 422
2. 맥에서 만든 zip이 윈도우에서 안 풀림 (→ 작업 2)¶
- 증상: Finder '압축하기'로 만든 zip이 윈도우에서 안 풀리고, 한글 이름이 깨졌다.
- 원인 → 해결: UTF-8 표시가 없는 한글 이름, 자모로 나뉜 한글 저장 방식,
__MACOSX부속 파일 때문이었다. 윈도우 호환 zip을 다시 만들었고, 앞으로는 맥용 반디집을 쓴다. - 👉 맥 zip 윈도우에서 압축 해제 실패
🧠 부족했던 개념¶
1. LLM 서빙 서버의 도구 호출 파서 · 🔁 10번 물음¶
- 어떻게 드러났나: Gemma 실패 원인을 분석하다가(→ 작업 4) 처음엔 "젬마가 왜 str로 바꾸냐"고 물었다. 이어서 "젬마 전용 파서가 있냐", "vllm 설정이냐", "다른 모델도 그러냐", "파서를 굳이 거쳐야 하냐"로 바꿔 가며 10번 물었다.
- 헷갈린 점: 값을 바꾸는 주체를 모델로 알고 있었다. 실제로는 서빙 서버의 파서다. 이 동작이 설정인지 코드인지, 모든 모델에 해당하는지도 몰랐다.
- 핵심:
- 오픈 모델은 도구 호출을 자기 학습 표기로 쓴다. 서빙 엔진(vLLM)이 모델 전용 파서로 이걸 OpenAI 형식 JSON으로 옮긴다.
- Gemma 4는 글자를
<|"|>로 감싸고 숫자·참거짓은 그냥 쓴다. vLLM 파서는 감싸지 않은 값도 일단 문자열로 두고, 요청에 온 스키마에 타입이 적힌 칸만 되돌린다. 이건 옵션이 아니라 코드에 박힌 동작이다. - 인자를 JSON으로 쓰는 모델(
tool_args_json=True)이나 회사 API(Claude, GPT)는 처음부터 JSON이라true와"true"가 구분된다. 그래서 이 문제가 없다. - 👉 LLM 도구 호출 파서와 타입 복원
2. LLM 도구 호출(function calling) 흐름 · 🔁 7번 물음¶
- 어떻게 드러났나: 원인 설명을 이해하려다(→ 작업 4) "LLM과 에이전트를 잘 모른다"며 바닥부터 물었다. 그 뒤로도 "툴을 우리가 먼저 고르냐", "스키마가 서버에 할당돼 있냐", "스키마에 값을 넣어 파서로 넘기냐"를 여러 번 바꿔 물었다.
- 헷갈린 점: 도구를 우리가 고른다고, 스키마가 서버에 미리 등록돼 있다고, 모델이 양식에 값을 채운다고 생각했다. 셋 다 틀렸다.
- 핵심:
- LLM은 글만 쓴다. 프로그램이 도구 정의(tool definition: name, description, parameters 스키마)를 매 요청마다 함께 보낸다.
- 모델이 도구를 고르고 스키마를 참고해 인자를 글로 써 낸다. 서버 파서가 그 글을 JSON으로 바꾸고 처음 받은 스키마로 타입을 맞춘다.
- 도구 실행은 우리 프로그램이 한다. 결과를 다시 대화에 붙여 반복하는 루프가 에이전트다.
- 스키마를 바꾸면 같은 도구 정의를 받는 모든 모델에 적용된다.
- 👉 LLM 도구 호출 function calling 흐름
3. pydantic 검증과 Field 설정 · 🔁 5번 물음¶
- 어떻게 드러났나: 로컬에서
models.py를 고쳐 보면서(→ 작업 6) 물었다. "타입을 바꾸는 것과 Field에 넣는 게 뭐가 다르냐", "Field가 원래 그런 역할이냐", "검사 없이 타입 힌트만 줄 수 있냐", "B안은 타입 자체를 바꾸는 거냐"까지 5번이다. - 헷갈린 점: 값 검사와 스키마 설명을 구분하지 못했다. "Field는 설명만 한다"고 단순하게 알고 있었다.
- 핵심:
- pydantic(파이단틱)은 타입 힌트(
dict[str, Any])로 실제 검사·변환을 한다. 그래서 타입을 바꾸면 검문소 규칙이 바뀐다. Field에는 검사하는 설정(min_length,pattern,ge)과 검사하지 않는 설정(description,json_schema_extra)이 섞여 있다.json_schema_extra는 JSON Schema에만 끼워 넣고 검사는 안 한다.model_validator(mode="before")는 검사 직전에 데이터를 고치는 함수다. 타입 정의는 그대로 둔다.- 정확한 용어는 "타입 힌트 추가"가 아니라 "스키마 힌트 추가"다.
- 👉 pydantic 검증과 Field 설정
4. JSON Schema 규약과 해석 · 🔁 2번 물음¶
- 어떻게 드러났나: 스키마 힌트를 이해하다가(→ 작업 4, 6) "아무 스키마나 다 통하냐", "커스텀으로 만든 json 타입을 vllm이 어떻게 읽냐"고 물었다.
- 헷갈린 점: 우리 스키마를 우리만의 형식으로 여겼다. 그리고 스키마가 있으면 모델이 반드시 지킨다고 생각했다.
- 핵심:
- 도구 인자 스키마는 JSON Schema 표준 문법(
type,properties,items,required)으로 쓴다. 우리 것은 칸 이름과 구조뿐이다. - 공급자마다 받아 주는 범위가 다르다. Gemini는 일부만 받고, vLLM 타입 복원은
properties·items만 따라간다(anyOf는 안 들어간다). - 일반 모드에서 스키마는 강한 안내일 뿐 강제가 아니다. 강제하려면 엄격 모드(제약 생성)가 필요하다.
- 👉 JSON Schema 규약과 해석
5. 파이썬 패키지 설치와 import 의존¶
- 어떻게 드러났나: 스키마가 어디서 오는지 정리하다가(→ 작업 4) "매니저가 패키지를 만들고 어시스턴트가 import해서 쓰는 거냐"고 한 번 물었다.
- 헷갈린 점: 어시스턴트가 실행 중에 매니저에 물어서 타입을 받아 온다고 생각했다.
- 핵심:
- 한 저장소의 코드를 패키지로 묶고, 다른 프로젝트가
pyproject.toml에 git 주소와 태그를 고정해 설치한 뒤 import해서 쓴다. - 설치본은
.venv/.../site-packages에 복사된다. 원본 저장소가 바뀌어도 태그를 올리기 전까지는 따라가지 않는다. - 패키지 import는 내 프로세스 안에서 돌고, HTTP API 호출은 상대 서버에서 돈다. 둘은 다른 연결 방식이다.
- 👉 파이썬 패키지 설치와 import 의존
🩹 오늘 드러난 약점¶
- 책임 주체를 섞어서 생각한다 — 근거: "젬마가 str로 바꾼다", "vllm 설정이냐", "manager에서 타입 가져와 json 만든다"처럼 모델·파서·어시스턴트·매니저의 몫을 계속 헷갈렸다 → 다음에: 시스템을 이해할 때 먼저 "누가, 언제, 무엇을" 표로 적고 나서 질문한다.
- 흐름을 머릿속 그림 없이 조각으로 묻는다 — 근거: 도구 호출 순서를 16:23~16:29 사이에 4번 다시 정리했다 → 다음에: 시퀀스를 내가 먼저 1~6단계로 써 보고 틀린 곳만 확인받는다.
- 용어를 대충 쓴다 — 근거: "설명서" ↔ tool definition, "타입 힌트" ↔ 스키마 힌트, "검사" ↔ "설명"을 구분하지 못했다 → 다음에: 시니어에게 설명하기 전에 공식 용어로 바꿔 말해 본다.
- 파이썬 코드를 읽는 기초가 약하다 — 근거: "파이썬 코드 잘 몰라", 어느
models.py인지 찾지 못했다 → 다음에:dict[str, Any],Field(...), 데코레이터 같은 기본 표기 읽는 법을 한 번 정리한다.
🧪 복습 퀴즈¶
1. Gemma가 nullable:true라고 제대로 썼는데 어시스턴트에 "true"로 도착한 이유는?
답 보기
vLLM의 Gemma 4 파서가 따옴표 없는 값을 일단 문자열로 두고, 스키마에 타입이 적힌 칸만 되돌린다. 그런데 `payload`가 `dict[str, Any]`라서 안쪽 타입 정보가 없어 되돌리지 못했다.2. 도구 호출에서 "도구를 고르는 주체"와 "도구를 실행하는 주체"는 각각 누구인가?
답 보기
고르는 건 LLM(모델)이고, 실행하는 건 우리 프로그램(어시스턴트)이다. 우리는 매 요청마다 도구 정의 전체를 함께 보낸다.3. pydantic Field(json_schema_extra=...)와 model_validator(mode="before")의 차이는?