-
RAG 청크 맥락에서 thinking을 꺼야 하는 이유 — enable_thinking=False가 필요한 순간IT 2026. 5. 6. 23:00
들어가며 — "응답 본문이 비어 있다"
RAG 인덱싱 코드가 청크 한 덩어리에 50토큰짜리 맥락 설명을 붙이는 호출을 했다. 응답을 받았는데, 본문이 비어 있다. 토큰 예산은 다 소진됐고, finish_reason은
length다.로그를 보니 모델이
<think>블록 안에서만 1500토큰을 쓰다가max_tokens한도에 걸려 종료됐다. 본문은 시작도 안 했다.해결은 한 줄이다.
chat_template_kwargs: { enable_thinking: false }이 옵션이 필요한 이유, 어떤 호출 패턴에서 켜고 끄는 게 옳은지를 풀어쓴다. thinking 모델을 운영해본 사람이라면 한 번쯤 마주치는 함정이다.
1. thinking 모델은 토큰 예산을 어떻게 쓰는가
thinking 모델은 답을 내기 전에 "먼저 생각하고 그 다음 답한다" 패턴을 따른다. 일반 챗에서는 좋은 답을 위해 도움이 된다. 하지만 응답 길이가 짧고 정해진 형식인 호출에서는, thinking이 토큰 예산을 다 잡아먹어 본문이 시작도 못 하는 사고가 발생한다.
2. 어떤 호출이 위험한가
경험칙: "응답이 50토큰 미만으로 정해져 있다면 thinking은 OFF가 안전하다." 짧은 정형 응답에서는 thinking이 만든 추론 과정을 사용자가 보지도 않는다 — 그저 토큰 예산을 잡아먹는 짐이다.
3. 호출 단위로 켜고 끈다는 것의 의미
enable_thinking은 서버 설정이 아니라 호출 옵션이다. 같은 모델, 같은 서버에서, 호출자가 호출마다 결정할 수 있다.이게 중요한 이유는 "전역 강제"가 아니기 때문이다. 만약 thinking이 서버 설정이라면, RAG 호출을 위해 끄면 챗봇 호출도 같이 thinking이 사라진다. 호출 단위로 결정할 수 있어야, 같은 모델로 다른 사용 시나리오를 동시에 지원할 수 있다.
4. 호출 코드는 이렇게 생긴다
OpenAI-compat 클라이언트(예: Python
openai라이브러리)에서:response = client.chat.completions.create( model="qwen3.6", messages=[...], max_tokens=200, extra_body={ "chat_template_kwargs": {"enable_thinking": False} } )extra_body로 표준 OpenAI 스펙에 없는 옵션을 vLLM에 전달한다. 이 옵션은 vLLM이 모델의 chat template에 변수로 주입해, 토크나이저가 thinking 시작 토큰을 포함하지 않게 한다.참고로 Ollama 시절에는
think: false옵션이 있었지만, OpenAI-compat 엔드포인트에서는 무시되는 버그가 있었다. vLLM으로 옮기면서 이 문제가 자연스럽게 해결됐다.
5. 실측 — 같은 호출, thinking ON vs OFF
두 호출은 완전히 동일하다 — 단지
enable_thinking한 줄 차이. 결과는 "응답 본문 비어 있음 vs 정상 사용 가능"이다. 게다가 thinking OFF가 latency도 4배 빠르다 (생성 토큰 수 자체가 줄어드니).
정리
thinking 모델은 강력하지만, 모든 호출에서 켜둘 이유는 없다.
- thinking은 답을 내기 전에 추론 과정을 출력 — 토큰 예산을 함께 잡아먹는다.
- 응답이 짧고 정형화된 호출(RAG 맥락, RAGAS 채점, 분류, JSON 추출)에서는 thinking이 본문 예산을 잡아먹어 사고가 난다.
- 일반 챗·코드·수학·긴 글쓰기에서는 thinking ON이 도움 된다.
enable_thinking은 서버 설정이 아니라 호출 옵션이라, 같은 모델·같은 서버에서 호출자가 패턴별로 결정할 수 있다.- 이 옵션 한 줄로 latency도 줄고 본문이 살아난다.
한 줄로 줄이면, "thinking은 도구다 — 적절한 호출에서만 켜라"이다. 전역 강제 대신 호출 단위 결정이 깔끔하다. 그리고 실수를 줄이려면 RAG 인덱싱 같은 정형 호출은 처음부터 thinking OFF를 기본값으로 두는 게 좋다.
이 글은 생성형 AI의 도움을 받아 작성되었습니다. 원본 자료를 기반으로 AI가 초안을 생성하고, 작성자가 검토·편집하였습니다.
'IT' 카테고리의 다른 글
로컬 챗봇 시리즈 #3 — 도구에 '지금 누구의 첨부인지' 어떻게 알려주나: ContextVar 패턴 (0) 2026.05.08 로컬 챗봇 시리즈 #2 — Project 시스템 프롬프트는 왜 글로벌 Custom Instructions '다음에' 와야 하나 (0) 2026.05.08 로컬 챗봇 시리즈 #1 — 메시지 편집은 왜 그렇게 단순해야 하나: 컨텍스트 엔지니어링 관점에서 (0) 2026.05.08 Ralph Loop — bash while true + LLM CLI가 만든 어이없게 강력한 에이전트 패턴 (0) 2026.05.07 GPU 스케줄러를 Ollama warmup에서 vLLM 컨테이너로 옮긴 과정 — 시작·종료 시퀀스를 다시 짜다 (0) 2026.05.06 OpenAI-compat 표준화로 어댑터 100줄 들어내기 — passthrough가 가져온 코드 청결도 (0) 2026.05.06 vLLM reasoning_parser — <think> 블록을 정규식 말고 구조로 받는 법 (0) 2026.05.06 KV cache FP8로 동시 요청 76배 수용하기 — LLM 메모리의 숨은 주범 정리 (0) 2026.05.06 Ollama에서 vLLM으로 백엔드를 바꿨더니 throughput이 148% 올랐다 — 같은 모델, 다른 엔진 (0) 2026.05.06 Gemma 4에서 Qwen 3.6으로 갈아탔다 — 두 모델을 모든 지표로 비교한 기록 (0) 2026.05.06