返回工具研究所
行业深度原创13 分钟阅读

Kimi K3 视觉输入和 1M 长上下文怎么用?图片视频传入与缓存命中技巧

本篇指南解决开发者接入 Kimi K3 时的两大核心痛点:视觉输入格式约束导致的接口报错,以及长上下文调用时的 token 成本失控。适合应用开发者与 API 接入工程师阅读。你将掌握图片视频的正确传入方式、content 对象数组的写法、自动缓存的命中条件及预算控制策略。

2026/07/22

文章速读

这篇文章回答的问题

开发者如何正确配置 Kimi K3 的视觉输入并有效利用 1M 长上下文与自动缓存功能以控制成本?

核心结论

视觉输入必须用 base64 或 ms:// 协议,不支持公网 URL;content 必须是对象数组;1M 上下文自动缓存需保持前缀不变且前一个请求 prompt tokens 大于 256;计费按实际消耗非分段定价,输入 ¥20.00/MTok,缓存命中 ¥2.00/MTok。

关键要点

  • 视觉输入不支持公网 URL,必须用 base64 或 ms:// 协议
  • content 必须是对象数组,不能是序列化后的字符串
  • 图片支持 png/jpeg/webp/gif,视频支持 9 种格式,Body 限制 100M

适用边界:本指南仅覆盖 Kimi K3 的视觉输入格式约束和 1M 长上下文缓存配置,不涉及其他模型的横向对比或未经官方文档核验的底层架构猜测。输出 token 具体价格需以官方定价页为准。

最新工具

刚收录的 AI 工具,适合继续发现可用产品。

查看全部

开发者接入 Kimi K3 时,最常遇到的报错往往是直接填入公网图片 URL 导致请求失败,或者在处理长文档时发现 token 消耗远超预期。Kimi K3 虽然支持原生视觉输入和 1M 超长上下文,但在 API 格式约束和缓存计费上有严格的硬性要求。如果不了解这些底层规则,很容易在开发过程中反复踩坑,不仅影响应用稳定性,还会产生不必要的计费开销。本篇指南将聚焦视觉输入的正确传参方式以及 1M 上下文自动缓存的命中条件,帮助你避开高频错误并有效控制调用成本。

视觉输入为什么不能用公网 URL?该怎么传图片和视频?

在接入多模态大模型时,很多开发者习惯性地将图片的公网链接直接粘贴到请求参数中。但在 Kimi K3 的 API 规范里,这是一个明确的高频错误。Kimi K3 的视觉输入不支持公网 URL,所有多媒体数据必须通过 base64 编码或 ms:// 协议传入。

这个限制的核心原因在于平台对数据可控性和请求稳定性的要求。公网 URL 存在失效、鉴权失败或网络波动等不可控因素,直接拉取会导致请求超时或失败。因此,官方要求开发者自行处理多媒体数据的读取和编码。

对于小体积的图片或短视频,推荐使用 base64 编码方式直接嵌入请求体。你需要将图片或视频文件读取为二进制数据,然后转换为 base64 字符串,并按照特定的前缀格式拼接到 image_url 参数中。例如,一张 PNG 图片的 base64 字符串前需要加上 data:image/png;base64, 前缀。

以下是使用 Python 将本地图片转为 base64 编码并构造请求的示例:

import base64
import requests

def encode_image_to_base64(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

base64_image = encode_image_to_base64("example.png")
image_url = f"data:image/png;base64,{base64_image}"

payload = {
    "model": "kimi-k3",
    "messages": [
        {
            "role": "user",
            "content": [
                {"type": "text", "text": "请描述这张图片的内容"},
                {"type": "image_url", "image_url": {"url": image_url}}
            ]
        }
    ]
}
# 后续发送 requests.post 请求

如果文件体积较大,直接使用 base64 编码会导致请求体膨胀,甚至超出接口限制。这时必须使用 ms:// 协议。具体操作步骤是:先调用官方的文件上传接口,将本地图片或视频上传到平台,接口会返回一个 file-id。随后在视觉请求中,将 image_url 的值设置为 ms://<file-id> 即可。这种方式不仅绕过了请求体大小的限制,还能提升数据传输的稳定性。

以下是调用文件上传接口获取 file-id 并拼接 ms:// 协议的示例:

def upload_file_and_get_id(file_path, api_key):
    headers = {"Authorization": f"Bearer {api_key}"}
    files = {
        "file": (file_path, open(file_path, "rb"), "application/octet-stream"),
        "purpose": (None, "file-extract") # 根据实际文档要求填写 purpose
    }
    # 调用官方文件上传接口
    response = requests.post("官方文件上传接口地址", headers=headers, files=files)
    file_id = response.json()["id"]
    return f"ms://{file_id}"

# 调用示例
ms_url = upload_file_and_get_id("large_video.mp4", "your_api_key")
# 将 ms_url 放入 payload 的 image_url 字段中

传入图片或视频时,content 对象数组怎么写才不会报错?

解决了数据传入方式的问题,接下来是另一个极易报错的环节:content 参数的结构。在 Kimi K3 的 API 中,content 必须是一个对象数组,而不能是 JSON 序列化后的字符串。这是一个非常隐蔽但高频的踩坑点。

很多开发者在拼接请求体时,由于编程语言的处理习惯或序列化库的默认行为,不小心将整个 content 数组转换成了 JSON 字符串再赋值给 content 字段。这种写法不会在参数校验阶段被拦截,但在模型处理阶段会引发 Your request exceeded model token limit 报错。

原因在于,当 content 被当作字符串处理时,模型无法解析其中的多模态结构,而是把整个 JSON 字符串当作纯文本输入。这会导致 token 数量暴增,瞬间撑爆上下文窗口。

以下是错误写法与正确写法的对比:

错误写法(将数组序列化为字符串):

{
  "role": "user",
  "content": "[{\"type\": \"text\", \"text\": \"描述这张图片\"}, {\"type\": \"image_url\", \"image_url\": {\"url\": \"data:image/png;base64,...\"}}]"
}

在这种写法中,content 的值被双引号包裹,变成了一个长字符串。模型会逐字读取这串字符,导致 token 消耗急剧上升。

正确写法(原生对象数组):

{
  "role": "user",
  "content": [
    {"type": "text", "text": "描述这张图片"},
    {"type": "image_url", "image_url": {"url": "data:image/png;base64,..."}}
  ]
}

在代码实现时,务必检查序列化后的最终 JSON 字符串中,content 对应的值是以方括号 [ 开头和结尾,而不是以引号 " 包裹的字符串。如果你使用的是 OpenAI SDK 或类似的封装库,通常直接传入原生的 List/Array 结构即可,不要手动调用 json.dumps() 方法处理 content。

Kimi K3 支持哪些图片和视频格式?文件大小有限制吗?

明确了传入方式和数据结构后,还需要关注多媒体文件本身的格式和体积限制。Kimi K3 对视觉输入有明确的格式白名单和物理限制。

在图片格式方面,支持 png、jpeg、webp 和 gif。推荐分辨率不超过 4K,超过 4K 的图片不仅不会提升模型的理解效果,反而会无谓地增加 token 消耗。在视频格式方面,支持 mp4、mpeg、mov、avi、x-flv、mpg、webm、wmv 和 3gpp 共 9 种常见格式,推荐分辨率不超过 2K。

除了格式和分辨率,最关键的硬性限制是请求 Body 的总大小不能超过 100M。这意味着如果你使用 base64 编码方式,原始文件大小加上 base64 编码带来的约 33% 体积膨胀,必须控制在 100M 以内。对于大多数视频文件来说,直接 base64 传入几乎都会超限。因此,处理视频或高清图片时,务必走文件上传接口获取 file-id,使用 ms:// 协议进行调用。

1M 长上下文的自动缓存怎么触发?为什么我的请求没有命中缓存?

Kimi K3 提供了 1M 的超长上下文窗口,这对于长文档分析和代码库理解场景非常友好。但长上下文意味着高昂的输入 token 成本。为了降低开发者的重复调用成本,平台内置了自动缓存机制。理解并利用这个机制,是控制成本的核心。

自动缓存的触发不需要开发者额外配置 cache ID 或 TTL 参数,它是全自动的。但命中缓存有一个绝对前提:前缀不变。也就是说,当前请求的 prompt 前缀必须与上一次请求完全一致。此外,前一个请求的 prompt tokens 必须大于 256,才会被系统缓存。

很多开发者发现两次请求内容差不多,但第二次没有命中缓存,往往是因为对“前缀不变”的理解不够严格。前缀不变意味着从第一个字符开始,到发生变化的字符之前,所有内容必须逐字一致。任何微小的改动都会破坏缓存。

常见的破坏缓存的操作包括:在多轮对话中修改了 system prompt;在历史消息中追加或修改了之前的用户输入;或者在会话中途切换了 reasoning_effort(思考力度)档位。

以下是一个具体的对话历史示例,说明如何保持前缀不变:

第一次请求:

{
  "messages": [
    {"role": "system", "content": "你是一个专业的代码助手。"},
    {"role": "user", "content": "分析这段代码:..."},
    {"role": "assistant", "content": "这段代码的功能是..."},
    {"role": "user", "content": "如何优化它?"}
  ]
}

第二次请求(命中缓存):

{
  "messages": [
    {"role": "system", "content": "你是一个专业的代码助手。"},
    {"role": "user", "content": "分析这段代码:..."},
    {"role": "assistant", "content": "这段代码的功能是..."},
    {"role": "user", "content": "如何优化它?"},
    {"role": "assistant", "content": "你可以通过...来优化。"},
    {"role": "user", "content": "这种优化有什么副作用?"}
  ]
}

在第二次请求中,前面的消息列表完全保持不变,只是在末尾追加了新的对话轮次,因此前缀缓存能够正常命中。

第三次请求(未命中缓存):

{
  "messages": [
    {"role": "system", "content": "你是一个高级的代码助手。"}, // 修改了 system prompt
    {"role": "user", "content": "分析这段代码:..."},
    {"role": "assistant", "content": "这段代码的功能是..."},
    {"role": "user", "content": "如何优化它?"}
  ]
}

在第三次请求中,由于 system prompt 中将“专业的”改为了“高级的”,导致前缀从第一个字符就发生了变化,整个缓存失效。因此,在需要多次调用的长上下文场景中,务必保持 system prompt 和历史消息的绝对稳定,只追加新的用户问题。

缓存命中后计费怎么算?1M 上下文和视觉输入的 token 配额是共享的吗?

理解了缓存机制,接下来需要明确计费规则。Kimi K3 的计费不按上下文长度分段定价,而是按实际消耗的 token 量计费。根据官方定价页信息,常规输入 token 的价格为 20.00 元每百万 tokens,而缓存命中的 token 价格仅为 2.00 元每百万 tokens。这意味着如果能够稳定命中缓存,输入成本可以降低到原来的十分之一。关于输出 token 的具体价格,需以官方定价页最新公示为准。

在预算控制方面,有一个关键点需要特别注意:视觉输入的 token 消耗与 1M 文本上下文配额是共享的。也就是说,Input 加上 Output 的总 token 数不能超过 1M,而图片和视频传入后产生的视觉 token 也会占用这个配额。

视觉 token 是动态计算的,与图片的分辨率、视频的关键帧数量正相关。一张高清图片可能会消耗数百甚至上千个 token,一段几分钟的视频消耗的 token 量更是惊人。如果在一次请求中同时传入大量高清图片和长篇代码,很容易迅速耗尽 1M 的配额,导致请求被截断或报错。因此,在规划应用时,必须对视觉输入的 token 消耗进行预估,合理控制单次请求中的多媒体数量和文本长度。

实战场景:长文档分析和代码库理解怎么配最省钱?

掌握了上述规则后,我们来看两个典型场景的配置策略。

场景一:长文档分析

假设你需要让模型分析一份 50 万字的产品手册,并且用户会针对这份手册提出多个问题。最省钱的配置方式是:将 system prompt 和完整的文档内容放在消息列表的最前面,作为固定前缀。用户的每一次提问作为新的 message 追加在列表末尾。

具体的请求流程如下:

  1. 第一次请求时,构造消息列表:[{"role": "system", "content": "你是产品手册分析助手。"}, {"role": "user", "content": "手册内容:...(50万字)\n问题:第一章讲了什么?"}]
  2. 模型返回回答后,第二次请求时,将第一次的完整消息列表保留,并在末尾追加新的对话:[{"role": "system", "content": "你是产品手册分析助手。"}, {"role": "user", "content": "手册内容:...(50万字)\n问题:第一章讲了什么?"}, {"role": "assistant", "content": "第一章讲了..."}, {"role": "user", "content": "第二章的核心功能是什么?"}]
  3. 由于前缀保持不变,从第二次提问开始,系统就会自动命中缓存,50 万字的文档输入成本将从常规的 10 元左右降至 1 元左右。

场景二:代码库理解与视觉反馈

在这个场景中,开发者通常需要传入大量的代码文件和前端 UI 截图。为了控制成本并命中缓存,建议将所有代码文件拼接成一个长文本,放在请求的最前面。UI 截图通过文件上传接口转为 ms:// 协议,放在代码文本之后。

具体的请求流程如下:

  1. 将多个代码文件读取并拼接为一个长字符串 code_content
  2. 将 UI 截图上传获取 ms:// 链接。
  3. 构造消息列表:[{"role": "system", "content": "你是前端开发专家。"}, {"role": "user", "content": [{"type": "text", "text": code_content}, {"type": "image_url", "image_url": {"url": "ms://..."}}]}]
  4. 在多轮交互中,保持代码和截图的引用不变,只修改末尾的指令文本。如果需要分析新的截图,建议开启新的会话,避免因为中间插入新图片导致历史前缀发生变化。

常见问题排查

传入公网图片 URL 为什么会报错?
Kimi K3 视觉输入不支持直接拉取公网 URL,必须使用 base64 编码或 ms:// 协议传入。这是平台的硬性限制,目的是保证数据传输的稳定性。

视频文件太大无法直接 base64 传怎么办?
必须先调用文件上传接口将视频上传至平台,获取返回的 file-id,然后在请求参数中使用 ms://<file-id> 格式传入。请求 Body 总大小不能超过 100M。

content 写成 JSON 字符串为什么会提示 token limit?
如果 content 被序列化成字符串,模型会将其视为纯文本输入,导致 token 数量暴增,瞬间超出模型限制。必须确保 content 是一个原生的对象数组结构。

为什么两次请求内容差不多,但第二次没有命中缓存?
自动缓存要求前缀绝对不变。检查是否修改了 system prompt,是否在历史消息中插入了新内容,或者是否切换了 reasoning_effort 参数。任何细微的前缀变化都会导致缓存失效。

视觉输入的 token 消耗是怎么计算的?
视觉 token 采用动态计算机制,与图片分辨率和视频关键帧数量正相关。视觉 token 会与文本 token 共享 1M 的总上下文配额。

切换思考力度会影响缓存吗?
会。reasoning_effort 是请求级别的参数,切换该参数会改变请求的签名,从而破坏前缀缓存命中。在需要缓存的连续对话中,请保持该参数不变。

Kimi K3 的 1M 上下文是输入输出总共 1M 吗?
是的,1M 上下文配额是 Input 与 Output 的总和,并且视觉输入产生的 token 也包含在这个配额内。

常见问题

传入公网图片 URL 为什么会报错?

Kimi K3 视觉输入不支持直接拉取公网 URL,必须使用 base64 编码或 ms:// 协议传入。

视频文件太大无法直接 base64 传怎么办?

必须先调用文件上传接口将视频上传至平台,获取返回的 file-id,然后在请求参数中使用 ms://<file-id> 格式传入。请求 Body 总大小不能超过 100M。

content 写成 JSON 字符串为什么会提示 token limit?

如果 content 被序列化成字符串,模型会将其视为纯文本输入,导致 token 数量暴增,瞬间超出模型限制。必须确保 content 是一个原生的对象数组结构。

为什么两次请求内容差不多,但第二次没有命中缓存?

自动缓存要求前缀绝对不变。检查是否修改了 system prompt,是否在历史消息中插入了新内容,或者是否切换了 reasoning_effort 参数。

继续探索

读完这篇,可以继续看