생각 모델

생각 모델 (Thinking Models)

생각 모델은 최종 답변을 내놓기 전에 추론용 토큰으로 먼저 "생각"을 해요. 문제를 분해하고, 단계를 계획하고, 여러 방안을 평가하는 과정이 응답의 reasoning_content 필드에 실려서 내려와요. 먼저 생각하고 답하는 방식 덕분에 복잡한 추론·코드 생성·다단계 도구 호출 성능이 좋아지지만, 그 대가로 지연이 더 길어지고 토큰 소모도 늘어나요. 이 문서는 Kimi API 공식 문서의 思考模型 페이지를 해요체로 옮긴 거예요. 원문은 Kimi API Docs에서 확인할 수 있어요.

시나리오별 모델 선택

  • kimi-k3 — 플래그십 생각 모델. 항상 추론하고 Preserved Thinking이 항상 켜져 있어서 reasoning_content를 돌려줄 수 있어요. 요청 최상위 reasoning_effort("low" / "high" / "max", 기본 "max")로 추론 강도를 조절해요.
  • kimi-k2.7-code — 코드 시나리오용. 생각이 항상 켜져 있고 Preserved Thinking도 항상 켜져 있어요. 고속판 kimi-k2.7-code-highspeed는 같은 모델이라 생각 동작도 완전히 동일해요.
  • kimi-k2.6 — 일반용 생각 모델. 기본적으로 생각이 켜져 있고 필요 시 끌 수 있으며, Preserved Thinking을 지원해요.
요청 필드 kimi-k3 kimi-k2.7-code kimi-k2.6
reasoning_effort "low"/"high"/"max" (기본 "max") 미지원 미지원
thinking.keep 미전달이나 "all" 모두 "all"로 처리(항상 켬, 다른 값은 오류) null(기본, 미보존)/"all"(보존)

기본 호출

kimi-k3 호출하기

kimi-k3는 항상 추론하고 Preserved Thinking이 항상 켜져 있으므로 thinking 파라미터를 넘길 필요도 없고 넘기면 안 돼요. model만 지정하고 필요 시 최상위 reasoning_effort로 추론 강도를 조절하면 돼요.

client = OpenAI(
    api_key=os.environ["MOONSHOT_API_KEY"],
    base_url="https://api.moonshot.cn/v1",
)

completion = client.chat.completions.create(
    model="kimi-k3",
    messages=[{"role": "user", "content": "루트 2가 무리수임을 증명하세요."}],
)

다중 턴 대화와 도구 호출에서는 API가 돌려준 전체 assistant 메시지(reasoning_content 포함)를 원형 그대로 messages에 되돌려 보내야 해요.

kimi-k2.7-code 호출하기

kimi-k2.7-codekimi-k2.6과 같은 생각 메커니즘(reasoning_content, 다단계 도구 호출, 스트리밍 등)을 공유해요. thinking 파라미터는 넘기지 않고, model만 바꾸면 모델이 항상 reasoning_content를 출력해요. Preserved Thinking이 항상 켜져 있으니 다중 턴에서 매 턴 assistant 메시지의 reasoning_content를 꼭 원형 그대로 보존해 주세요.

kimi-k2.6 호출하기

kimi-k2.6은 기본으로 생각이 켜져 있어서, thinking 파라미터 없이 호출해도 추론 내용이 함께 나와요. 생각을 끄거나 Preserved Thinking을 켜려면 thinking 파라미터를 쓰면 돼요.

생각 동작 제어하기

K3: reasoning_effort로 추론 강도 조절

kimi-k3thinking 파라미터를 지원하지 않아요. 대신 요청 최상위 reasoning_effort"low" / "high" / "max" 세 단계(기본 "max")를 지정해 추론 깊이·지연·토큰 소모를 조절해요.

kimi-k2.6: thinking 파라미터로 생각 제어

  • thinking.type"enabled"(기본) | "disabled". 생각 켜고 끄기. 기본이 "enabled"라 예시처럼 명시하지 않아도 생각해요.
  • thinking.keepnull(기본, 이력 턴 생각 무시) | "all" (이력 턴의 reasoning_content를 보존, Preserved Thinking).

응답에서 reasoning_content 읽기

kimi-k2.7-code·kimi-k2.6 같은 생각 모델은 reasoning_content 필드로 생각 내용을 실어 보내요. 읽을 때 주의할 점:

  • openai SDK의 ChoiceDeltaChatCompletionMessage 타입에는 reasoning_content 필드가 선언돼 있지 않아요. hasattr(obj, "reasoning_content")로 존재 여부를 판단한 뒤 있으면 getattr(obj, "reasoning_content")로 값을 가져와야 해요.
  • HTTP로 직접 붙은 경우엔 content 필드와 같은 레벨의 reasoning_content 필드를 바로 읽으면 돼요.
  • 스트리밍(stream=True)에서는 reasoning_content가 항상 content보다 먼저 오니까, content가 등장했는지로 생각(추론)이 끝났는지를 판단할 수 있어요.
  • reasoning_content에 들어간 토큰도 max_tokens 제한을 받아요. 즉 reasoning_content 토큰 + content 토큰 ≤ max_tokens가 돼야 해요.

다단계 도구 호출 구성하기

kimi-k2.7-codekimi-k2.6(생각 켰을 때)은 깊은 추론으로 다단계 도구 호출을 해서 매우 복잡한 작업도 처리할 수 있어요. 최상의 효과를 위해 생각 모드를 쓸 때는:

  • 한 번의 도구 호출 루프 안에서 생긴 모든 생각(reasoning_content)을 컨텍스트에 보존하고 요청에 함께 보내요. 턴을 넘어서 보존할지는 thinking.keep이 결정해요 (kimi-k2.6은 기본 null 미보존, kimi-k2.7-code는 항상 보존).
  • max_tokens>=16000으로 설정해서 reasoning_contentcontent가 온전히 출력되게 해요.
  • temperature는 설정하지 마세요. kimi-k2.7-code·kimi-k2.6temperature를 바꿀 수 없어서 기본값을 쓰고, 명시적으로 넘기지 말아요.
  • stream=True 스트리밍을 써요. 생각 모델은 일반 모델보다 출력이 많아서 스트리밍이 UX도 좋고 네트워크 타임아웃도 어느 정도 피할 수 있어요.

다중 턴에서 생각 보존 (Preserved Thinking)

Preserved Thinking은 다중 턴 대화에서 과거 턴(previous turns)의 reasoning_content를 모델에 그대로 넘겨서, 이번 턴 추론이 이전의 생각 맥락을 이어가게 하는 방식이에요.

kimi-k2.6thinking.keep으로 제어해요.

동작
null/미전달(기본) 이력 턴 reasoning_content 무시. 컨텍스트가 짧아져 비용이 낮아요.
"all" 이력 턴 reasoning_content 완전 보존, Preserved Thinking 활성화.

참고: thinking.keep이력 턴의 reasoning_content에만 영향을 주고, 이번 턴에 모델이 생각을 낼지 말지는 바꾸지 않아요(그건 thinking.type이 결정). keep: "all"type: "enabled"와 함께 쓰는 걸 권장해요. kimi-k2.7-code는 Preserved Thinking이 항상 켜져 있고 꺼지지 않아서, thinking.keep을 미전달하거나 "all"을 주면 "all"로 처리되고 다른 값을 주면 오류가 나요. 이 모델을 쓸 때는 이력 턴 assistant 메시지의 reasoning_content 원형 그대로 보존해야 해요.

keep: "all"을 쓸 때는 매 턴 assistant 메시지의 reasoning_contentmessages에 그대로 넣어야 해요. 가장 간단한 방법은 이전 턴 API가 돌려준 assistant 메시지를 통째로 messages에 append하는 거예요.

messages = [
    {"role": "system", "content": "당신은 Kimi입니다."},
    {"role": "user", "content": "첫 번째 질문..."},
    {
        "role": "assistant",
        "reasoning_content": "<이전 턴 API가 돌려준 reasoning_content>",
        "content": "<이전 턴 API가 돌려준 최종 답변>",
    },
    {"role": "user", "content": "이전 분석을 바탕으로 다음 단계를 계속 추론해 주세요."},
]

response = client.chat.completions.create(
    model="kimi-k2.6",
    messages=messages,
    stream=True,
    extra_body={"thinking": {"type": "enabled", "keep": "all"}},
)

경고: reasoning_content는 토큰 소모에 포함돼요. Preserved Thinking을 켜면 이력 생각이 계속 컨텍스트를 차지하고 과금되니 상황에 맞게 써야 해요.

자주 묻는 질문

Q1. 왜 reasoning_content를 보존해야 하나요? 다단계 추론의 연속성을 보장하기 위해서예요. 특히 도구 호출 과정에서요. API가 돌려준 전체 assistant 메시지를 messages에 원형 그대로 되돌려 보내야 해요. K3는 다중 턴과 도구 호출 모두에서 그래야 하고, K2.x는 모델별 thinking.keep이 결정해요 (kimi-k2.6은 기본 미보존, kimi-k2.7-code는 항상 보존).

Q2. reasoning_content가 추가 토큰을 소모하나요? 네. reasoning_content는 입력/출력 토큰 소모에 모두 포함돼요. 구체적인 과금은 제품 가격을 확인하세요.

더 알아보기