오픈 모델에서 실행하기
모델 레이어가 에이전트 레이어와 어떻게 분리된 채로 유지되는지 — 능력 프로빙, 멀티 백엔드 라우팅, 그리고 작은 오픈 모델이 도구 호출에서 깨지는 네 가지 방식을 게이트웨이가 대신 처리하는 방법.
여기의 에이전트는 특정 모델에 맞춰 작성되지 않습니다. 에이전트 레이어가 필요로 하는 모든 것 — 채팅, 임베딩, 도구 호출 — 은 OpenAI 호환 HTTP 형태로 말하는 게이트웨이를 통과하므로, 그 뒤의 모델은 호스팅된 프런티어 API, 당신이 직접 운영하는 오픈 모델, 또는 여러 개가 동시에일 수 있습니다.
이 페이지는 그 주장 뒤의 엔지니어링 세부 사항입니다. "오픈 모델 지원"은 말하기 쉽고 검증하기 어렵기에 존재하며, 플랫폼을 평가하는 사람이 이를 묻는 것은 정당합니다.
게이트웨이
백엔드는 테넌트별로 스코프된 테이블의 행입니다. 각 행은 base URL, API key, 모델 이름, 종류(chat 또는
embedding), 가중치를 지닙니다. 하나를 추가하거나 교체하는 것은 설정 변경입니다 — 배포도, 에이전트 재작성도
없습니다.
의존성 트리 어디에도 벤더 SDK가 없습니다. 게이트웨이는 OpenAI 호환 표면에 대해 평범한 HTTP를 발행하며, 그것이 그 표면을 구현하는 무엇이든 — vLLM, Ollama, llama.cpp 서버, 대부분의 상용 API — 어댑터 코드 없이 동작하는 이유입니다.
능력은 가정되지 않고 프로빙됩니다
시작 시 게이트웨이는 활성화된 백엔드에서 /v1/models를 호출해 그 모델이 실제로 무엇을 제공하는지 읽어옵니다:
컨텍스트 윈도, 임베딩 차원, 선언된 능력.
모델에 대해 하드코딩된 것은 아무것도 없습니다. 이는 들리는 것보다 더 중요합니다: 프런티어 크기의 컨텍스트 윈도를 가정하는 플랫폼은 32K 윈도를 가진 오픈 모델을 조용히 넘쳐흐르게 하고, 그 실패는 오류가 아니라 잘리거나 말이 안 되는 답변으로 표면화됩니다.
백엔드가 프로브에 응답하지 않으면, 게이트웨이는 윈도를 알 수 없음으로 기록하고 작은 숫자를 추측하는 대신 잘라내기를 거부합니다. 잘못된 추측은 모델이 쓸 수 있었던 컨텍스트를 조용히 삭제하고, 시도하고 실패하는 것은 적어도 눈에 보입니다.
작은 오픈 모델이 깨지는 네 가지 방식
이들은 가설이 아닙니다. 각각은 실제로 나타났기에 처리됩니다.
1. 도구 호출이 텍스트로 도착함
많은 오픈 모델이 구조화된 tool_calls 필드를 무시하고 대신 답변 본문에 호출을 씁니다. 지금까지 프로덕션에 도달한 형태는 아홉 가지이고, 그 숫자 자체가 이 절에서 가장 정직한 부분입니다. 하나하나가 잘못 나간 답변을 읽다가 발견된 것이지 코드를 읽다가 발견된 것은 하나도 없습니다. 그러니 아홉 번째가 마지막이라고 볼 이유는 없습니다. 흔한 것은 두 가지입니다:
<tool_call>
<function=search_docs>
<parameter=query>refund policy</parameter>
</function>
</tool_call><tool_call>
{"name": "search_docs", "arguments": {"query": "refund policy"}}
</tool_call>나머지 일곱은 울타리조차 없습니다. 벌거벗은 JSON 객체, doc_update_section({"key": …})처럼 한 줄의 코드로 쓰인 호출, call: 또는 call:네임스페이스:도구 접두사, 토큰 한도에 절반이 잘린 JSON 객체, 그리고 가장 최근의 것으로 {{ query_knowledge_table }}라는 일곱 글자만으로 이루어진 답변 전체입니다.
처리하지 않으면 아무것도 실행되지 않고 엔드유저는 채팅에서 원시 마크업을 봅니다. 도구 루프는 이 형태들을 파싱하고 도구를 정상적으로 디스패치하며 — 최후의 보루로 — 텍스트가 보내지기 전에 남은 호출 구문을 제거합니다. 원시 도구 호출 구문은 파싱이 실패하더라도 엔드유저에게 절대 도달해서는 안 됩니다.
그 보루가 스스로 버그가 되지 않도록 규칙이 둘 있고, 둘 다 어겨보고 배운 것입니다. 제거하기 전에 파싱한다: 한 줄의 코드로 쓰인 호출은 실행 가능한 것인데, 초기 버전은 그것을 잔해로 보고 제거했습니다 — 그래서 문서는 한 글자도 바뀌지 않았는데 모델은 다 고쳤다고 명랑하게 보고했습니다. 제거해서 비면 다시 답한다: 구문을 걷어내고 아무것도 남지 않으면, 그 턴은 빈 채로 보내지 않고 다시 작성합니다.
2. 스트리밍된 도구 호출이 조각으로 도착함
OpenAI 호환 서버들은 도구 호출을 스트리밍 청크에 걸쳐 어떻게 나눌지 서로 의견이 다릅니다. 하나의 호출이 여러 부분 델타로 도착할 수 있고, 모델이 도구를 하나 이상 요청할 때는 때때로 뒤섞입니다. 조각은 인덱스별로 누적되어 어떤 도구가 실행되기 전에 완전한 호출로 재조립됩니다.
3. 컨텍스트 예산은 실제 윈도에서 나와야 함
사용 가능한 입력 예산은 설정되지 않고 유도됩니다:
input_budget =
probed_context_window − output_reservation − safety_margin바닥값이 있어서 공격적인 예약이 예산을 결코 0으로 몰지 못하게 합니다. 32K 모델에서는 백만 토큰 모델과 매우 다른 예산이 나오며, 그것이 바로 요점입니다 — 같은 에이전트 정의가 둘 다에서 올바르게 실행됩니다.
4. 추론이 답변을 잡아먹음
최종 답변 전에 추론을 내보내는 모델에서, 답변만을 위해 크기가 정해진 출력 예산은 추론에 잡아먹히고, 사용자는 잘린 답변을 받습니다. 출력 허용량은 추론 토큰을 고려해 올려져, 답변 자체가 살아남게 합니다.
라우팅과 페일오버
같은 종류의 백엔드는 가중치로 선택되므로, 트래픽을 나눌 수 있습니다 — 예컨대 대부분의 요청은 작은 자체 호스팅 모델로, 나머지는 더 강한 호스팅 모델로. 요청이 재시도 가능한 방식으로 실패하면, 게이트웨이는 지수 백오프로 되돌아가기 전에 다른 적격 백엔드를 시도합니다.
실용적 패턴은 난이도가 아니라 결과의 무게로 나누는 것입니다: 읽기 전용과 저위험 작업은 값싼 모델에, 쓰거나 커밋하는 것은 무엇이든 더 강한 모델에.
이것이 하지 않는 것
가장자리에 대해 정직한 것이 더 긴 기능 목록보다 유용합니다:
- 작은 모델을 큰 모델만큼 유능하게 만들지 않습니다. 도구 선택 — 지저분한 다단계 상황에서 어떤 도구를 어떤 인자로 호출할지 결정하는 것 — 이 모델 품질이 가장 잘 드러나는 곳입니다. 고위험 작업을 작은 모델로 옮기기 전에 당신 자신의 작업을 테스트하세요.
- 당신의 추론 인프라를 관리하지 않습니다. 자체 호스팅한다면, GPU 용량, 모델 서버와 그 가동 시간은 당신의 것입니다. 게이트웨이는 다운된 백엔드를 우회해 라우팅하지만, 하나를 더 빠르게 만들 수는 없습니다.
- 특정 모델을 인증하지 않습니다. 호환성 작업은 모델이 만들어내는 형태에 관한 것이지 테스트된 목록이 아닙니다. 어떤 OpenAI 호환 엔드포인트든 동작할 것으로 기대되며, 어떤 모델이 당신의 워크로드에 맞는지는 당신이 실행해야 할 평가입니다.
관련
- 자체 모델 반입하기 — 통합하는 사람이 아니라 결정하는 사람을 위한 같은 주제
- 도구와 스킬 — 에이전트가 실제로 호출할 수 있는 것
- 보안 — 격리, 암호화, 그리고 무엇이 당신의 환경을 떠나는지