news 2026/9/10 18:20:07

Agent 接收用户上传文件

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Agent 接收用户上传文件

1. 问题与目标

前面的工作已经实现了用户端文件上传,但目前文件主要用于用户侧操作。下一步需要让 Agent 本身能够接收这些文件。

对于通用 Agent 来说,文件不应该只限制在图片。例如用户上传一个 Word 文档,希望 Agent 阅读并分析其中的内容;或者上传 Excel、PDF、Markdown 等文件,再让 Agent 根据文件执行任务。

LangGraph CLI 创建的工程默认已经支持文件上传,但前端组件支持的类型主要是:

pjp, jfif, pjpeg, jpeg, jpg, png, gif, webp, pdf

这些类型本质上都是图片格式,PDF 在默认情况下也会作为图片处理。

如果项目只要求 Agent 接收图片,那么后端只需要将模型替换成支持视觉输入的 VLM 即可,其他部分基本不需要调整。

但本项目后续还需要处理 Word、Excel、PDF、Markdown 等文件,因此这里先解决一个更基础的问题:

让 Agent 能够接收任意类型的用户文件,并将文件保存到当前 Agent 工作目录。

文件内容的具体解析、转换和处理属于后续工作。


2. 实现方案

整体流程比较简单:

用户上传文件 ↓ Agent Chat UI ↓ 文件转换为 Base64 ↓ AgentState.upload_files ↓ before_agent Middleware ↓ Base64 解码 ↓ user_uploads/ ↓ Agent 读取文件

具体分为两部分:

  1. 修改 Agent Chat UI,使上传组件支持任意文件,并将文件信息放入upload_files

  2. 在后端before_agent中读取upload_files,将 Base64 文件恢复成实际文件。


3. 前端文件数据

前端接收到用户上传的文件后,不直接将二进制文件放进 JSON,而是使用 Base64 字符串表示文件内容。

例如,一个上传文件的数据结构如下:

{ "type": "file", "mimeType": "image/jpeg", "data": "DQoNCiMjIEFJIEFnZW50...", "metadata": { "filename": "a.md", "size": 8238, "lastModified": 1757389979338 } }

其中:

  • type:固定为file

  • mimeType:文件 MIME 类型

  • data:文件内容对应的 Base64 字符串

  • metadata.filename:原始文件名

  • metadata.size:文件大小

  • metadata.lastModified:文件最后修改时间

多个文件则组成一个列表,并通过 Agent State 传递:

from langchain.agents.middleware import AgentState class CustomState(AgentState): upload_files: list

3.1 为什么使用 Base64

Base64 的作用只是将二进制数据转换成字符串,方便放进 JSON 等文本格式中进行传输。

例如:

原始文件 ↓ 二进制数据 ↓ Base64 编码 字符串 ↓ JSON ↓ 后端 ↓ Base64 解码 原始文件

需要注意,Base64不是加密,同时会使数据体积增加约三分之一,因此这里只把它作为前后端之间的传输方式,而不是文件存储方式。


4. 后端实现

4.1 Base64 文件处理

content/utils下新增base64_util.py,负责将 Base64 数据恢复成文件。

import base64 import os def save_base64_file_from_content_block(content_block, save_dir): """ 从前端文件内容块中提取 Base64 数据并保存为文件 """ return save_base64_file( base64_data=content_block["data"], filename=content_block["metadata"]["filename"], save_dir=save_dir ) def save_base64_file( base64_data: str, filename: str, save_dir: str ): """ 将 Base64 数据保存为文件 """ file_path = os.path.join(save_dir, filename) file_data = base64.b64decode(base64_data) with open(file_path, "wb") as f: f.write(file_data) return { "success": True, "file_path": str(file_path), "filename": filename, }

这里将具体的 Base64 解码逻辑独立出来,Middleware 只负责处理 Agent 生命周期和状态,不直接处理文件编码细节。


4.2 配置上传目录

base/configs.py中增加:

USER_UPLOAD_PATH = "user_uploads"

后续如果需要调整目录,只修改配置即可,不需要再修改 Middleware。


4.3 在 Middleware 中处理上传文件

文件上传发生在 Agent 开始执行之前,因此放在FileMiddlewareabefore_agent中处理。

首先增加相关状态和依赖:

from base.configs import USER_UPLOAD_PATH from content.utils import base64_util as bu class CustomState(AgentState): upload_files: list start_work_time: float file_update_time: float

然后修改abefore_agent

async def abefore_agent(self, state, runtime): file_update_time = time.time() # 当前线程对应的工作目录 dir_path = os.path.join( rt.get_root_thread_dir(), USER_UPLOAD_PATH ) # 创建用户上传目录 await asyncio.to_thread( os.makedirs, dir_path, exist_ok=True ) files = state.get("upload_files") if files: content = "用户上传了如下文件,文件路径如下:" for file in files: # Base64 解码并保存文件 result = await asyncio.to_thread( bu.save_base64_file_from_content_block, file, dir_path ) # 返回给 Agent 相对路径 content += f"\n{rt.get_out_path(result['file_path'])}" return { "messages": [ ToolMessage( content=content, tool_call_id=get_uuid(), name="file_upload" ) ], "upload_files": None, "start_work_time": time.time(), "file_update_time": file_update_time } return { "start_work_time": file_update_time, "file_update_time": file_update_time }

这里有两个需要注意的地方。

第一,文件操作没有直接阻塞异步流程。

os.makedirs和文件写入属于同步 I/O,因此使用:

await asyncio.to_thread(...)

放到线程中执行,避免直接阻塞 Agent 的异步执行流程。

第二,处理完成后清空upload_files

文件已经落盘后,就没有必要继续将完整的 Base64 数据保存在 Agent State 中:

"upload_files": None

这样可以避免后续 Agent 状态继续携带较大的文件数据。

此时 Agent 实际拿到的是类似下面的信息:

用户上传了如下文件,文件路径如下: ./user_uploads/a.md ./user_uploads/test.pdf ./user_uploads/data.xlsx

后续 Agent 可以根据路径继续调用文件处理工具。


5. 测试

前端选择多个不同类型的文件进行上传,例如:

test.pdf test.docx data.xlsx demo.md image.png

上传后检查当前线程对应的工作目录:

<thread_work_dir>/ └── user_uploads/ ├── test.pdf ├── test.docx ├── data.xlsx ├── demo.md └── image.png

确认文件能够正常生成,并且文件内容与原文件一致,即可说明前后端文件传输链路已经打通。


6. 最终目录结构

本次只列出新增和修改的部分:

├─ base │ └─ configs.py │ # 添加 USER_UPLOAD_PATH │ ├─ content │ ├─ middles │ │ └─ file_manager_middle.py │ │ # 处理 Agent 接收用户文件 │ │ │ └─ utils │ ├─ runtime_util.py │ └─ base64_util.py │ # 新增,负责 Base64 文件解码

7. 小结

这一阶段没有处理文件内容,只解决了Agent 接收文件这个基础问题。

目前链路为:

前端上传任意文件 ↓ Base64 ↓ AgentState.upload_files ↓ FileMiddleware.abefore_agent ↓ Base64 解码 ↓ 当前线程 / user_uploads/ ↓ Agent 获取文件路径

至此,Agent 已经可以接收任意类型的用户文件。

下一步只需要在这个基础上继续增加文件解析能力,例如:

Word / PDF / Markdown ↓ 文本提取 ↓ Markdown / 纯文本 ↓ Agent 分析

而图片、Excel 等文件则可以根据实际类型交给对应的工具或 SubAgent 处理。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/9 8:50:09

Windows 10 + VS2019 下编译64位libcurl库(支持HTTPS)完整指南

简介&#xff1a;本资源是为Windows 10平台开发者准备的、开箱即用的CURL 64位静态/动态链接库集合&#xff0c;基于最新稳定版7.84.0源码&#xff0c;使用CMake 3.22与Visual Studio 2019完整编译生成&#xff0c;专为C/C网络编程初学者及嵌入式HTTP客户端开发人员设计&#x…

作者头像 李华
网站建设 2026/9/9 8:40:46

计算机单片机毕设实战-基于 STM32 的红外人体检测智能调速风扇装置设计 基于 STM32 的温湿度采集语音控制风扇系统设计与开发(018505)

博主介绍&#xff1a;✌️码农一枚 &#xff0c;专注于大学生项目实战开发、讲解和毕业&#x1f6a2;文撰写修改等。全栈领域优质创作者&#xff0c;博客之星、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于嵌入式单片机&#xff0c;Java、小程序技术领域和毕业项目实战 ✌️…

作者头像 李华
网站建设 2026/9/9 9:48:13

Windows下OpenCV CUDA预编译包:开箱即用的GPU加速视觉开发方案

简介&#xff1a;本资源是为Windows平台深度学习与计算机视觉开发者定制的OpenCV 4.9.0预编译二进制包&#xff0c;专为CUDA加速场景优化&#xff0c;面向需调用GPU加速DNN推理、视频分析、立体视觉及图像处理算法的中高级开发者。包内完整集成CUDA 11.1与cuDNN 8.0.4支持&…

作者头像 李华
网站建设 2026/9/9 8:41:36

Anaconda与conda虚拟环境管理完全指南:从安装到PyCharm配置与排错

很多刚接触 Python 的人&#xff0c;第一次被 Anaconda 卡住&#xff0c;往往不是因为代码写不出来&#xff0c;而是卡在环境上。一个项目要 Python 3.8&#xff0c;另一个项目要 Python 3.11&#xff1b;这个库要求 numpy 1.x&#xff0c;那个库却因为 numpy 2.x 报错。于是到…

作者头像 李华
网站建设 2026/9/4 16:33:50

Herdr多Agent协作实战:分屏配置与并行开发指南

如果你所在的项目里已经有两个以上的 AI 编程助手在同时工作&#xff0c;你大概遇到过这样的场景&#xff1a;一个 Agent 负责重构后端接口&#xff0c;另一个 Agent 想在前端调用同一套接口&#xff0c;结果它们互相覆盖了文件&#xff0c;或者干脆在同一个终端里排队&#xf…

作者头像 李华
网站建设 2026/9/3 0:44:29

Cursor Pro 2.5折订阅攻略:Team组队分摊成本全流程

先说明白&#xff1a;这篇文章不是劝你买高价订阅&#xff0c;也不是教你怎么绕过官方限制。而是把当前可行的正版折扣思路、操作步骤、验证方式和常见坑都整理出来&#xff0c;让想用 Cursor Pro 又不想原价付费的人有一个低成本入口。2.5 折是合规路径下的成本结果&#xff0…

作者头像 李华