Kimi K2 Documentation

repository·main·Indexed 27 days ago

https://github.com/moonshotai/kimi-k2

A large-scale Mixture-of-Experts (MoE) language model with 1 trillion total parameters and 32 billion activated parameters per token. Optimized for agentic intelligence, reasoning, and tool use, Kimi K2 is available in Base and Instruct variants. The documentation covers architecture specifications, evaluation results, API access via platform.moonshot.ai, and deployment guidance using inference engines such as vLLM, SGLang, KTransformers, and TensorRT-LLM.

Tokens
7K
Snippets
10
Records
18
Agent score
95%

What's inside Kimi K2

  1. Overview of Kimi K2 Model

    main

    Kimi K2 is a state-of-the-art Mixture-of-Experts (MoE) language model designed for agentic intelligence, including tool use, reasoning, and autonomous problem-solving. It features 1 trillion total parameters with 32 billion activated parameters per token.

    Key Features

    • Large-Scale Training: Pre-trained on 15.5T tokens.
    • MuonClip Optimizer: Utilizes the Muon optimizer for large-scale stability.
    • Agentic Intelligence: Optimized for reasoning and tool-use tasks.

    Model Variants

    • Kimi-K2-Base: The foundation model intended for researchers and builders performing fine-tuning or custom solutions.
    • Kimi-K2-Instruct: A post-trained model optimized for general-purpose chat and agentic experiences. It is described as a reflex-grade model without long thinking processes.
  2. Tool calling in streaming mode

    main

    When using stream=True, tool calls are delivered in chunks. You must accumulate the delta.tool_calls fragments (specifically id, function.name, and function.arguments) into a list until the stream finishes.

    Important: After processing all tool calls and appending the results to messages, you must reset the accumulated text message (msg = '') because the text generated during the tool-calling phase is not the final response.

    messages = [
        {"role": "user", "content": "What's the weather like in Beijing today? Let's check using the tool."}
    ]
    finish_reason = None
    msg = ''
    while finish_reason is None or finish_reason == "tool_calls":
        completion = client.chat.completions.create(
            model=model_name,
            messages=messages,
            temperature=0.3,
            tools=tools,
            tool_choice="auto",
            stream=True 
        )
        tool_calls = []
        for chunk in completion:
            delta = chunk.choices[0].delta
            if delta.content:
                msg += delta.content
            if delta.tool_calls:
                for tool_call_chunk in delta.tool_calls:
                    if tool_call_chunk.index is not None:
                        while len(tool_calls) <= tool_call_chunk.index:
                            tool_calls.append({
                                "id": "",
                                "type": "function",
                                "function": {
                                    "name": "",
                                    "arguments": ""
                                }
                            })
    
                        tc = tool_calls[tool_call_chunk.index]
    
                        if tool_call_chunk.id:
                            tc["id"] += tool_call_chunk.id
                        if tool_call_chunk.function.name:
                            tc["function"]["name"] += tool_call_chunk.function.name
                        if tool_call_chunk.function.arguments:
                            tc["function"]["arguments"] += tool_call_chunk.function.arguments
    
            finish_reason = chunk.choices[0].finish_reason
        if finish_reason == "tool_calls":
            for tool_call in tool_calls:
                tool_call_name = tool_call['function']['name']
                tool_call_arguments = json.loads(tool_call['function']['arguments'])
                tool_function = tool_map[tool_call_name] 
                tool_result = tool_function(tool_call_arguments)
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call['id'],
                    "name": tool_call_name,
                    "content": json.dumps(tool_result),
                })
            msg = ''
    
        print(msg)
  3. Deploy Kimi K2 using inference engines

    main

    Kimi K2 model checkpoints are stored in block-fp8 format and are available on Huggingface.

    For local deployment, it is recommended to use one of the following inference engines:

    • vLLM
    • SGLang
    • KTransformers
    • TensorRT-LLM

    Detailed deployment examples for vLLM and SGLang are available in the docs/deploy_guidance.md file.

  4. Manually parse tool calls from raw text

    main

    If your service does not provide a built-in tool-call parser, you can manually extract tool calls from the model's raw text output using specific delimiters.

    Delimiters:

    • Section start/end: <|tool_calls_section_begin|> and <|tool_calls_section_end|>
    • Individual tool call start/end: <|tool_call_begin|> and <|tool_call_end|>
    • Argument separator: <|tool_call_argument_begin|>

    ID Format: The tool ID follows the pattern functions.{func_name}:{idx}. You can extract the function name by splitting this string.

    Implementation Example:

    def extract_tool_call_info(tool_call_rsp: str):
        if '<|tool_calls_section_begin|>' not in tool_call_rsp:
            return []
        import re
        pattern = r"<\|tool_calls_section_begin\|>(.*?)<\|tool_calls_section_end\|>"
        
        tool_calls_sections = re.findall(pattern, tool_call_rsp, re.DOTALL)
        
        func_call_pattern = r"<\|tool_call_begin\|>\s*(?P<tool_call_id>[\w\.]+:\d+)\s*<\|tool_call_argument_begin\|>\s*(?P<function_arguments>.*?)\s*<\|tool_call_end\|>"
        tool_calls = []
        for match in re.findall(func_call_pattern, tool_calls_sections[0], re.DOTALL):
            function_id, function_args = match
            function_name = function_id.split('.')[1].split(':')[0]
            tool_calls.append(
                {
                    "id": function_id,
                    "type": "function",
                    "function": {
                        "name": function_name,
                        "arguments": function_args
                    }
                }
            )  
        return tool_calls
  5. Prepare tools for Kimi-K2

    main

    To use tool calling, you must provide a structured description of your functions in a tools list. Each tool should be an object of type: "function" containing a function object with name, description, and parameters (following JSON Schema format). It is recommended to maintain a tool_map that maps function names to their actual Python implementations for easy execution during the tool-calling loop.

    def get_weather(city):
        return {"weather": "Sunny"}
    
    # Collect the tool descriptions in tools
    tools = [{
        "type": "function",
        "function": {
            "name": "get_weather",
            "description": "Get weather information. Call this tool when the user needs to get weather information",
            "parameters": {
                "type": "object",
                "required": ["city"],
                "properties": {
                    "city": {
                        "type": "string",
                        "description": "City name",
                    }
                }
            }
        }
    }]
    
    # Tool name->object mapping for easy calling later
    tool_map = {
        "get_weather": get_weather
    }
  6. Chat with tools using OpenAI SDK

    main

    You can use the openai.OpenAI client to interact with Kimi-K2. When the model decides to use a tool, it returns a finish_reason='tool_calls'.

    Workflow:

    1. Send messages and the tools list to the model.
    2. Check if finish_reason == "tool_calls".
    3. If true, iterate through choice.message.tool_calls, execute the local functions using your tool_map, and append the results to the messages list with role='tool'.
    4. Include the tool_call_id, name, and the stringified JSON content of the result.
    5. Repeat the loop until finish_reason is no longer tool_calls.
    import json
    from openai import OpenAI
    model_name='moonshotai/Kimi-K2-Instruct'
    client = OpenAI(base_url=endpoint, api_key='xxx')
    
    messages = [
        {"role": "user", "content": "What's the weather like in Beijing today? Let's check using the tool."}
    ]
    finish_reason = None
    while finish_reason is None or finish_reason == "tool_calls":
        completion = client.chat.completions.create(
            model=model_name,
            messages=messages,
            temperature=0.3,
            tools=tools, 
            tool_choice="auto",
        )
        choice = completion.choices[0]
        finish_reason = choice.finish_reason
        if finish_reason == "tool_calls": 
            messages.append(choice.message)
            for tool_call in choice.message.tool_calls: 
                tool_call_name = tool_call.function.name
                tool_call_arguments = json.loads(tool_call.function.arguments) 
                tool_function = tool_map[tool_call_name] 
                tool_result = tool_function(tool_call_arguments)
                print("tool_result", tool_result)
    
                messages.append({
                    "role": "tool",
                    "tool_call_id": tool_call.id,
                    "name": tool_call_name,
                    "content": json.dumps(tool_result), 
                })
    print('-' * 100)
    print(choice.message.content)
  7. Deploy Kimi-K2 using TensorRT-LLM

    main

    Deployment requires TensorRT-LLM v1.0.0-rc2 built from source.

    Setup Requirements:

    1. Install blobfile: pip install blobfile.
    2. Use mpirun for multi-node serving.
    3. Ensure passwordless SSH access between nodes (e.g., using port 2233).
    4. Create an extra-llm-api-config.yml for trtllm-serve options.

    Multi-node Launch Command: Use trtllm-llmapi-launch trtllm-serve serve with the --backend pytorch flag.

    # Example mpirun command for 2 nodes (8 GPUs each)
    mpirun -np 16 \
    -H <HOST1>:8,<HOST2>:8 \
    -mca plm_rsh_args "-p 2233" \
    --allow-run-as-root \
    trtllm-llmapi-launch trtllm-serve serve \
    --backend pytorch \
    --tp_size 16 \
    --ep_size 8 \
    --kv_cache_free_gpu_memory_fraction 0.95 \
    --trust_remote_code \
    --max_batch_size 128 \
    --max_num_tokens 4096 \
    --extra_llm_api_options /path/to/TensorRT-LLM/extra-llm-api-config.yml \
    --port 8000 \
    <YOUR_MODEL_DIR>
  8. Deploy Kimi-K2 using vLLM

    main

    To deploy Kimi-K2 with vLLM, use version v0.10.0rc1 or later. For FP8 weights with 128k seqlen on H200/H20 platforms, a minimum of 16 GPUs is recommended. You can use either pure Tensor Parallelism (TP) or a combination of Data Parallelism and Expert Parallelism (DP+EP).

    Key Parameters for Tool Usage:

    • --enable-auto-tool-choice: Required to enable tool usage.
    • --tool-call-parser kimi_k2: Required to enable tool usage.
    # Tensor Parallelism (TP <= 16)
    vllm serve $MODEL_PATH \
      --port 8000 \
      --served-model-name kimi-k2 \
      --trust-remote-code \
      --tensor-parallel-size 16 \
      --enable-auto-tool-choice \
      --tool-call-parser kimi_k2
  9. Deploy Kimi-K2 using SGLang

    main

    SGLang supports both Tensor Parallelism (TP) and Data Parallelism + Expert Parallelism (DP+EP).

    Tensor Parallelism (TP16) Example: Run on two nodes (Node 0 and Node 1) using --dist-init-addr to connect them.

    Key Parameter:

    • --tool-call-parser kimi_k2: Required for tool usage.
    # Node 0
    python -m sglang.launch_server --model-path $MODEL_PATH --tp 16 --dist-init-addr $MASTER_IP:50000 --nnodes 2 --node-rank 0 --trust-remote-code --tool-call-parser kimi_k2
    
    # Node 1
    python -m sglang.launch_server --model-path $MODEL_PATH --tp 16 --dist-init-addr $MASTER_IP:50000 --nnodes 2 --node-rank 1 --trust-remote-code --tool-call-parser kimi_k2
  10. Configure model_type in config.json

    main

    Kimi-K2 uses the DeepSeekV3CausalLM architecture. To ensure inference engines apply the correct optimizations and distinguish it from DeepSeek-V3, set the following in your config.json:

    "model_type": "kimi_k2"

    Workaround for unsupported frameworks: If your framework does not recognize kimi_k2, manually change model_type to deepseek_v3. Note that you may need to manually parse tool calls if the framework lacks a specific kimi_k2 parser.