azosi · 2026.7.22 04:47 · 조회 0
Kimi Thinking
상위 문서: ← Kimi Model Capabilities 출처: Kimi API Platform 공식 문서 — Thinking Mode 한글화 (2026-07-22) 공급사: Moonshot AI (月之暗面)
Kimi 사고 모델은 최종 답변 전에 reasoning_content(추론 트레이스)를 출력합니다 — 복잡한 추론, 코드 생성, 다단계 도구 호출에 적합합니다. 이 문서는 네 가지 사고 모델(kimi-k3, kimi-k2.7-code, kimi-k2.6, kimi-k2.5)의 차이, K2.x의 thinking 파라미터, K3의 reasoning_effort, 추론 콘텐츠 읽는 법, 다단계 도구 호출 설정과 Preserved Thinking을 설명합니다.
1. 사고 모델 선택
| 모델 | 사고 모드 | Preserved Thinking | 사고 강도 설정 |
|---|---|---|---|
kimi-k3 | 항상 ON | 항상 ON | 최상위 reasoning_effort: "low" / "high" / "max" (기본 "max") |
kimi-k2.7-code | 항상 ON | 항상 ON | thinking 파라미터 불필요 (항상 사고, reasoning_content 반환) |
kimi-k2.6 | 기본 ON (비활성화 가능) | 지원 (선택) | thinking.type: "enabled"(기본) / "disabled", thinking.keep: null / "all" |
kimi-k2.5 | 기본 ON (비활성화 가능) | 미지원 | thinking.type: "enabled"(기본) / "disabled", thinking.keep 없음 |
요청 파라미터 비교:
| 필드 | kimi-k3 | kimi-k2.7-code | kimi-k2.6 | kimi-k2.5 |
|---|---|---|---|---|
reasoning_effort | "low"/"high"/"max" (기본 "max") | 미지원 | 미지원 | 미지원 |
thinking.type | — | "enabled"만 (비활성화 시 에러) | "enabled"(기본) / "disabled" | "enabled"(기본) / "disabled" |
thinking.keep | — | "all"만 (유효값이 아니면 에러) | null(기본) / "all" | 없음 (미지원) |
벤치마크 테스트 시 benchmark best practice 참고.
2. kimi-k2.7-code 호출: thinking 파라미터 불필요
kimi-k2.7-code는 코드 특화 사고 모델로, kimi-k2.6과 동일한 사고 메커니즘(reasoning_content, 다단계 도구 호출, 스트리밍 등)을 공유합니다. 유일한 차이는 thinking 파라미터 처리입니다. thinking 파라미터를 전달할 필요 없고 전달하지 마세요 — model만 바꾸면 모델이 항상 reasoning_content를 출력합니다. Preserved Thinking이 항상 ON이므로, 멀티턴 대화에서는 모든 assistant 메시지의 reasoning_content를 messages에 그대로 유지해야 합니다.
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.ai/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
stream = client.chat.completions.create(
model="kimi-k2.7-code",
messages=[
{"role": "system", "content": "You are Kimi."},
{"role": "user", "content": "Implement quicksort in Python."}
],
max_tokens=1024*32,
stream=True,
# temperature 수정 불가, 사고는 항상 ON — 설정 불필요
)
thinking = False
for chunk in stream:
if chunk.choices:
choice = chunk.choices[0]
if choice.delta and hasattr(choice.delta, "reasoning_content"):
if not thinking:
thinking = True
print("=============Start Reasoning=============")
print(getattr(choice.delta, "reasoning_content"), end="")
if choice.delta and choice.delta.content:
if thinking:
thinking = False
print("\n=============End Reasoning=============")
print(choice.delta.content, end="")
3. kimi-k2.6 호출: 기본적으로 사고 출력
kimi-k2.6은 범용 사고 모델입니다. 사고는 기본 활성화되어 있어, 아래 기본 호출은 thinking 파라미터 없이도 추론 콘텐츠를 출력합니다 (비활성화나 Preserved Thinking은 아래 참고).
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.ai/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
stream = client.chat.completions.create(
model="kimi-k2.6",
messages=[
{"role": "system", "content": "You are Kimi."},
{"role": "user", "content": "Please explain why 1+1=2."}
],
max_tokens=1024*32,
stream=True,
# temperature 수정 불가 — 설정 불필요, 사고는 기본 ON
)
thinking = False
for chunk in stream:
if chunk.choices:
choice = chunk.choices[0]
if choice.delta and hasattr(choice.delta, "reasoning_content"):
if not thinking:
thinking = True
print("=============Start Reasoning=============")
print(getattr(choice.delta, "reasoning_content"), end="")
if choice.delta and choice.delta.content:
if thinking:
thinking = False
print("\n=============End Reasoning=============")
print(choice.delta.content, end="")
3-1. thinking 파라미터로 사고 제어
kimi-k2.6의 사고 동작은 thinking 파라미터의 두 하위 필드로 제어합니다.
thinking.type:"enabled"(기본) /"disabled"— 사고 ON/OFF- 기본이
"enabled"라 위 예제는 명시 없이도 사고 수행 - 비활성화 예제는 K2.6 가이드의 Disable Thinking Capability Example 참고
- 기본이
thinking.keep:null(기본, 이전 턴 사고 무시) /"all"(이전 턴reasoning_content유지 — Preserved Thinking 활성화)
4. 응답에서 reasoning_content 읽기
kimi-k2.7-code, 사고를 활성화한 kimi-k2.6 등 사고 모델의 응답은 reasoning_content 필드에 추론을 담습니다. 읽을 때 주의사항:
- OpenAI SDK에서
ChoiceDelta와ChatCompletionMessage타입은reasoning_content를 직접 제공하지 않아.reasoning_content로 접근 불가 —hasattr(obj, "reasoning_content")로 존재 확인 후getattr(obj, "reasoning_content")로 값 가져오기 - 다른 프레임워크나 HTTP API 직접 호출 시
content필드와 같은 레벨에서reasoning_content를 직접 얻을 수 있음 - 스트리밍(
stream=True)에서reasoning_content는 항상content이전에 등장 —content출력을 감지해 추론(추론 과정) 종료 시점 판단 가능 reasoning_content의 토큰도max_tokens제약을 받음 —reasoning_content+content토큰 합계가max_tokens이하여야 함
5. 다단계 도구 호출 설정
kimi-k2.7-code와 사고를 활성화한 kimi-k2.6은 다단계 도구 호출에 걸친 깊은 추론을 수행하도록 설계되어, 매우 복잡한 작업도 처리 가능합니다. 신뢰할 수 있는 결과를 위해 사고 모델 사용 시 아래 규칙을 반드시 따르세요:
- 단일 작업(한 번의 도구 호출 루프 내 다단계 추론) 중에는 모든 reasoning content(
reasoning_content필드)를 컨텍스트에 유지하고 요청에 함께 전송. 모델이 필요한 부분만 골라 추론에 활용. 턴 간 사고 보존 여부는thinking.keep이 제어 (kimi-k2.6은 기본null로 보존 안 함,kimi-k2.7-code는 항상 보존) max_tokens >= 16000설정 —reasoning_content와content가 잘림 없이 반환되도록 보장temperature설정 금지 —kimi-k2.7-code와kimi-k2.6은temperature수정 불가, 기본값 사용, 명시적으로 전달하지 마세요 (Model Parameter Reference 참고)- 스트리밍 활성화 (
stream=True) — 사고 모델은reasoning_content와 일반content를 함께 반환하므로 응답 크기가 큽니다. 스트리밍이 더 나은 UX를 제공하고 네트워크 타임아웃 회피에 도움
5-1. 완전 예제: 일일 뉴스 리포트 생성
아래 예제는 "일일 뉴스 리포트 생성" 시나리오로, 모델이 순차적으로 date(날짜 조회) → web_search(뉴스 검색) 같은 공식 도구를 호출하고, 이 과정 전반에 깊은 추론을 보여줍니다.
import os
import json
import httpx
import openai
class FormulaChatClient:
def __init__(self, base_url: str, api_key: str):
self.base_url = base_url
self.api_key = api_key
self.openai = openai.Client(base_url=base_url, api_key=api_key)
self.httpx = httpx.Client(
base_url=base_url,
headers={"Authorization": f"Bearer {api_key}"},
timeout=30.0,
)
self.model = "kimi-k2.6"
def get_tools(self, formula_uri: str):
r = self.httpx.get(f"/formulas/{formula_uri}/tools")
r.raise_for_status()
return r.json().get("tools", [])
def call_tool(self, formula_uri: str, function: str, args: dict):
r = self.httpx.post(
f"/formulas/{formula_uri}/fibers",
json={"name": function, "arguments": json.dumps(args)},
)
r.raise_for_status()
fiber = r.json()
if fiber.get("status") == "succeeded":
return fiber["context"].get("output") or fiber["context"].get("encrypted_output")
if "error" in fiber:
return f"Error: {fiber['error']}"
return "Error: Unknown error"
def close(self):
self.httpx.close()
client = FormulaChatClient(
os.getenv("MOONSHOT_BASE_URL", "https://api.moonshot.ai/v1"),
os.getenv("MOONSHOT_API_KEY"),
)
# 공식 도구 Formula URI
formula_uris = ["moonshot/date:latest", "moonshot/web-search:latest"]
# 모든 도구 정의 로드 및 매핑 구축
all_tools = []
tool_to_uri = {}
for uri in formula_uris:
for tool in client.get_tools(uri):
func = tool.get("function")
if func and func.get("name"):
tool_to_uri[func["name"]] = uri
all_tools.append(tool)
print(f" Loaded: {func['name']} from {uri}")
messages = [
{"role": "system", "content": "You are Kimi, a professional news analyst. You excel at collecting, analyzing, and organizing information to generate high-quality news reports."},
{"role": "user", "content": "Please help me generate a daily news report including important technology, economy, and society news."}
]
# 다단계 대화 루프
for iteration in range(10):
completion = client.openai.chat.completions.create(
model=client.model,
messages=messages,
max_tokens=1024*32,
tools=all_tools,
)
message = completion.choices[0].message
# 추론 과정 출력
if hasattr(message, "reasoning_content"):
reasoning = getattr(message, "reasoning_content")
if reasoning:
print(f"--- Round {iteration+1} reasoning ---")
print(reasoning[:300] + ("..." if len(reasoning) > 300 else ""))
# assistant 메시지를 컨텍스트에 추가 (reasoning_content 보존)
messages.append(message)
if not message.tool_calls:
print("--- Final answer ---")
print(message.content)
break
for tool_call in message.tool_calls:
func_name = tool_call.function.name
args = json.loads(tool_call.function.arguments)
formula_uri = tool_to_uri.get(func_name)
if not formula_uri:
continue
result = client.call_tool(formula_uri, func_name, args)
messages.append({
"role": "tool",
"tool_call_id": tool_call.id,
"name": func_name,
"content": result,
})
client.close()
6. Preserved Thinking (턴 간 사고 보존)
Preserved Thinking은 멀티턴 대화에서 이전 턴의 reasoning_content를 다음 요청에 함께 전달해, 모델이 현재 턴의 추론에서 이전 사고 사슬을 이어갈 수 있게 합니다.
kimi-k2.6의 경우 thinking.keep 파라미터로 제어:
| 값 | 동작 |
|---|---|
null / 생략 (기본) | 이전 reasoning_content 무시. 컨텍스트 짧고 비용 낮음 |
"all" | 이전 reasoning_content 완전히 보존 — Preserved Thinking 활성화 |
thinking.keep은 이전 턴의reasoning_content에만 영향. 현재 턴의 사고 생성/출력 여부는thinking.type이 제어 (thinking.type=enabled와 함께keep: "all"사용 권장).
kimi-k2.7-code는 Preserved Thinking이 항상 ON이라 끌 수 없음:thinking.keep을 생략하거나 유일한 유효값"all"을 전달하면 항상"all"로 처리 (다른 잘못된 값은 에러). 따라서 이 모델을 사용할 때는 이전 assistant 메시지의reasoning_content를messages에 그대로 유지해야 합니다.
keep: "all" 사용 시, 모든 이전 assistant 메시지의 reasoning_content를 messages에 그대로 유지하세요. 가장 간단한 방법은 이전 API 호출에서 반환된 assistant 메시지를 그대로 다시 추가하는 것입니다.
import os
import openai
client = openai.Client(
base_url="https://api.moonshot.ai/v1",
api_key=os.getenv("MOONSHOT_API_KEY"),
)
# 이전 API 호출의 assistant 메시지(reasoning_content 포함)를 messages에 그대로 유지
messages = [
{"role": "system", "content": "You are Kimi."},
{"role": "user", "content": "First question..."},
{
"role": "assistant",
"reasoning_content": "<이전 API 호출의 reasoning_content>",
"content": "<이전 API 호출의 최종 답변>"
},
{"role": "user", "content": "Please continue the analysis and derive the next step."}
]
response = client.chat.completions.create(
model="kimi-k2.6",
messages=messages,
stream=True,
extra_body={"thinking": {"type": "enabled", "keep": "all"}},
)
⚠️
reasoning_content는 토큰 소비에 포함됩니다. Preserved Thinking을 활성화하면 이전 사고 콘텐츠가 컨텍스트 윈도우를 계속 차지하고 그만큼 과금됩니다. 신중히 사용하세요.
7. 자주 묻는 질문
Q1. 왜 reasoning_content를 유지해야 하나요?
A: reasoning_content 유지는 다단계 추론, 특히 도구 호출 중 연속성을 보장합니다. API가 반환한 완전한 assistant 메시지를 messages에 그대로 다시 전달하세요. K3는 멀티턴 대화와 도구 호출 루프에서 필수입니다. K2.x는 모델별 thinking.keep 동작에 따라 턴 간 보존: kimi-k2.6은 기본 보존 안 함, kimi-k2.7-code는 항상 보존.
Q2. reasoning_content가 추가 토큰을 소모하나요?
A: 네, reasoning_content는 입력/출력 토큰 할당량에 포함됩니다. 자세한 가격은 MoonshotAI 가격 문서를 참고하세요.
변경 이력
| 날짜 | 변경 |
|---|---|
| 2026-07-22 | 초판 작성 (공식 Thinking Mode 가이드 한글화) |
| 2026-07-22 | 제목에 "Kimi" 접두사 추가, 본문 H1 중복 제거 |
댓글
아직 댓글이 없습니다.
댓글을 작성하려면 로그인이 필요합니다.