Skip to content

Kimi API 通过 Files API 支持文件问答:先上传文件获取 file_id,再提取文件内容作为 system prompt,最后对内容提问。本文提供 Python 和 Node.js 完整示例,以及多文件和清理管理的实践方案。

Kimi API 文件问答

工作原理

Kimi 的文件问答不是"把文件 ID 传给模型",而是:

  1. 上传文件 → 获取 file_id
  2. 提取文件文本内容 → 获取可读的文字
  3. 将文字内容放入 messages 的 system prompt → 模型基于内容回答

这和 Kimi 智能助手的文件上传功能底层是同一机制。


单文件问答

python
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key="MOONSHOT_API_KEY",
    base_url="https://api.moonshot.cn/v1",
)

# 1. 上传文件(purpose="file-extract")
file_obj = client.files.create(
    file=Path("report.pdf"),
    purpose="file-extract"
)

# 2. 提取文件内容
file_content = client.files.content(file_id=file_obj.id).text

# 3. 将内容作为 system prompt 进行问答
messages = [
    {"role": "system", "content": "你是一个文档分析助手。"},
    {"role": "system", "content": file_content},  # 文件内容
    {"role": "user", "content": "请总结这份报告的主要结论。"},
]

completion = client.chat.completions.create(
    model="kimi-k2.6",
    messages=messages
)

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

重要:文件内容通过 files.content() 获取的是已提取的文字,不是文件 ID,这是最常见的误用。


多文件问答

python
from typing import List
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key="MOONSHOT_API_KEY",
    base_url="https://api.moonshot.cn/v1",
)

def upload_and_extract(files: List[str]) -> List[dict]:
    """上传多个文件并提取内容,每个文件独立一个 system message"""
    file_messages = []
    for file_path in files:
        file_obj = client.files.create(
            file=Path(file_path),
            purpose="file-extract"
        )
        content = client.files.content(file_id=file_obj.id).text
        file_messages.append({"role": "system", "content": content})
    return file_messages

file_messages = upload_and_extract(["report_q1.pdf", "report_q2.pdf"])

messages = [
    *file_messages,  # 多个文件内容
    {"role": "system", "content": "你是一个财务分析助手。"},
    {"role": "user", "content": "对比 Q1 和 Q2 报告,收入变化趋势如何?"},
]

completion = client.chat.completions.create(model="kimi-k2.6", messages=messages)
print(completion.choices[0].message.content)

Node.js 示例

typescript
import OpenAI from "openai";
import fs from "fs";

const client = new OpenAI({
  apiKey: process.env.MOONSHOT_API_KEY,
  baseURL: "https://api.moonshot.cn/v1",
});

async function fileQA(filePath: string, question: string): Promise<string> {
  const fileObj = await client.files.create({
    file: fs.createReadStream(filePath),
    purpose: "file-extract",
  });

  const fileContent = await (await client.files.content(fileObj.id)).text();

  const completion = await client.chat.completions.create({
    model: "kimi-k2.6",
    messages: [
      { role: "system", content: "你是一个文档分析助手。" },
      { role: "system", content: fileContent },
      { role: "user", content: question },
    ],
  });

  return completion.choices[0].message.content ?? "";
}

const answer = await fileQA("document.pdf", "这份文档的主要内容是什么?");
console.log(answer);

文件管理与清理

每个用户最多上传 1000 个文件,定期清理避免触及上限:

python
# 列出并删除所有文件
file_list = client.files.list()
for file in file_list.data:
    client.files.delete(file_id=file.id)
    print(f"已删除: {file.filename}")

最佳实践

  • 对于需要反复问答的文件,缓存 file_content 到本地,避免重复上传
  • 问答完成后及时删除临时文件,节省配额
  • 对于超大文件(> 100MB),优先考虑文件上传而非 base64

支持的文件格式

类型格式
文档PDF、Word (.docx)、PowerPoint (.pptx)
表格Excel (.xlsx)、CSV
代码Python、JavaScript、TypeScript 等文本文件
纯文本.txt、.md、.html

常见问题

Q: 文件内容太长,超出了模型上下文怎么办?

A: kimi-k2.6 支持 256K token 上下文,已能覆盖大多数文档。如果仍然超出,可以将文档分块处理,或只提取相关章节。

Q: 上传的文件会被 Kimi 用于训练吗?

A: 参考 Kimi 官方隐私政策。如果是敏感文档,建议在问答完成后及时调用删除 API。

Q: 可以直接传 file_id 给模型吗?

A: 不可以,必须先用 files.content() 提取文字内容,再放入 messages。直接传 file_id 模型不会理解。

Kimi API 通过 Files API 实现文件问答:先上传文件,再提取文件内容(已格式化)作为 system prompt 放入 messages,然后提问。注意要用提取后的文本内容,而不是 file_id。本文包含单文件和多文件的完整示例。

使用 Kimi API 进行文件问答

核心流程

文件问答分三步:

  1. 上传文件:通过 Files API 上传到 Kimi 服务器
  2. 提取内容:获取已格式化的文件文本内容(PDF/图片走 OCR)
  3. 放入对话:将提取内容作为 system prompt,然后提问

重要:放入 messages 的是文件内容文本,不是 file_id。Kimi API 目前不支持在 chat completions 中用 file_id 直接引用文件。

单文件问答

typescript
import OpenAI from "openai";
import fs from "fs";

const client = new OpenAI({
  apiKey: process.env.MOONSHOT_API_KEY,
  baseURL: "https://api.moonshot.cn/v1",
});

// 1. 上传文件
const fileObject = await client.files.create({
  file: fs.createReadStream("document.pdf"),
  purpose: "file-extract",
});

// 2. 提取内容(已对齐为模型易于理解的格式)
const fileContent = await (await client.files.content(fileObject.id)).text();

// 3. 放入 messages 并提问
const completion = await client.chat.completions.create({
  model: "kimi-k2.6",
  messages: [
    {
      role: "system",
      content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手。",
    },
    {
      role: "system",
      content: fileContent, // 文件内容放在 system prompt 中
    },
    {
      role: "user",
      content: "请简单介绍这份文档的主要内容。",
    },
  ],
});

console.log(completion.choices[0].message.content);
python
from pathlib import Path
from openai import OpenAI

client = OpenAI(
    api_key="MOONSHOT_API_KEY",
    base_url="https://api.moonshot.cn/v1",
)

# 上传文件(支持 pdf、doc、图片等格式)
file_object = client.files.create(
    file=Path("document.pdf"),
    purpose="file-extract"
)

# 获取提取后的文本内容
file_content = client.files.content(file_id=file_object.id).text

messages = [
    {"role": "system", "content": "你是 Kimi,由 Moonshot AI 提供的人工智能助手。"},
    {"role": "system", "content": file_content},
    {"role": "user", "content": "请简单介绍这份文档的主要内容。"},
]

completion = client.chat.completions.create(model="kimi-k2.6", messages=messages)
print(completion.choices[0].message.content)

多文件问答

多个文件时,每个文件单独放一个 role: "system" 消息:

typescript
async function uploadAndExtract(filePaths: string[]) {
  const fileMessages: OpenAI.Chat.ChatCompletionSystemMessageParam[] = [];

  for (const filePath of filePaths) {
    const fileObject = await client.files.create({
      file: fs.createReadStream(filePath),
      purpose: "file-extract",
    });
    const content = await (await client.files.content(fileObject.id)).text();
    fileMessages.push({ role: "system", content });
  }

  return fileMessages;
}

const fileMessages = await uploadAndExtract(["report.pdf", "data.xlsx", "notes.txt"]);

const completion = await client.chat.completions.create({
  model: "kimi-k2.6",
  messages: [
    ...fileMessages, // 文件内容放最前面
    { role: "system", content: "你是 Kimi,由 Moonshot AI 提供的人工智能助手。" },
    { role: "user", content: "对比这几份文档,总结它们的主要差异。" },
  ],
});

最佳实践

提取结果本地缓存

文件提取后可以将内容存到本地,下次提问时直接用,无需重新上传和提取:

typescript
import fs from "fs";
import path from "path";

async function getFileContent(filePath: string): Promise<string> {
  const cachePath = `${filePath}.extracted.txt`;
  
  // 本地有缓存就直接用
  if (fs.existsSync(cachePath)) {
    return fs.readFileSync(cachePath, "utf-8");
  }
  
  const fileObject = await client.files.create({
    file: fs.createReadStream(filePath),
    purpose: "file-extract",
  });
  const content = await (await client.files.content(fileObject.id)).text();
  
  // 缓存到本地
  fs.writeFileSync(cachePath, content, "utf-8");
  return content;
}

定期清理上传的文件

每个账号最多上传 1000 个文件,建议提取完成后删除,释放配额:

typescript
const fileList = await client.files.list();
for (const file of fileList.data) {
  await client.files.delete(file.id);
}
python
file_list = client.files.list()
for file in file_list.data:
    client.files.delete(file_id=file.id)

支持的文件格式

类型格式
文档PDF、Word、TXT、Markdown
表格Excel、CSV
图片PNG、JPEG、WebP(走 OCR 提取文字)

常见问题

Q: 可以在 messages 里用 file_id 直接引用上传的文件吗?

A: 不行。Kimi API 目前不支持用 file_id 在 chat completions 中引用文件。必须先调 files.content 拿到文本内容,再放进 messages。

Q: 文件提取费用怎么算?

A: 文件提取 API(Files API)目前免费,不计入 token 费用。按内容问答时,文件文本作为 system prompt 才开始计费。

Q: 图片 OCR 效果不好怎么办?

A: 可以用 pdf-parse 等工具自行提取文本后作为字符串传入,效果可能更可控。另外,Kimi 的视觉模型支持直接将图片作为 user 消息中的 image_url 传入,适合需要"看图理解"而非 OCR 的场景。