Skip to main content
With the Kimi API, file-based Q&A takes only two steps: upload a file through the Files API to extract its text, then put the extracted text into messages. When you query the same document repeatedly, keeping the document prefix stable lets the built-in Context Caching feature cut your costs. This cookbook walks through:
  • Upload and read: get model-readable text with the file-extract flow;
  • Ask: put the file content into messages as a system message;
  • Multi-turn chat: keep the fixed prefix in place and append turns to the end of messages;
  • Multi-file Q&A: put each file in its own system message at the head of messages;
  • Constrain the output: add a fixed response rule to control format and length;
  • Cut costs: reuse a stable document prefix so Context Caching kicks in automatically;
  • Clean up uploaded files: keep the extracted text locally and delete uploaded files on a schedule.

1. Setup

The Kimi API is compatible with the OpenAI SDK, so you only need the openai package:
When creating the client, point base_url at the Kimi API endpoint and read the API key from an environment variable:
The examples use the kimi-k3 model. To use another model such as kimi-k2.6 or kimi-k2.5, just replace the model field, but note that parameter support differs between models. See the model parameter reference. The sample file is the PDF of the Kimi K3 technical report from the official MoonshotAI GitHub repository. Download it with the code below (or use any PDF of your own; the Files API supports .pdf, .txt, .csv, .doc, and .docx, with a 100MB limit per file):

2. Upload the file

To get started, we’ll upload the PDF through the Files API with purpose set to file-extract, which marks the file for text extraction. The Files API also accepts purpose values such as image and video, used for the model’s native understanding of those files:

3. Read the extracted content

After uploading, fetch the extracted text through the file content endpoint. It already follows the format that the official documentation recommends for model consumption:
If you will query the same document repeatedly, save the extracted text locally and read it back next time, instead of uploading and extracting again:
Two common mistakes:
  1. Do not put the file_id into messages. The file_id is only a handle; the model cannot see any content through it. You must read the extracted content first and put the text into messages.
  2. Do not inline a base64-encoded PDF into messages. Base64-encoded files lead to very high token consumption. If the file type is supported by the /v1/files API, upload the file and extract its content instead.

4. Ask a question

Put the extracted file content into messages as a system message, then ask your question in a user message:
Note: all outputs in this cookbook come from real runs. Model output is not deterministic, so your results may differ slightly.

5. Multi-turn chat

To follow up, append the question and answer to the end of messages. The file content and instructions stay at the front, unchanged. This “fixed content first, conversation appended at the end” structure is not just a convention; it determines whether the cache described later can be hit:

6. Multi-file Q&A

Multi-file Q&A is the same pattern scaled out: put each file in its own system message and place these messages at the head of the messages list:

7. Constrain the response

The system message in section 4 is an identity setting: it tells the model who it is. In practice you often add a response rule that tells the model what the answer should look like. Format, length, and style can all be pinned down with a fixed instruction. The rule is part of the stable prefix, just like the identity setting and the file content, and does not affect cache hits in the next section:
We run the same question twice, with and without the rule: without it the model answers freely with a long, sectioned piece; with it the output fits the defined shape, with bullet points, a quote per point, and a much tighter length:

8. Cut costs: Context Caching

Billing for file Q&A has a structural property: the document content appears in every request as a fixed prefix, so the more questions you ask about the same document, the more times that prefix is billed. Context Caching removes this repeated cost. The Kimi API enables it automatically for all requests: when the system detects a repeated leading context (system prompt, file content, tool definitions, and so on), it reuses the cached prefix and bills it as a cache hit instead of charging the full price again. No extra code is needed. You do not create a cache, reference a cache ID, or manage a TTL. Just call /v1/chat/completions as usual. There is only one thing to do: keep the fixed parts (file content, system prompt, tool definitions) stable and at the front of the messages array. Two details from the official documentation:
  • A later request can only hit the prefix cache when the preceding request has more than 256 prompt tokens; smaller requests are not cached. File Q&A meets this condition naturally.
  • For reference, the official figures are up to 90% cost reduction in specific scenarios, and average time to first token under 5 seconds for long texts. Check the pricing page for the exact billing rules.
We can send the exact same request as in section 7 again and look at the cache hit in usage:
60,160 of the 60,260 prompt tokens in that request came from cache. Cached tokens are billed at a discount, so this is where the cost figures from the official documentation show up on a real bill. Compared with RAG, the official advice is: for frequent queries over fixed content (such as FAQ or document Q&A), prefer Context Caching; when the content is extremely long and the query direction is not fixed, consider RAG. The two compare as follows:

9. Clean up uploaded files

The Files API limits each user to 1,000 files and 10GB in total, so delete uploaded files once you are done with them. For a periodic full cleanup, list all files with files.list and delete them one by one with files.delete:

10. FAQ

Extraction can fail for several reasons: unsupported format, corrupted file, or exceeding the 100MB limit. Formats the API does not support cannot be parsed by the model, so do not put them into the context. Wrapping upload and extraction in defensive handling is a good idea:
Example output
With kimi-k3’s 1M-token context, most single documents fit in one piece. If a document is really too long, split it along its own structure (chapters, headings) and put each part in a separate system message.If your scenario is “a huge document collection with unpredictable queries”, for example asking anything across an entire knowledge base, that is beyond what single-document Q&A covers. See the Context Caching versus RAG guidance in section 8.

Reference docs: File-based Q&A with the Kimi API, File upload API reference, Context Caching with the Kimi API.