资源管理 resource manager
智能体的"工作区":它读入的输入文件、产出的输出文件怎么存、怎么灌进向量库供检索、怎么生成摘要。读 resource_manager/。
什么是资源
FileManager(resource_manager/file_manager.py:11),工具(WriteFileTool 等)都把读写委托给它。资源管理就像公司的"共享网盘":每个员工每个项目有自己的文件夹(隔离)、重要文件本地留一份又传网盘一份(双写)、网盘有全文搜索(灌向量库)、每个文件夹置顶一份目录清单(摘要)。今天全天沿用这个"公司网盘"世界观。
智能体干活会涉及文件——你上传给它的输入文件(PDF、CSV),它产出的输出文件(写的报告、生成的代码)。这些统称资源(Resource),由资源管理器管理。目录 resource_manager/。
FileManager 双写
FileManager(resource_manager/file_manager.py:11)是工具(如 CodingTool、WriteFileTool)读写文件的入口。核心模式:"先写本地磁盘,再同步到 S3":
# write_file (file_manager.py:48)
final_path = ResourceHelper.get_agent_write_resource_path(file_name, agent=..., agent_execution=...)
with open(final_path, mode="w") as file:
file.write(content)
self.write_to_s3(file_name, final_path) # 再同步 S3
# write_to_s3 (:35):先在 DB 登记 Resource 记录;storage_type==S3 时才真上传
WriteFileTool 就是把活委托给这个 resource_manager.write_file。WriteFile(file_name="report.txt", content="季度总结…"):• 本地:写到
.../resources/agent_7/run_42/report.txt(隔离路径,见 L03)• 云:若
storage_type==S3,同一份内容上传到 S3• DB:插入一条
Resource(path=..., channel="OUTPUT", agent_id=7, ...)下次要读,就用
read_file(file_manager.py:94)按同样的隔离路径取回。report.txt。FileManager 先把我安置在 agent_7/run_42/ 这个专属文件夹(别的智能体进不来);接着发现平台配了 S3,又把我复制了一份传上云(这样别的容器也能看到我);然后在公司档案里给我登记了户口——一条 Resource 记录,写明我住哪、我是"产出(OUTPUT)"。如果主人后来想让智能体"查阅"我,我还会被切块、做成索引卡灌进向量库(L05),并在目录清单里留个名(L06)。从出生到可被检索,我一路都有人管。」👶 小白:既然最后要传到 S3 云上,为什么还先在本地磁盘写一份?直接传云不就省事了?
👨🏫 老师:两份各有用。本地那份"就近、快、不强依赖网络",写完立刻能读;S3 那份负责"跨容器共享"——回忆 Day 04,backend 和 celery 是不同容器,本地磁盘互不相通,只有云上这份大家都看得到。而且 write_to_s3 会先在 DB 登记一条 Resource 记录,再看 storage_type 决定要不要真上传——本地开发没配 S3 时,只写本地照样能跑。
路径按 agent 隔离
get_agent_write_resource_path 算出 agent + execution 专属的写入路径。
output.csv:• A →
resources/agent_7/run_42/output.csv• B →
resources/agent_9/run_88/output.csv同名,但路径带了各自的 agent_id/execution_id 前缀,彼此不覆盖。去掉隔离,B 的文件就会把 A 的冲掉。
report.txt 被 B 智能体的同名文件覆盖。路径按 agent_id + execution_id 隔离(每个运行有自己的目录),保证互不干扰。多租户/并发场景,"按身份隔离资源路径"是必须的。这和 OpenHands 的 workspace 按会话隔离、AutoGPT 用 execution_id 隔离一个道理。生活类比(网盘世界观):公司网盘从来不是所有人共用一个根目录,而是"部门/项目/个人"层层建文件夹——市场部的《方案.pptx》永远盖不掉设计部的同名文件。
agent_id/execution_id 就是这套文件夹层级。Resource 登记表
Resource 模型(models/resource.py:6)登记每个文件:
class Resource(DBBaseModel):
storage_type = Column(String) # FILESERVER / S3
path = Column(String)
channel = Column(String) # INPUT(用户给的)/ OUTPUT(智能体产的)
agent_id / agent_execution_id
summary = Column(String)
channel 区分 INPUT/OUTPUT 很实用——摘要时只汇总输入资源(L06)。文件灌向量库(RAG 入库)
ResourceManager.save_document_to_vector_store(resource_manager/resource_manager.py:72)用 LlamaIndex 解析文件、灌进向量库:
for docs in documents:
docs.metadata["agent_id"] = str(self.agent_id) # 打标签
docs.metadata["resource_id"] = resource_id
vector_store = LlamaVectorStoreFactory(...).get_vector_store() # 默认 Redis
index = VectorStoreIndex.from_documents(documents, storage_context=...)
agent_id 标签,检索时只召回"本智能体的文件"(隔离)。这就是"给智能体挂知识库"——它能"查阅"你给的资料,而非死记硬背。用 LlamaIndex(文档解析 + RAG 框架)做解析和切块。资源摘要
ResourceSummarizer.generate_agent_summary(resource_manager/resource_summary.py:50)把该智能体所有 INPUT 资源的名字拼起来,写进 AgentConfiguration 的 resource_summary 键。LlamaDocumentSummary 用 LLM 生成单个文档的内容摘要。
resource_summary 就来自这里。这也是为什么上传文件后会触发后台 summarize_resource 任务(Day 17)。生活类比(网盘世界观):摘要就是网盘文件夹里置顶的那份《目录清单.md》——新人进项目组不用把几十个文件挨个打开,扫一眼清单就知道"有什么资料、要用时去翻哪份"。
一句话复述:摘要管"知道有什么",RAG 检索管"需要时取出来"——清单在手,用时才翻。
存储可插拔
write_to_s3 里 if resource.storage_type == StorageType.S3.value: S3Helper().upload_file(...)——存储后端(FILE/S3)由配置的 StorageType 枚举决定。
report.txt 写进了 A 的磁盘;用户在 GUI 点下载,请求打到 backend(容器 B)——B 的磁盘上根本没有这个文件,404,"明明生成了却下载不到"。容器一销毁文件还会彻底丢。S3 是所有容器都能访问的"公共网盘",写到 S3 才算大家都能看到。这就是存储必须可切换成 S3 的根本原因。StorageType 枚举 + if 分支切换——改配置就换存储后端,业务代码不变。和 AutoGPT 的 local/S3、Day 10 的 LLM 工厂一个思路——面向接口、可插拔。LlamaVectorStoreFactory(llama_vector_store_factory.py)同理,给文件 RAG 选 Pinecone/Redis/Chroma/Qdrant。今日小结 + 动手
🧠 今天你应该能回答
- 什么是资源?资源管理要解决哪四件事?
- FileManager 的"双写"是什么?
- 为什么文件路径要按 agent/execution 隔离?
- 为什么要把文件灌进向量库?摘要有什么用?
- 存储为什么可插拔(FILE/S3)?
✋ 动手
P=superagi/resource_manager
sed -n '35,64p' file_manager.py # 双写
sed -n '72,109p' resource_manager.py # 灌向量库
grep -n 'def generate_agent_summary' resource_summary.py
sed -n '6,33p' ../models/resource.py # Resource 表