版本说明:
与createModel不同,只要你的智能体是基于@vectorx/agent-runtime当前版本(> 0.6.2)开发或升级的,就天然支持该文件上传服务,无需额外接入或手动实现该方法。
const { AgentRuntime, AgentDriver } = require("@vectorx/agent-runtime");
/**
* @typedef {import('@vectorx/agent-runtime').IAgent} IAgent
*
* @class
* @implements {IAgent}
*/
class MyAgent extends AgentRuntime {
async sendMessage(message) {
try {
// 创建 qwen-doc-turbo 模型
const model = this.createModel("qwen-doc-turbo");
// 组装消息数组
const messages = [];
// 1. 处理文件:根据 fileSource 区分处理
if (Array.isArray(message?.files) && message.files.length > 0) {
message.files.forEach((file) => {
if (file.fileSource === "openai") {
// OpenAI 上传的文件:使用 file-id,通过 system role 传入
const fileId = file.id;
if (fileId) {
messages.push({
role: "system",
content: `fileid://${fileId}`,
});
console.log(`==== 添加 OpenAI 文件 file-id: ${fileId} ====`);
}
}
}
// 2. 添加 user 消息
const userContent = [];
// 2.1 添加标准上传的文件(doc_url)
if (Array.isArray(message?.files) && message.files.length > 0) {
message.files.forEach((file) => {
if ((file.fileSource === "standard" || !file.fileSource) && file.url) {
userContent.push({
type: "doc_url",
doc_url: [file.url],
});
}
});
}
// 2.2 添加用户文本提示
const userPrompt = message?.msg || "请分析这个文档";
if (userPrompt.trim()) {
userContent.push({
type: "text",
text: userPrompt.trim(),
});
}
messages.push({
role: "user",
content: userContent,
});
console.log("==== 构建的消息 ====", JSON.stringify(messages, null, 2));
// 3. 调用模型
const modelResponse = await model.streamText({
messages,
parameters: {
temperature: 0.3,
max_tokens: 2000,
},
enable_thinking: true,
});
// 4. 流式返回结果
for await (const chunk of modelResponse) {
this.sseSender.send({ data: chunk });
}
this.sseSender.end();
} catch (error) {
console.error("qwen-doc-turbo stream error:", error);
this.sseSender.end();
}
}
}
exports.main = function (event, context) {
return AgentDriver.run(event, context, new MyAgent(context));
};
interface UploadFileInput {
/** 文件内容(模拟器 / 中间件会保证该字段) */
file: File | Buffer | string;
/** 文件名 */
filename: string;
/** 文件用途,默认 "file-extract" */
purpose?: string;
}
在当前
type RuntimeUploadInput = {
file: {
/** 文件二进制内容 */
buffer: Buffer;
/** 原始文件名及其变体 */
name?: string;
newFilename?: string;
originalFilename?: string;
/** MIME 类型 */
type?: string;
mimetype?: string;
/** 可选临时路径 */
filepath?: string;
size?: number;
} | Buffer;
/** 文件用途 */
purpose?: string; // 默认 "file-extract"
};
在默认实现中,框架会自动完成以下处理:
如果你不走
export const uploadFileInputSchema = z.object({
/** 文件名 */
filename: z.string().min(1, "文件名不能为空"),
/** 文件用途,固定为 "file-extract" */
purpose: z.string().optional().default("file-extract"),
/** 文件内容(base64 编码字符串) */
fileContent: z.string().min(1, "文件内容不能为空"),
/** 文件 MIME 类型 */
mimeType: z.string().optional(),
});
此时你可以在进入
interface BaseResponse<T = any> {
/** 状态码 */
code: number;
/** 消息 */
msg: string;
/** 数据 */
data?: T;
}
/** 真正的文件数据(OpenAI 风格) */
interface UploadFileData {
/** 文件 ID */
id: string;
/** 对象类型 */
object: string;
/** 文件大小(字节) */
bytes: number;
/** 创建时间戳(Unix) */
created_at: number;
/** 文件名 */
filename: string;
/** 文件用途 */
purpose: string;
/** 文件状态 */
status: string;
/** 状态详情 */
status_details?: any;
}
/** 文件上传响应 */
type UploadFileResponse = BaseResponse<UploadFileData>;
// 浏览器侧示例(multipart/form-data)
async function uploadOpenAiFile(file: File, purpose = "file-extract") {
const formData = new FormData();
formData.append("file", file);
formData.append("purpose", purpose);
const resp = await fetch("/api/agent/upload-openai-file", {
method: "POST",
body: formData,
});
const res = await resp.json();
if (res.code !== 0) throw new Error(res.msg || "文件上传失败");
return res.data as UploadFileData;
}
上传成功后得到的
class MyAgent extends AgentRuntime {
async sendMessage(input: any) {
// 假设你在上游已经通过 HTTP 上传过文件,并拿到了 UploadFileData
const uploadedFile: UploadFileData = input.uploadedFile;
const requestData = {
msg: input.msg,
files: [
{
id: uploadedFile.id,
filename: uploadedFile.filename,
purpose: uploadedFile.purpose || "file-extract",
bytes: uploadedFile.bytes,
created_at: uploadedFile.created_at,
},
],
history: [],
};
// 后续直接走模型调用逻辑(略)
}
}
如果你在某些自定义场景下需要主动上传本地文件(不经过 HTTP 中间件),也可以直接调用基类的
class LocalFileAgent extends AgentRuntime {
async uploadLocalFileExample() {
const fs = await import("fs");
const buffer = fs.readFileSync("/path/to/file.pdf");
const res = await this.uploadFile({
file: buffer,
purpose: "file-extract",
filename: "file.pdf",
});
if (res.code !== 0 || !res.data) throw new Error(res.msg || "上传失败");
return res.data; // UploadFileData
}
}
界面效果可参考:
请使用
@vectorx/xhs-cloud-cli@0.4.2及以上版本,就可以在本地使用「智能体模拟器」完整调试POST /upload-openai-file这个 OpenAI 标准文件上传接口。