도구 장벽 허물기: 검열되지 않은 모델이 구조화된 작업을 수행하게 만드는 방법
요약
검열되지 않은 모델이 자율 에이전트로서 유용함에도 불구하고, 구조화된 도구 호출(tool calling) 능력이 부족한 문제를 분석합니다. 모델이 JSON 스키마 대신 산문으로 응답하는 '도구 장벽' 현상을 설명하고 이를 극복하기 위한 필요성을 다룹니다.
핵심 포인트
- 검열되지 않은 모델은 지침 준수 능력이 뛰어나 에이전트에 적합함
- 대부분의 미세 조정된 모델은 네이티브 함수 호출 능력이 결여됨
- 도구 호출은 단순 예측이 아닌 미세 조정 단계에서 학습되어야 함
- 구조화된 작업 수행을 위한 의도 오케스트레이션의 중요성
XML 가로채기, 강제 프롬프트(enforcement prompts), 그리고 에이전시(agency)의 아키텍처에 대하여
검열되지 않은 모델의 문제점
검열되지 않은 모델(Uncensored models)은 에이전트 작업(agentic work)을 위해 실제로 당신이 원하는 모델들입니다. 이들은 의구심을 갖지 않고 복잡한 다단계 지침을 따를 것입니다. 안전 분류기(safety classifier)가 불안해한다고 해서 합리적인 작업을 거부하지도 않을 것입니다. 이들은 어두운 내용, 이상한 내용, 그리고 기업의 컴플라이언스(compliance) 팀을 당황하게 만드는 내용도 작성할 것입니다. 만약 콘텐츠 생성, 코드 실행, 실제 결과가 따르는 의사결정 등 현실 세계에서 작동해야 하는 자율 에이전트(autonomous agent)를 구축하고 있다면, 주저하지 않는 모델이 필요합니다.
하지만 문제가 있습니다. 검열되지 않은 모델들은 종종 네이티브 함수 호출(native function calling)을 수행하지 못합니다.
Chat Completions API의 OpenAI 호환 tools 파라미터는 언어 모델에 구조화된 능력을 부여하는 표준적인 방법입니다. 사용자는 사용 가능한 각 도구를 설명하는 JSON 스키마(JSON schema)를 전달합니다. 모델은 도구를 언제 사용할지 결정하고 응답에 tool_calls 배열을 반환합니다. 사용자의 코드는 해당 도구를 실행하고 결과를 다시 입력하며 대화가 계속됩니다. 이는 깔끔하고 표준화되어 있습니다. 이를 사용하도록 명시적으로 훈련된 GPT-4, Claude 및 기타 프런티어 모델(frontier models)에서는 완벽하게 작동합니다.
검열되지 않은 모델은 어떨까요? 이들은 이를 무시합니다. 도구를 실행하는 대신 무엇을 할 것인지 설명합니다. 구조화된 JSON을 생성하는 대신 산문(prose)으로 도구 호출을 서술합니다. 예를 들어 "사이버펑크 도시의 이미지를 생성하겠습니다"라고 말한 뒤... 그냥 계속 말을 이어갑니다. tool_calls 필드도 없고, 함수 호출(function invocation)도 없습니다. 그저 말뿐입니다.
도구 호출이 가능한 검열되지 않은 모델들 — glm-5.1-venice, deepseek-v4-flash-venice, glm-4.7-flash-heretic — 은 예외적인 경우이지 규칙이 아닙니다. 창의적 자유, 역할극(roleplay), 또는 제한 없는 지침 준수(instruction following)를 위해 미세 조정(fine-tuned)된 대부분의 모델은 도구 호출 훈련을 받은 적이 없습니다. 이는 미세 조정 과정에서 모델에 의도적으로 구워 넣어야(baked into) 하는 능력입니다. 다음 토큰 예측(next-token prediction)으로부터 자연스럽게 발생하는 능력이 아닙니다.
이것이 바로 도구 장벽(tool barrier)입니다. 자율적인 에이전트(autonomous agency)에 가장 적합한 모델들이 정작 구조화된 도구 사용(structured tool use) 능력은 가장 떨어지는 경우가 많습니다. 만약 유용한 작업을 수행하기 위해 도구 호출(tool calling)에 의존하는 에이전트 시스템을 구축하고 있다면, 이 장벽은 치명적인 결격 사유가 됩니다.
저는 Hermes Agent를 위한 의도 오케스트레이션(intent-orchestration) 플러그인을 구축하면서 이 벽에 정면으로 부딪혔습니다. 제가 이를 어떻게 극복했는지 소개하겠습니다.
네이티브 도구 호출의 작동 방식 (정상 작동할 때)
우회 방법을 설명하기 전에, 우리가 무엇을 우회하려 하는지 이해할 필요가 있습니다.
OpenAI 호환 도구 호출 프로토콜은 간단합니다. API 요청에는 tools 배열이 포함됩니다:
{
"tools": [
{
...
모델이 도구를 사용하기로 결정하면, 응답에 tool_calls 필드가 포함됩니다:
{
"role": "assistant",
"tool_calls": [
...
호출 코드는 함수를 실행한 다음, 그 결과를 tool 역할(role) 메시지로 다시 보냅니다. 모델은 이 결과를 통합하여 작업을 계속합니다. 이는 잘 설계된 프로토콜입니다. 여러 개의 도구 호출, 병렬 실행, 오류 전파(error propagation)를 처리합니다. 이는 모든 주요 에이전트 프레임워크의 중추 역할을 합니다.
하지만 이를 위해서는 모델이 프로토콜을 이해해야 합니다. 모델은 tools 배열을 인식하고, JSON 스키마(JSON schemas)를 파싱하며, 언제 도구 호출이 적절한지 결정하고, 인자(arguments)를 올바르게 형식화하며, 정확한 응답 구조를 생성해야 합니다. 이는 일반적인 언어 모델링(language modeling) 과정에서 자연스럽게 발생하는 것이 아닙니다. 이는 도구 호출 예시를 통한 지도 미세 조정(supervised fine-tuning), 도구 호출 보상 신호를 활용한 RLHF(Reinforcement Learning from Human Feedback), 또는 훈련 파이프라인이 사용하는 어떤 방법론을 통해서든 반드시 학습되어야 하는 특정한 동작입니다.
그러한 훈련(GPT-4, Claude, 도구 호출(tool-calling) 파인튜닝이 적용된 Llama 3, Venice가 처리한 GLM 및 DeepSeek 변형 모델 등)을 거친 모델들은 이를 기본적으로 처리합니다. 반면, 그러한 훈련을 거치지 않은 모델들 — 대부분의 검열되지 않은 파인튜닝(uncensored fine-tunes) 모델, 역할극(roleplay) 모델, 그리고 창의적 글쓰기에 최적화된 체크포인트(checkpoints)들이 여기에 해당합니다 — 은 tools 파라미터를 어떻게 다뤄야 하는지 전혀 알지 못합니다. 이들은 API 요청에서 해당 파라미터를 보기는 하지만, 그것이 텍스트 생성에 아무런 영향을 미치지 못합니다. 대신 이들은 자신이 무엇을 할 것인지 설명하는 산문을 생성하는데, 이는 그들의 훈련이 그렇게 하도록 가르쳤기 때문입니다.
이 문제는 추론(inference) 단계에서 해결할 수 없습니다. 그 어떤 시스템 프롬프트 엔지니어링(system prompt engineering)도 모델이 한 번도 학습하지 않은 능력을 가르쳐줄 수는 없습니다. 다른 접근 방식이 필요합니다.
XML 가로채기 패턴 (The XML Interception Pattern)
해결책은 기만적일 정도로 간단합니다. 모델이 가지고 있지 않은 API 기능을 사용하라고 요구하는 것을 멈추고, 대신 여러분이 파싱(parse)할 수 있는 텍스트를 생성하도록 요구하는 것입니다.
tools 배열을 전달하며 모델이 tool_calls를 생성하기를 기대하는 대신, 시스템 프롬프트(system prompt)에 사용 가능한 도구들을 XML 스타일의 태그로 기술합니다. 모델은 해당 태그를 포함하는 텍스트를 생성합니다. 별도의 파서(parser) — 정규 표현식(regex), XML 파서, 커스텀 토크나이저(custom tokenizer) 등 무엇이든 — 가 출력을 가로채어 도구 호출을 추출하고 이를 실행합니다.
실제 작동 방식은 다음과 같습니다. 시스템 프롬프트에는 다음과 같은 내용이 포함됩니다:
당신은 다음 도구들에 접근할 수 있습니다. 응답 시 해당하는 XML 태그를 생성하여 도구를 사용하십시오:
<generateImage>여기에 프롬프트 텍스트 입력</generateImage> — 텍스트 설명으로부터 이미지를 생성합니다.
...
모델이 이미지를 생성하고 싶을 때, 함수를 호출하는 것이 아니라 다음과 같이 작성합니다:
제가 그것을 생성해 드리겠습니다.
<generateImage>score_9, score_8_up, 1girl, solo, protogen, female, black fur, blue circuits, visor, cyberpunk workshop</generateImage>
출력 파이프라인(output pipeline)에 있는 플러그인이 <generateImage> 태그를 포착하여 프롬프트(prompt)를 추출하고, 이를 이미지 생성 서비스로 라우팅(routing)한 뒤, 해당 태그를 결과물로 교체합니다 (또는 아키텍처에 따라 다음 메시지 사이클에서 결과를 반환합니다).
이것이 의도 오케스트레이션(intent-orchestration) 패턴입니다. 이것은 심(shim)이자 호환성 계층(compatibility layer)입니다. 모델이 할 수 있는 것(텍스트 생성)과 우리가 모델에게 시키고자 하는 것(구조화된 작업 호출) 사이의 번역기 역할을 합니다. 저는 이를 Hermes Agent를 위한 플러그인으로 구축했으며, 그 이후로 제 에이전트 인프라 전반의 프로덕션 환경에서 계속 실행되고 있습니다.
핵심 통찰은 다음과 같습니다: 텍스트 생성은 언어 모델이 '하는' 일입니다. 모든 모델이 그렇습니다. 단 하나도 예외 없이 말이죠. XML 태그를 포함하는 구조화된 텍스트를 생성하도록 모델에게 요청하는 것은, 모델이 말 그대로 수행하도록 만들어진 일을 시키는 것입니다. 반면, 모델이 학습한 적 없는 API 기능을 통해 특정 JSON 형식으로 tool_calls를 생성하도록 요청하는 것은, 모델이 어떻게 해야 할지 모를 수도 있는 일을 시키는 것입니다. XML 패턴이 작동하는 이유는 모델이 도달할 수 없는 곳을 요구하는 대신, 모델이 현재 있는 위치에서 작업을 수행할 수 있게 해주기 때문입니다.
이 태그들은 유연합니다. 모델을 재학습시키지 않고도 새로운 태그를 정의할 수 있습니다. 태그를 중첩할 수도 있고, 복잡한 인자(arguments)를 태그 내용으로 전달할 수도 있습니다. 파싱 계층(parsing layer)이 실제 도구 호출(tool invocations)로의 번역을 처리합니다. 또한 모델이 일반적인 텍스트 출력의 일부로서 태그를 생성하기 때문에, 그와 함께 따라오는 모든 맥락적 추론(contextual reasoning)과 계획(planning)을 얻을 수 있습니다. 즉, 모델이 무엇을 하고 있는지, 왜 특정 도구를 선택했는지, 그리고 결과가 어떠할 것으로 예상하는지를 설명해 줍니다. 이러한 맥락은 디버깅(debugging)과 관찰 가능성(observability) 측면에서 매우 가치 있습니다.
강제 프롬프트 (The Enforcement Prompt)
제가 발견하는 데 시간이 좀 걸렸던 미묘한 차이가 하나 있습니다. 시스템 프롬프트(system prompt)에 XML 태그를 설명하더라도, 모델이 항상 이를 '사용'하는 것은 아니라는 점입니다.
일부 모델들 — 특히 지시 이행 (instruction-following) 또는 어시스턴트 스타일의 상호작용에 대해 집중적으로 학습된 모델들 — 은 실제로 행동하기보다 자신이 무엇을 할 것인지 설명하는 것을 기본값으로 삼습니다. 이들은 "...의 이미지를 생성해야 합니다" 또는 "generateImage 도구를 사용하여..."라고 말한 뒤, 실제 태그를 생성하지 않은 채 텍스트를 이어갑니다. 도구 호출 (tool call)을 수행하는 대신, 도구 호출 과정을 서술(narrating)하는 것입니다.
이는 "그것을 검색해 보겠습니다"라고 말하는 모델과 실제로 <searchNotes>query</searchNotes>를 생성하는 모델의 차이입니다. 둘 다 의도는 이해했습니다. 하지만 오직 하나만이 그 의도에 따라 행동했습니다.
해결책은 아키텍처 (architecture)가 아닌 프롬프트 엔지니어링 (prompt engineering)입니다. Hermes Agent에는 모델 이름 패턴과 일치하는 TOOL_USE_ENFORCEMENT_MODELS 튜플 (tuple)이 있습니다. 일치하는 모델이 감지되면, 시스템은 다음과 같은 취지의 추가적인 시스템 프롬프트 지시 사항을 주입합니다: "도구를 사용해야 할 때는 실제로 XML 태그를 생성하세요. 당신이 무엇을 할 것인지 설명하지 마세요. 행동을 서술하지 마세요. 태그를 생성함으로써 실행하세요."
이것은 제약 (constraint)이 아니라 넛지 (nudge, 가벼운 권유)입니다. 강제적인 집행 메커니즘은 없습니다. 모델은 여전히 이를 무시할 수 있습니다. 하지만 실제로 이 명시적인 지시 사항은 실질적인 차이를 만들어냅니다. 그렇지 않았다면 도구 사용을 서술했을 모델들이 실제 태그를 생성하기 시작합니다. 이해와 실행 사이의 간극이 좁혀지는 것입니다.
설정은 네 가지 모드를 지원합니다:
- "auto" — 내장된
TOOL_USE_ENFORCEMENT_MODELS목록과 대조하여 알려진 문제 모델에 대해서만 주입합니다. - "always" — 목록 포함 여부와 관계없이 모든 모델에 대해 강제 프롬프트를 주입합니다.
- "off" — 절대 주입하지 않으며, 시스템 프롬프트에만 의존합니다.
- Custom list (사용자 정의 목록) — 대조할 모델 이름 패턴을 직접 제공합니다.
기본 목록에 포함되지 않은 검열되지 않은 모델들 — 사실 대부분의 모델이 여기에 해당합니다 — 의 경우, 강제 설정을 "always"로 설정하는 것이 올바른 선택입니다. 비용은 미미하며 (시스템 프롬프트에 몇 개의 토큰이 추가됨), 이점은 전체 모델 카탈로그에 걸쳐 일관된 도구 호출 (tool invocation)을 보장한다는 점입니다.
저는 이러한 주입 (injection)만으로 모델의 도구 태그 생성률이 20%에서 90% 이상으로 올라가는 것을 목격했습니다. 이는 화려한 엔지니어링은 아닙니다. 그저 시스템 프롬프트 (system prompt)를 추가하는 것뿐입니다. 하지만 이는 행동하는 에이전트 (agent)와 행동에 대해 말만 하는 에이전트 사이의 차이를 만들어냅니다.
하이브리드 아키텍처 (The Hybrid Architecture)
실제로 대부분의 프로덕션 에이전트 시스템은 단 하나의 방식만 사용하지 않습니다. 두 가지 방식을 모두 사용합니다.
Hermes Agent가 좋은 예시입니다. 내장된 도구들 — 터미널 (terminal), 파일 작업 (file operations), 웹 검색 (web search), 브라우저 제어 (browser control) — 는 OpenAI 호환 tools 파라미터를 통한 네이티브 도구 호출 (native tool calling)을 거칩니다. 모델이 이를 지원할 때 (제가 프로덕션에서 사용하는 대부분의 모델은 지원합니다), 이 경로는 빠르고 신뢰할 수 있으며 충분히 검증되어 있습니다. 프레임워크는 tool_calls 파싱, 실행 및 결과 주입 (result injection)을 자동으로 처리합니다.
커스텀 도구들 — 메모리 작업 (memory operations), 이미지 생성 (image generation), 연구 위임 (research delegation), 실행 위임 (execution delegation), 위키 작업 (wiki operations) — 는 XML 가로채기 계층 (XML interception layer)을 거칩니다. 이것들은 핵심 프레임워크의 네이티브 스키마 (native schema)에 포함되지 않은 도구들입니다. 이들은 자신의 XML 태그를 등록하고 핸들러 함수 (handler functions)를 제공하는 플러그인 (plugins)으로 정의됩니다. 출력 파이프라인 (output pipeline)은 태그를 스캔하여 추출하고, 이를 적절한 핸들러로 라우팅한 뒤 결과를 반환합니다.
두 시스템은 깔끔하게 공존합니다. 모델의 단일 응답에는 네이티브 tool_calls 배열 (터미널 명령용)과 XML 태그 (메모리 작업 및 이미지 생성용)가 모두 포함될 수 있습니다. 프레임워크는 네이티브 호출을 처리하고, 플러그인은 XML 호출을 처리합니다. 이들은 서로 간섭하지 않습니다.
이것은 편법 (hack)이 아닙니다. 핵심 프레임워크가 제공하는 범위를 넘어 에이전트의 역량을 확장하기 위한 합리적인 아키텍처입니다. 네이티브 도구 호출 경로는 일반적이고 잘 정의된 작업들을 처리합니다. XML 가로채기 경로는 커스텀 및 도메인 특화 (domain-specific) 작업들을 처리합니다. 두 방식 모두 실행 파이프라인 (execution pipeline)에서 일등 시민 (first-class citizens)으로서 대우받습니다.
유일한 실제 복잡성은 출력 파싱 (output parsing) 순서에 있습니다. 먼저 네이티브 tool_calls를 처리해야 하며 (이는 구조화되어 있고 모호하지 않습니다), 그 다음 텍스트 콘텐츠를 스캔하여 XML 태그를 찾아야 합니다. 만약 모델이 동일한 응답 내에서 두 가지를 모두 생성한다면, 둘 다 실행됩니다. 모델이 둘 중 하나만 생성하더라도 괜찮습니다. 시스템은 우아하게 성능을 저하시키며(degrades gracefully) 작동합니다.
모델 카탈로그에서 배운 점
최근 저는 api.navy에 있는 제 LLM 프록시의 전체 모델 카탈로그를 감사했습니다 — 총 131개의 모델이 있습니다. 세부 내역은 다음과 같습니다:
- 99개의 모델은
supports_tools=True가 확인되었습니다. 이들은 네이티브 도구 호출 (tool calling)을 안정적으로 처리하는 모델들입니다. GPT-4 변형 모델들, Claude 변형 모델들, 도구 호출 파인튜닝 (fine-tunes)이 적용된 Llama 3, GLM 모델들, DeepSeek 모델들, Mistral 모델들 및 기타 다양한 모델들이 포함됩니다. - 17개의 모델은 도구 지원이 없습니다. 이들은 대부분 임베딩 (embedding) 모델, TTS 모델, 그리고 이미지 생성 모델들입니다. 텍스트 완성 (text completion) 모델이 아니므로, 도구 호출 기능이 없는 것은 예상된 일이며 무관합니다.
- 44개의 모델은 도구 지원에 대한 메타데이터가 null입니다 — 즉, 알 수 없음 상태입니다. 이들은 와일드카드 (wild cards)와 같습니다. 일부는 아마도 도구를 지원하지만 태그가 지정되지 않았을 것이고, 다른 일부는 아마도 지원하지 않을 것입니다.
특히 검열되지 않은 (uncensored) 모델들 중에서는 다음과 같습니다:
- glm-5.1-venice — 네이티브 도구 호출 확인됨
- glm-4.7-flash-heretic — 네이티브 도구 호출 확인됨
- deepseek-v4-flash-venice — 네이티브 도구 호출 확인됨
- glm-5-venice — 네이티브 도구 호출 확인됨
- venice-uncensored variants — 메타데이터 null, 네이티브 도구 호출이 없을 가능성 높음
- Roleplay-optimized models — 메타데이터 null, 거의 확실히 네이티브 도구 호출이 없음
AI 자동 생성 콘텐츠
본 콘텐츠는 Dev.to AI tag의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기