제약 디코딩과 도구 호출에 대한 제약 디코딩은 이미 오래전부터 vLLM에 있던 기능임. 글 전체를 이해하기 전에는 제목처럼 vLLM 자체를 수정했다는 인상을 받기 쉽지만, 실제로는 설정을 제대로 맞추는 이야기라 혼란스러움.
다만 그동안 vLLM의 도구 호출 제약 설정이 바뀌면서 동작까지 달라진 것이 진짜 문제임. 성능을 추적하고 회귀를 포착할 벤치마크를 갖춘 Ubicloud 팀은 높이 평가할 만함. OpenRouter의 일부 제공업체는 다른 업체보다 성능이 납득하기 어려울 정도로 낮고, 이만큼 신경 쓰지 않는 듯함.
이미 있던 기능인데 무엇을 고쳤다는 것인지 혼란스럽다면, 글 마지막의 설정 변경 부분부터 보면 됨.
전반적으로 타당하지만, Kimi가 올바르게 동작하려면 코드 수정이 필요했다는 점은 덧붙이고 싶음. 당시에는 설정만으로 해결할 수 없었고, 이후 vLLM 팀이 업스트림에서 수정함. 최신 vLLM에서는 --tool-strict-level을 parameter로 설정하면 글에서 다룬 문제를 해결할 수 있음.
vLLM의 복잡하고 혼란스러운 구성도 원인 중 하나임. 성능을 제대로 끌어내려면 상당한 시간을 투자해야 하며, 잘 맞추면 정말 뛰어나지만 취약하고 지나치게 복잡함.
글을 재미있게 읽었고, 위에서 짚은 혼란은 느끼지 않았다는 피드백을 저자에게 전하고 싶음.
제목을 “vLLM 자체의 도구 호출 정확도 개선”이 아니라 “vLLM을 활용한 도구 호출 정확도 개선”으로 썼으면 됐을 듯함.
재미있게도 제약 디코딩은 우리가 자기회귀(AR) 모델을 /v1/systemone 엔드포인트로 만들 때 쓰는 접근법이기도 함. 해당 vLLM 기능 개발에 참여했음.
도구 호출에는 함정이 많으며, 특히 실행 내내 모델의 도구 목록이 고정된다는 보장이 없음. 대규모 접두부 캐시 미스를 피하려고 실행 도중 도구를 추가하기도 하는데, 적어도 마지막으로 확인했을 때까지는 이런 갱신을 위한 OpenAI식 채팅 메시지 형식이 업계 표준으로 정착하지 않았음. 완전히 제약된 도구 호출 환경을 훨씬 선호하며, 처음부터 이렇게 무작정 밀어붙이지 않았으면 좋았겠음. PTC 방식은 도구 호출을 JavaScript에 맡겨 일부 해결하지만, 제약을 강제하기는 더 어려움. 해당 방식으로 학습하지 않은 모델은 한 차례 도구 호출에 실패하고 나서야 제대로 처리할 수도 있음.
컨텍스트에 덧붙이기만 하는 대신 기존 컨텍스트를 수정하는 방식은 얼마나 실용적일지 궁금함. 잘못된 도구 호출과 오류 메시지를 지워 컨텍스트 오염을 막는 식임. KV 캐시를 재구축하느라 성능이 떨어지겠지만, 충분히 드물게 발생한다면 감수할 만할 수도 있음.
실제로 실행 도중 도구를 추가할 수 있는 건가? 모델이 컨텍스트 안에서 도구가 놓인 위치를 크게 신경 쓰지는 않겠지만, 실제로 작동하는 방식인 줄은 몰랐음.
“완전히 제약된 도구 호출 환경”은 구체적으로 무엇을 뜻하나?
실제 모델 품질에 미치는 영향도 공개했으면 좋겠음. 스키마 제약 디코딩은 LLM의 출력 분포를 바꾸므로, 실패한 도구 호출을 되돌리고 재시도하는 방식과 비교해 보고 싶음. 이 방식도 컨텍스트를 오염시키지 않고 도구 호출 정확도 100%를 달성할 수 있음.
예시의 성공률인 23/25라면 호출 시도 자체에 쓰는 토큰은 약 9% 늘겠지만, 전체 토큰 중 작은 일부에만 해당함. 재시도 방식이 조금이라도 더 나은 정확도를 보인다면 오히려 유리할 수 있음.
스키마 제약은 유효하지 않은 다음 상태를 금지할 뿐이라, 재시도했을 때의 분포와 같은 비율로 재조정되는 줄 알았는데 아닌가?
아니면 개념적인 토큰별 재시도가 아니라 도구 호출 전체를 재시도하는 편이 낫다는 뜻인가? 처음에 잘못 선택해서 막다른 길에 몰린 모델이 나쁜 상태를 계속 수습하려는 상황이라면 충분히 이해가 됨.
이 글의 공동 저자임. LLM·추론 및 서빙 엔진·제약 디코딩 구현을 통합해 의도한 출력과 전체 품질을 얻으려면 세심한 엔지니어링과 테스트가 필요함. 무엇이든 편하게 질문해 주시길 바람.
그렇다면 도구 호출은 실제로 모델이 하는 것이 아닌가? 모델이 출력을 만들어도, 추론 엔진이 그중 유효한 선택지만 남기도록 걸러내는 결과라는 뜻인지 궁금함.
다른 맥락에도 이런 방식을 적용할 수 있을까? 가중치를 조금 조정해 모델을 동적으로 유도한다는 이야기는 들었는데, 가중치를 유지한 채 샘플러를 조정하는 것만으로도 출력을 상당히 통제할 수 있을 듯함.
<||> 문법이 어디서 유래했는지 아는가? 기존 마크업을 쓰지 않은 점이 매우 특이하고, 온라인에도 정보가 거의 없음.
DFlash나 MTP 같은 추론 최적화 기법과 함께 사용할 수 있나? 속도가 너무 느려져서 차라리 재시도하는 편이 나아지는 것은 아닌가?
조준경에 맞추려고 총열을 휘는 셈임. 글에서는 모델이 학습 중 본 도구명이나 필드명을 현재 환경에도 존재하는 것처럼 생성한다고 설명함. 예를 들어 web_search 대신 search_web을, location 대신 city_name을 생성하는 식임.
그런데 바로 거기에 해결책도 있음. 모델이 search_web을 호출한다면 함수 이름을 search_web으로 바꾸면 됨. 호출 문법을 주지 않고 이름만 보고 무엇을 하는지 살펴보면 더 흥미로워짐.
vLLM 0.28로 Kimi K2.6을 제공할 때 기대한 도구 호출 스키마가 나오는 비율이 92%, 즉 25회 중 2회가 실패했다면, 도구 호출 성공률 100% 가 왜 중요한지 드러남.
성공률이 95%여도 연속으로 실행해야 하는 호출이 50개라면 오류 없이 끝날 확률은 약 8% 에 불과함. 오류 피드백 등으로 복구할 수는 있지만, 에이전트가 계속 잘못된 도구와 인자를 사용하면 전체 시스템이 제대로 작동하기 어려움.
LLM 추론 제공업체와 중국 LLM 연구소들이 최신 vLLM을 빨리 도입했으면 좋겠음. 프롬프트당 약 300회의 도구 호출이 필요한 작업을 하다 보니 2024년부터 OpenAI와 Anthropic만 쓸 수밖에 없었음.
두 회사의 경쟁 우위가 무엇인지 궁금하다면, 이미 2024년에 제약 디코딩을 활용한 도구 호출 정확도 100%와 프롬프트 캐싱을 제대로 구현했다는 점을 보면 됨.
실제로 자주 발생하는 문제인가? 최상위 모델에 Codex나 Claude Code 같은 실행 도구를 붙여도 문법 오류가 있는 코드가 꾸준히 나오나?
Qwen 3.8에서도 작동하나?
vLLM에 Qwen 3.8용 제약 디코딩이 있는 것으로 알고 있음. 다만 문법적으로 올바른 도구 호출을 보장하더라도 제약 디코딩을 켰을 때와 껐을 때의 전체 모델 품질은 비교해 봐야 함.
Kimi는 개발사가 활성화를 명확히 권장하지만, Qwen 3.8도 그런지는 모르겠음.