Gemma 4 툴 호출 템플릿 버그 발견 및 수정
I stumbled on a Gemma 4 chat template bug for tools and fixed it
핵심 요약
Gemma 4의 툴 호출 시 JSON 스키마 파싱 오류를 발견하고 Jinja 템플릿 수정을 통해 해결함.
- 툴 호출 오류 — JSON 스키마의 anyOf 패턴이 Gemma 4 템플릿에서 제대로 처리되지 않아 발생함.
- Jinja 템플릿 수정 — $ref, anyOf, oneOf 등 복잡한 스키마 구조를 지원하도록 템플릿을 개선함.
- PR 제출 — 수정 사항을 Hugging Face의 gemma-4-31B-it 저장소에 풀 리퀘스트로 제안함.
TLDR: anyOf: [$ref, null]과 같은 일반적인 JSON 스키마 패턴을 사용하는 툴 파라미터가 프롬프트에서 빈 type 필드로 렌더링됩니다. 이로 인해 모델이 스키마 정보를 제대로 인식하지 못하게 됩니다.
--
상세 버전:
Gemma 4는 3개 이상의 추론 엔진에서 제 커스텀 MCP 툴을 호출하는 데 문제가 있었지만, Qwen3.5와 gpt-oss-20b는 잘 작동했습니다.
저는 이게 챗 템플릿 문제이거나 추론 라이브러리의 엣지 케이스 문제라고 생각했고, 많은 사람들이 Gemma 4를 에이전트로 잘 사용하고 있었기에 시간이 해결해 줄 것이라 생각했습니다.
하지만 최소 2주 동안 해결되지 않았고, 직접 조사할 수밖에 없었습니다.
제가 한 일:
- llama-server를 통해 맥북 프로에서 Qwen3.5-27B-Q4_K_M과 gemma-4-31B-it-Q4_K_S로 동일한 프롬프트/툴을 실행하여 상세 로그 파일을 만들었습니다.
- GPT-5.5-high(codex CLI)에게 로그를 읽고 문제를 진단하도록 했습니다.
- 몇 분 만에 원인을 찾았습니다. 기본 Gemma 챗 템플릿은 툴 파라미터가 직접적인 type 필드를 가지고 있다고 가정합니다. 즉, 다음과 같은 nullable 참조가 포함된 JSON 스키마 형태에서는 작동하지 않습니다:
{"anyOf": [{"$ref": "#/$defs/SomeObject"}, {"type": "null"}]}
여기에는 최상위 type이 없습니다. 유용한 구조는 anyOf와 $defs 내부에 있습니다. 템플릿은 anyOf, $ref, $defs를 삭제하고 type: ""로 렌더링합니다.
- 챗 템플릿 jinja를 조금 수정했더니 Gemma가 제 툴을 완벽하게 호출하게 되었습니다!
어쨌든 HF의 google/gemma-4-31B-it에 PR을 보냈습니다.
<UPDATE>
nullable 참조로 인해 발생하는 여러 문제 중 하나만 해결했다는 것을 깨달았습니다. 다음 사항들을 처리하도록 jinja를 업데이트했습니다:
이제 jinja는 다음을 보존합니다:
- $ref
- anyOf
- oneOf
- allOf
- $defs
- enum
- const
- type: ["string", "null"]
- 배열이나 객체를 포함하는 타입 배열의 items / properties
- null 값을 null로 유지

