실용적 조언
- Unsloth GGUF를 사용하여 템플릿 필터 오류를 방지하라.
- 서버 응답에서 <tool_call> 태그를 직접 추출하는 정규표현식 파서를 클라이언트 코드에 추가하라.
- 응답에 도구 호출이 포함되어 있다면 stop_reason을 강제로 tool_use로 변경하여 에이전트 중단을 막아라.
- LM Studio 0.4.9 이상 버전을 사용하여 서버 측 파싱 안정성을 확보하라.
섹션별 상세
Qwen 3.5는 도구 호출을 XML 형식으로 생성하지만 서버가 이를 제대로 파싱하지 못하는 문제가 있다. llama.cpp의 peg-native 파서는 XML 앞에 일반 텍스트가 오거나 추론 블록이 활성화된 경우 파싱에 실패하여 도구 호출을 일반 텍스트로 출력하고 finish_reason을 stop으로 반환한다. 이로 인해 에이전트가 도구를 실행하지 못하고 멈추는 현상이 발생한다.
추론 태그(think tags)가 텍스트로 유출되어 컨텍스트를 오염시키는 결함이 확인됐다. llama.cpp는 enable_thinking: false 설정에도 불구하고 내부적으로 thinking=1을 강제하여 태그가 누적되며, 이는 멀티 턴 세션의 품질을 저하시킨다. Ollama는 v0.17.6에서 이를 수정했으나 llama.cpp b8664 버전에서는 여전히 해결되지 않은 상태이다.
서버가 도구 호출이 포함된 응답에 대해 잘못된 finish_reason을 반환하는 문제가 심각하다. 많은 서버가 도구 호출 시에도 stop, eos_token, null 등을 반환하며, 이로 인해 대부분의 에이전트 프레임워크는 이를 최종 답변으로 오해하여 충돌하거나 루프를 종료한다. vLLM 0.19.0과 LM Studio 0.4.9는 이 문제를 비교적 잘 처리하는 것으로 나타났다.
안정적인 에이전트 구축을 위해 Unsloth GGUF 사용과 클라이언트 측 안전장치 구현이 권장된다. Unsloth는 기본 Jinja 템플릿의 필터 오류를 수정한 21개의 템플릿 패치를 제공한다. 또한 서버의 파싱 실패를 대비해 정규표현식으로 XML을 직접 추출하고 stop_reason을 tool_use로 강제 변경하는 파이썬 함수를 적용하면 신뢰도를 99%까지 높일 수 있다.
python
import re, json, uuid
# 1. Parse Qwen XML tool calls from text content
def parse_qwen_xml_tools(text):
results = []
for m in re.finditer(r'<tool_call>([\s\S]*?)</tool_call>', text):
args = {}
for p in re.finditer(r'<parameter name="(.*?)">([\s\S]*?)</parameter>', m.group(2)):
k, v = p.group(1).strip(), p.group(2).strip()
try:
v = json.loads(v)
except:
pass
args[k] = v
results.append({"id": f"call_{uuid.uuid4().hex[:24]}", "name": m.group(1), "args": args})
return results
# 2. Fix finish_reason
def fix_stop_reason(message):
has_tools = any(b.get("type") == "tool_call" for b in message.get("content", []))
if has_tools and message.get("stop_reason") in ("stop", "error", "eos_token", "", None):
message["stop_reason"] = "tool_use"서버에서 실패하는 Qwen XML 도구 호출 파싱과 잘못된 종료 사유를 클라이언트 측에서 강제로 수정하는 안전장치 코드
용어 해설
- 도구 호출(Tool Calling)
- — LLM이 외부 API나 함수를 실행하기 위해 특정 형식(JSON, XML 등)의 명령을 생성하는 기능이다. 모델이 텍스트 생성 외에 실질적인 작업을 수행하게 하는 에이전트 아키텍처의 핵심 요소이다.
- 종료 사유(Finish Reason)
- — LLM 추론이 끝난 이유를 나타내는 상태 값이다. 일반 답변은 'stop', 도구 실행이 필요할 때는 'tool_calls' 또는 'tool_use'여야 하며, 이 값이 잘못되면 에이전트 루프가 중단된다.
- 추론 블록(Thinking Block)
- — 모델이 최종 답변을 내놓기 전 내부적으로 사고 과정을 거치는 영역으로 보통 <thought> 태그로 감싸진다. 로컬 서버에서 이 태그가 제대로 처리되지 않으면 답변 본문에 노출되어 컨텍스트를 오염시킨다.
- 진자 템플릿(Jinja Template)
- — 대화 기록을 모델별 특정 프롬프트 형식으로 변환하는 템플릿 엔진이다. Qwen 3.5의 경우 기본 템플릿의 필터 오류로 인해 도구 인자 전달이 실패하는 문제가 보고됐다.
언급된 도구
AI 분석 전체 내용 보기
AI 요약 · 북마크 · 개인 피드 설정 — 무료
출처 · 인용 안내
원문 발행 2026. 04. 06.수집 2026. 04. 06.출처 타입 REDDIT
인용 시 "요약 출처: AI Trends (aitrends.kr)"를 표기하고, 사실 확인은 원문 보기 기준으로 진행해 주세요. 자세한 기준은 운영 정책을 참고해 주세요.