Appearance
Kimi API 通过 Files API 支持文件问答:先上传文件获取 file_id,再提取文件内容作为 system prompt,最后对内容提问。本文提供 Python 和 Node.js 完整示例,以及多文件和清理管理的实践方案。
Kimi API 文件问答
工作原理
Kimi 的文件问答不是"把文件 ID 传给模型",而是:
- 上传文件 → 获取
file_id - 提取文件文本内容 → 获取可读的文字
- 将文字内容放入 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 进行文件问答
核心流程
文件问答分三步:
- 上传文件:通过 Files API 上传到 Kimi 服务器
- 提取内容:获取已格式化的文件文本内容(PDF/图片走 OCR)
- 放入对话:将提取内容作为 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 的场景。