发布时间:2026/8/30 18:35:49
Agent 文件传递 1. 问题目前 Agent 已经可以在工作目录中创建和处理文件但这些文件都保存在后端服务器上前端无法直接访问。因此需要增加一个中间环节把 Agent 生成的文件交给用户。这里采用对象存储的方式Agent生成文件 ↓ 工作目录 ↓ 打包 ↓ MinIO ↓ 生成下载链接 ↓ 前端下载这样 Agent 仍然只负责处理自己的工作目录文件交付由后续流程完成。2. 对象存储**对象存储Object Storage**主要用于保存图片、视频、压缩包等非结构化文件。和普通文件系统相比对象存储更适合通过程序进行文件上传和访问。可以简单理解成一个可以通过 API 操作的网盘。本项目使用MinIO。MinIO 是一个开源对象存储服务可以直接部署在自己的服务器上并提供 Python SDK。这里使用 MinIO 主要是因为项目本身可以本地部署没有必要为了文件存储再依赖第三方云存储。3. MinIO 部署项目使用 Docker 部署 MinIO。docker pull minio/minio mkdir -p /usr/local/minio-data docker run -p 9000:9000 -p 9190:9090 \ --name minio \ -d --restartalways \ -e MINIO_ROOT_USERminio \ -e MINIO_ROOT_PASSWORDminio123 \ -v /usr/local/minio-data:/data \ minio/minio server /data --console-address :9090启动后可以通过http://服务器IP:9190进入 MinIO 管理页面。如果是在本机部署则使用http://localhost:9190登录后即可看到 MinIO 的管理界面。4. Python SDK安装 MinIO 的 Python SDKpip install minio最基本的操作就是连接 MinIO、创建 Bucket、上传文件以及生成下载链接。from minio import Minio client Minio( localhost:9000, access_keyminio, secret_keyminio123, secureFalse )项目实际只需要用到其中两个操作上传文件 生成下载链接下载链接使用presigned_get_object()生成。它返回的是一个带有效期的 URL用户拿到链接后可以直接下载文件不需要知道 MinIO 的账号密码。5. 文件传递方案5.1 为什么需要打包一个 Agent 任务不一定只生成一个文件。例如工作目录/ ├── result.docx ├── data.xlsx ├── image.png └── output.pdf如果逐个上传并生成链接前端还需要处理多个文件。因此这里直接将整个工作目录打包成一个 ZIP工作目录 ↓ output.zip ↓ MinIO ↓ 一个下载链接用户只需要下载一个文件即可。5.2 为什么放到 Agent 结束之后处理文件上传不属于具体工具的功能。例如create_file工具只负责创建文件如果让它同时负责上传就会让工具本身承担文件交付的工作。因此将这部分放到FileMiddleware中在 Agent 执行完成后统一处理。6. 开始实现6.1 添加 ZIP 压缩方法在utils/doc_utils下增加zip_files.py。使用 Python 自带的shutil直接压缩目录import os import shutil def compress_dir(folder_path): 将目录压缩成 zip output_path shutil.make_archive( base_namefolder_path, formatzip, root_diros.path.dirname(folder_path), base_diros.path.basename(folder_path) ) return output_path这里没有额外引入压缩库项目目前的需求比较简单标准库就够用了。6.2 添加 MinIO 配置MinIO 的地址和认证信息放到.env中HOST_IPlocalhost MINIO_PORT9000 MINIO_ACCESS_KEYminio MINIO_SECRET_KEYminio123然后在配置文件中统一读取HOST_IP os.getenv(HOST_IP) MINIO_PORT os.getenv(MINIO_PORT) MINIO_ENDPOINT f{HOST_IP}:{MINIO_PORT} MINIO_ACCESS_KEY os.getenv(MINIO_ACCESS_KEY) MINIO_SECRET_KEY os.getenv(MINIO_SECRET_KEY)这样代码中不需要直接写 MinIO 的连接信息部署到其他环境时只需要修改环境变量。6.3 封装 MinIO 连接在conn下新建minio_conn.py。不直接在 Middleware 中操作 MinIO SDK而是简单封装一层from minio import Minio from base import configs as cfg class MinioConn: def __init__(self): self.client self.create_client() self.bucket_name stores self._init_bucket() def create_client(self): return Minio( cfg.MINIO_ENDPOINT, access_keycfg.MINIO_ACCESS_KEY, secret_keycfg.MINIO_SECRET_KEY, secureFalse ) def _init_bucket(self): if not self.client.bucket_exists(self.bucket_name): self.client.make_bucket(self.bucket_name) def upload_obj(self, object_name, file_path): self.client.fput_object( self.bucket_name, object_name, file_path ) def gen_presigned_url(self, object_name): return self.client.presigned_get_object( self.bucket_name, object_name )这里暂时只保留项目需要的两个方法upload_obj() gen_presigned_url()Bucket 在初始化时检查不存在就自动创建。7. 接入 FileMiddlewareMinIO 部分准备好之后最后需要把它接到 Agent 的执行流程中。首先在FileMiddleware初始化时创建 MinIO 连接class FileMiddleware(AgentMiddleware[CustomState]): def __init__(self): super().__init__() self.mc MinioConn()然后利用before_agent和aafter_agent两个生命周期节点完成文件处理。7.1 记录开始时间在before_agent中记录当前任务的开始时间。原因是工作目录可能本身就存在一些文件不能每次 Agent 执行结束都把整个目录当成新文件。因此需要知道Agent 开始执行之后有没有产生新的文件。7.2 Agent 执行结束后处理文件主要逻辑放在aafter_agentasync def aafter_agent(self, state, runtime): dir_path rt.get_root_thread_dir() # 判断任务期间是否产生新文件 if not await self._check_if_new_file( dir_path, state[start_work_time] ): return None # 压缩目录 local_path await asyncio.to_thread( compress_dir, dir_path ) # 上传 MinIO object_name os.path.basename(local_path) await asyncio.to_thread( self.mc.upload_obj, object_name, local_path ) # 生成下载链接 url self.mc.gen_presigned_url(object_name) return { messages: [ AIMessage(content可通过如下地址下载), AIMessage(contenturl) ] }这里压缩和上传都属于比较明显的文件 I/O 操作因此使用asyncio.to_thread()执行避免直接阻塞当前异步流程。如果任务期间没有产生文件则直接返回不进行压缩和上传。8. 测试可以直接在 Agent Chat UI 中测试例如做个 a.txt随便写点什么Agent 完成后可以看到返回结果中多了一条下载链接。整个过程实际上就是创建 a.txt ↓ Agent 执行结束 ↓ 检测到新文件 ↓ 工作目录压缩成 ZIP ↓ 上传 MinIO ↓ 生成 Presigned URL ↓ 返回给前端点击链接即可下载 Agent 生成的文件。9. 修改后的目录本次主要涉及以下几个文件.env # MinIO 配置 base/ └── configs.py # 读取 MinIO 配置 conn/ └── minio_conn.py # MinIO 连接、上传、生成下载链接 content/ └── middles/ └── file_manager_middle.py # Agent 执行结束后的文件处理 utils/ └── doc_utils/ └── zip_files.py # 工作目录压缩10. 小结这一部分实际上没有改变 Agent 原来的文件处理方式只是在原来的工作目录后面增加了一个文件交付流程Agent工作目录 ↓ 检测新文件 ↓ ZIP ↓ MinIO ↓ Presigned URL ↓ 用户Agent 继续在自己的工作目录中操作文件Middleware 负责在任务结束后把文件整理并交给用户。这样文件生成和文件传递就分开了。

相关新闻

2026/8/30 18:35:49

Cursor 入门指南:从安装到高效使用的 AI 代码编辑器

在实际写代码的过程中,工具选型往往比想象中更影响效率。Cursor 就是这样一款把 AI 能力直接嵌入编辑器流程的编程助手,它既能像普通代码编辑器一样打开项目、搜索文件、运行命令,又能在对话、补全、修改代码时调用大语言模型帮助你完成编码任…

2026/8/30 18:30:49

Qt+OpenCV+Basler工业相机跨平台视觉控制系统开发实战

简介:机器视觉系统通常由图像采集、处理与显示组成,而工业相机的稳定出图与实时算法处理是核心环节。以Basler相机为代表,借助pylon SDK完成底层取流,再通过OpenCV实现边缘检测、ROI定位等算法,最后以Qt构建跨平台GUI&…

2026/8/30 18:30:49

opencode 从客户端到命令行的完整迁移指南:安装、配置与实战

很多开发者第一次接触 opencode,是被桌面客户端吸引的。图形界面把对话区、文件树、结果预览都摆在了明面上,看起来比黑底白字的终端友好得多。可一旦把真实项目交给它,比如一次横跨多个文件的重构、一批测试用例的生成、或者一段需要反复执行…

2026/8/30 18:50:50

WPF动态曲线开发实战:基于LiveCharts的实时数据可视化方案

简介:本资源是一份基于WPF与LiveCharts实现动态折线图的完整可运行项目,面向.NET桌面开发初学者及WPF图表可视化实践者,重点解决传统静态图表在实时数据流中X轴无法自动平移、导致新旧数据挤压失真的痛点。项目通过精细配置LiveCharts的Axis和…

2026/8/30 18:50:50

从Roblox怀旧游戏到Postman接口调试:实战与最佳实践

之前和朋友在 Roblox 上找小游戏消遣,无意间逛到一个叫 “A Nostalgic Hangout Game” 的怀旧聚会游戏。名字本身就很有意思,“Nostalgic” 是怀旧,“Hangout” 是闲逛、聚会。进入地图后我的第一反应是:这不就是很多年前 Roblox …

2026/8/30 18:50:50

仿Claude Code:Spring AI 2.0 Java Agent开发实战

最近在业务系统中做大模型能力落地时,我明显感觉到一个转变:单纯调用大模型返回一段文本已经不能满足需求,团队更希望模型能像人一样“动手干活”,比如读取文件、修改配置、执行命令、查数据库,最后把结果反馈给用户。…

2026/8/30 18:50:50

Spring AI实战:构建仿ClaudeCode的Java终端Agent

在实际的 Java 大模型应用开发中,真正的分水岭不是能不能调用某个模型的 API,而是能不能让模型在一个任务上下文里反复思考、调用工具、拿到结果后继续推进。ClaudeCode 这类终端编码代理之所以让开发者印象深刻,是因为它把读代码、改文件、执…

2026/8/30 18:50:50

FastAPI从零入门:类型注解、参数校验与自动文档实战

做过 Web 接口开发的同学,多少都经历过这样的场景:用 Flask 写接口,路由简单上手快,但参数校验基本靠手写,请求体格式一复杂代码就开始膨胀;用 Django 写接口,功能齐全但框架较重,一…

2026/8/30 18:45:50

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

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

2026/8/30 0:03:35

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/30 0:03:35

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/30 0:03:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/30 0:03:35

vSound小提琴数字处理器实操指南:从接线到演出的完整配置

电小提琴或者原声小提琴插电演出,第一个绕不开的坎就是声音难听。原声琴的共鸣和空气感一旦进了拾音器,出来的往往是一坨干瘪、发尖、带着奇怪塑料味的信号。我当初第一次把琴接上乐队调音台,直接被主唱吐槽"你这声音像在锯钢丝"。…

2026/8/30 0:03:35

传感器接口IC如何攻克生物化学传感的微弱信号难题?

1. 从电极到比特流:为什么生物化学传感必须依赖专用接口IC 做生物化学传感的人都有过类似的经历:明明传感器本身性能很好,信号输出却一塌糊涂——噪声大、漂移明显、重复性差,怎么调都达不到预期。很多时候问题并不在传感器&#…

2026/8/30 0:03:35

STM32F411CEU6多通道ADC采集:扫描模式+DMA实现详解

1. 多通道 ADC 的用武之地把“Multichannel ADC”和“STM32F411CEU6”这两个关键字放在一起,其实就是嵌入式开发里最常遇到的一类需求:用一块不算贵的 MCU,同时采集多路模拟信号。STM32F411CEU6 是 48 引脚的 Cortex-M4F 主控,主频…

2026/8/28 16:16:48

实测才敢推 AI论文网站 2026最新测评与推荐

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。一、综…

2026/8/28 16:16:50

2026必备!AI论文网站测评:最新推荐与深度对比

2026年真正好用的AI论文网站,核心看生成的论文质量、低AI味、格式正确、学术适配四大指标。综合实测,千笔AI、ThouPen、豆包、DeepSeek、Grammarly 是当前最值得推荐的梯队,覆盖从免费到付费、从中文到英文、从文科到理工的全场景需求。 一、…

2026/8/28 11:06:45

摆脱论文困扰!盘点2026年全网爆红的的AI论文写作工具

一天写完毕业论文在2026年已不再是天方夜谭。2026年最炸裂、实测能大幅提速的AI论文写作工具,覆盖选题构思、文献整理、内容生成、格式排版等核心场景,真正帮你高效搞定论文难题。 一、全流程王者:一站式搞定论文全链路(一天定稿首…