LLM

Kimi K2.6 API 실전 가이드 2편 — Thinking 모드, preserve_thinking, 함수 호출, 프리픽스 캐싱 완전정리

cell-devlog 2026. 6. 1. 10:20
반응형

K2.6 아키텍처와 벤치마크를 알았으니 이제 실제로 씁니다. API 키 발급부터 Thinking 모드, 함수 호출, 프리픽스 캐싱 최적화까지 — 코드 그대로 쓸 수 있게 정리합니다.


핵심 요약

→ 엔드포인트: https://api.moonshot.ai/v1 — OpenAI SDK 완전 호환
→ 모델 ID: kimi-k2.6 (Instant), kimi-k2.6-thinking (Thinking 모드)
→ 기존 K2/K2.5 시리즈는 2026년 5월 25일 종료 — 신규 프로젝트는 K2.6 직접 사용
→ Thinking 모드: temperature 고정 1.0, reasoning_content 스트리밍
→ preserve_thinking: 멀티턴에서 추론 맥락 유지 — 기본값 off, 에이전트 루프에 필수
→ 함수 호출: 최대 128개 tools 배열, OpenAI tool_choice 호환
→ 프리픽스 캐싱: 동일 시스템 프롬프트 재전송 시 입력 비용 ~75% 절감
→ 공식 API 가격: 입력 $0.60/1M, 출력 $3.00/1M
→ Thinking 모드에서 $web_search 빌트인 툴 임시 비호환 — 웹 검색 필요 시 Thinking 비활성화
→ 멀티모달: 이미지/비디오 입력 가능, MoonViT 400M 인코더 (현재 API 노출 제한적)
→ 프로바이더 14개 — 용도별 선택 전략 정리


실전 1 — 5분 셋업: 첫 요청까지

API 키 발급

  1. platform.moonshot.ai 접속
  2. 계정 생성 후 API Keys 메뉴
  3. 키 발급 — sk-... 형식

패키지 설치

pip install openai  # OpenAI SDK 그대로 사용

첫 요청

from openai import OpenAI

client = OpenAI(
    api_key="sk-YOUR_KEY",
    base_url="https://api.moonshot.ai/v1"
)

response = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[
        {"role": "system", "content": "당신은 시니어 백엔드 개발자입니다."},
        {"role": "user", "content": "Python async 웹 스크레이퍼를 에러 핸들링 포함해서 작성해주세요."}
    ],
    temperature=0.6,  # Instant 모드 권장값
    max_tokens=4096
)

print(response.choices[0].message.content)

모델 ID 주의: 구버전인 kimi-k2, kimi-k2-turbo-preview, kimi-thinking-preview는 2026년 5월 25일 종료됐습니다. 기존 코드가 있다면 kimi-k2.6으로 교체 필수.


실전 2 — Thinking vs Instant 모드 선택 기준

K2.6의 가장 큰 차별점 중 하나입니다. 두 모드의 특성을 이해하고 상황에 맞게 선택해야 합니다.

모드 비교

항목 Instant 모드 Thinking 모드

모델 ID kimi-k2.6 kimi-k2.6-thinking
temperature 0.6 권장 1.0 고정 (변경 불가)
응답 방식 직접 답변 reasoning_content 먼저, 답변 후
속도 빠름 느림 (추론 토큰 추가)
적합한 작업 코드 완성, 단순 추출, 분류 복잡한 디버깅, 수학, 멀티스텝 에이전트
AIME 2026 96.4%

Thinking 모드 스트리밍 구현

stream = client.chat.completions.create(
    model="kimi-k2.6-thinking",
    messages=[
        {"role": "user", "content": "이 재귀 함수의 시간복잡도를 분석하고 최적화하세요."}
    ],
    stream=True
)

for chunk in stream:
    delta = chunk.choices[0].delta
    
    # 추론 과정 (사용자에게 숨기거나 별도 표시 가능)
    if hasattr(delta, "reasoning_content") and delta.reasoning_content:
        print(f"[thinking] {delta.reasoning_content}", end="", flush=True)
    
    # 최종 답변
    if delta.content:
        print(delta.content, end="", flush=True)

주의: Thinking 모드에서 temperature를 1.0이 아닌 값으로 설정하면 에러가 납니다. Moonshot 공식 문서 명시 사항.

Thinking 비활성화 (Instant로 강제)

# kimi-k2.6 또는 kimi-k2.5 모델에서 thinking 명시적 비활성화
response = client.chat.completions.create(
    model="kimi-k2.6",
    messages=[...],
    extra_body={
        "thinking": {"type": "disabled"}
    }
)

실전 3 — preserve_thinking: 멀티턴 에이전트의 핵심

기본값 off인데, 에이전트 루프를 짜면 반드시 켜야 합니다.

왜 필요한가

Thinking 모드에서 모델이 추론을 진행할 때 reasoning_content가 생성됩니다. 멀티턴 대화에서 이 추론 내용을 다음 턴에 전달하지 않으면, 모델이 이전 맥락을 잃어버립니다. preserve_thinking을 활성화하면 추론 내용이 컨텍스트에 유지됩니다.

# ❌ preserve_thinking 없는 멀티턴 — 추론 맥락 손실
messages = [
    {"role": "user", "content": "이 코드베이스의 버그를 찾아줘"},
    {"role": "assistant", "content": "버그 A를 발견했습니다..."},
    # assistant의 reasoning_content가 전달되지 않음 → 다음 턴에서 맥락 단절
    {"role": "user", "content": "이제 그 버그를 수정해줘"}
]

# ✅ preserve_thinking 활성화 — 추론 맥락 유지
response = client.chat.completions.create(
    model="kimi-k2.6-thinking",
    messages=messages,
    extra_body={
        "thinking": {
            "type": "enabled",
            "preserve_thinking": True  # ← 멀티턴 에이전트에서 필수
        }
    }
)

# 다음 턴을 위해 reasoning_content 포함해서 messages에 추가
assistant_msg = response.choices[0].message
messages.append({
    "role": "assistant",
    "content": assistant_msg.content,
    "reasoning_content": assistant_msg.reasoning_content  # 보존
})

공식 문서 명시: 멀티스텝 함수 호출 시 현재 턴의 reasoning_content를 컨텍스트에 반드시 포함해야 합니다. 누락 시 에러 발생.


실전 4 — 함수 호출(Function Calling) 실전

tools 배열 최대 128개 지원, OpenAI tool_choice 완전 호환입니다.

import json

# 도구 정의
tools = [
    {
        "type": "function",
        "function": {
            "name": "get_github_issue",
            "description": "GitHub 레포지토리의 이슈를 가져옵니다",
            "parameters": {
                "type": "object",
                "properties": {
                    "owner": {"type": "string", "description": "레포 소유자"},
                    "repo": {"type": "string", "description": "레포 이름"},
                    "issue_number": {"type": "integer", "description": "이슈 번호"}
                },
                "required": ["owner", "repo", "issue_number"]
            }
        }
    },
    {
        "type": "function",
        "function": {
            "name": "run_code",
            "description": "Python 코드를 실행하고 결과를 반환합니다",
            "parameters": {
                "type": "object",
                "properties": {
                    "code": {"type": "string", "description": "실행할 Python 코드"}
                },
                "required": ["code"]
            }
        }
    }
]

messages = [
    {"role": "user", "content": "microsoft/vscode#12345 이슈를 분석하고 수정 코드를 작성해줘"}
]

# 1단계: 모델이 tool_call 요청
response = client.chat.completions.create(
    model="kimi-k2.6",
    messages=messages,
    tools=tools,
    tool_choice="auto"
)

msg = response.choices[0].message

# 2단계: tool_call이 있으면 실행
if msg.tool_calls:
    messages.append(msg)  # assistant 메시지 추가
    
    for tool_call in msg.tool_calls:
        func_name = tool_call.function.name
        args = json.loads(tool_call.function.arguments)
        
        # 실제 함수 실행 (여기서는 예시)
        if func_name == "get_github_issue":
            result = fetch_github_issue(**args)  # 실제 구현 필요
        elif func_name == "run_code":
            result = execute_python(args["code"])  # 실제 구현 필요
        
        # tool 결과 추가
        messages.append({
            "role": "tool",
            "tool_call_id": tool_call.id,
            "content": json.dumps(result, ensure_ascii=False)
        })
    
    # 3단계: 결과를 포함해서 최종 응답
    final_response = client.chat.completions.create(
        model="kimi-k2.6",
        messages=messages,
        tools=tools
    )
    print(final_response.choices[0].message.content)

웹 검색 빌트인 툴 주의: $web_search 빌트인 툴은 현재 Thinking 모드와 임시 비호환입니다. 웹 검색이 필요한 에이전트는 Thinking 비활성화 후 사용하거나, 커스텀 search tool로 우회하세요.


실전 5 — 프리픽스 캐싱으로 에이전트 비용 75% 절감

에이전트 루프에서 가장 효과적인 비용 최적화 방법입니다.

왜 효과가 큰가

에이전트 루프는 매 턴마다 동일한 시스템 프롬프트 + 도구 스키마를 재전송합니다. 이 부분이 캐싱되면 입력 비용이 대폭 줄어듭니다.

# 시스템 프롬프트가 길수록 캐싱 효과 큼
SYSTEM_PROMPT = """
당신은 시니어 풀스택 개발자입니다.
[여기에 긴 컨텍스트: 코드베이스 설명, 코딩 가이드라인, 
프로젝트 구조, 제약 조건 등 — 수천 토큰]
"""

# 멀티턴 대화 — 시스템 프롬프트는 첫 턴에만 전송
# 이후 턴부터 자동 캐시 히트

# 비용 계산 예시 (256K 입력 기준)
# 캐싱 없음: 256,000 × $0.60/1M = $0.154
# 캐싱 적용 (DeepInfra): 256,000 × $0.15/1M = $0.038
# → 약 75% 절감

프로바이더별 캐싱 지원 현황

프로바이더 캐시 토큰 가격 비고

DeepInfra $0.15/1M 유일하게 명시적 캐시 가격 공개
Moonshot 공식 자동 적용 가격 별도 미공개
기타 미공개 내부 최적화 여부 불명확

에이전트 루프 비용이 중요하다면 DeepInfra가 현재 가장 투명한 선택입니다.


실전 6 — 프로바이더 선택 가이드

현재 14개 프로바이더에서 K2.6 서비스 중입니다.

프로바이더 입력 출력 TTFT TPS 추천 용도

DeepInfra (FP4) $0.75 $3.50 0.53s 77 프로덕션 에이전트, 캐싱 필수
Parasail $0.75 $3.50 2.61s 최저가, 레이턴시 덜 중요한 배치
Fireworks 350 최고 TPS 필요 시
CoreWeave 225 고속 처리
OpenRouter $0.684 $3.42 멀티프로바이더 폴백
Moonshot 공식 $0.60 $3.00 네이티브 기능 전체
Cerebras 별도 협의 981 엔터프라이즈 초고속 (3편에서 상세)

선택 기준

✅ 프로덕션 에이전트 루프 → DeepInfra (캐시 가격 투명, 균형)
✅ 최저 비용 배치 처리 → Parasail
✅ 초고속 스트리밍 UX → Fireworks (350 TPS)
✅ 멀티모달 네이티브 기능 → Moonshot 공식 API
✅ IDE 통합 (Cursor/VS Code) → Atlas Cloud (MCP 지원)
✅ 가용성 우선 → OpenRouter (21개 프로바이더 자동 폴백)

마무리

항목 평가

✅ OpenAI SDK 완전 호환 마이그레이션 비용 거의 없음
✅ Thinking/Instant 모드 유연 전환 비용·성능 트레이드오프 제어 가능
✅ preserve_thinking 롱 에이전트 루프 품질 유지
✅ 함수 호출 최대 128개 복잡한 오케스트레이션 대응
✅ 프리픽스 캐싱으로 최대 75% 절감 에이전트 비용 구조 개선
❌ Thinking + $web_search 임시 비호환 웹 검색 에이전트 구조 주의
❌ Thinking 모드 temperature 1.0 고정 파인 컨트롤 불가
❌ MoonViT API 노출 제한적 멀티모달 기능 일부 프로바이더만

3편에서는 Cerebras가 이 모델을 초당 981 토큰으로 돌린 원리 — Wafer-Scale Engine 아키텍처, GPU 클라우드와의 구조적 차이, 에이전트 개발자가 실제로 고려해야 할 인프라 선택 기준까지 다룹니다.


관련 글

 

반응형