跳转至

mintbot 如何处理文件

当你向 mintbot agent 发送一张照片、一份文档、一段语音、一张表格、一张截图或一份 PDF —— 不管是通过 Telegram、Web 面板还是 API —— 这个文件在送往语言模型的路上 不会 经过 mintbot 的中央基础设施。它直接落到 你自己 agent 的 VPS 上,想留多久就留多久,LLM 拿到的是一份为它优化过的副本。

这是一个安静的设计决策,却带来响亮的后果。值得展开讲讲,因为这是 mintbot 与消费级 LLM 聊天分道扬镳的最大几个地方之一。

端到端流程

  1. 上传抵达 agent VPS。 来自 Telegram 的照片、拖入 Web 面板的 PDF、语音备忘、粘贴进对话的截图。agent 的本地 API 接收字节,嗅探文件的 magic header 来判断它实际是什么类型(手机和浏览器误标的频率出奇地高),用 SHA-256 哈希,然后写入 agent 自己 VPS 上的 /var/lib/mintbot-agent/uploads/<shard>/<sha256>.<ext>。本地目录里加上一行,记录来源(telegram / panel / api)、上传者 ID、MIME 类型和原始文件名。

  2. 原件是神圣的。 从这一刻起,mintbot 内部不会再有任何东西去改动已保存的文件。为 LLM 准备文件的适配器只会输出 工作副本 —— 调整大小后的 JPEG、转码出的文本、提取出的缩略图。逐字节的原件留在磁盘上,直到你从 agent 的文件管理器里亲手删除。没有中央存储桶,没有保留计时器,agent 之间也没有泄漏:每个 agent VPS 只知道自己主人的上传。

  3. 模型拿到为 LLM 优化的版本。 当 agent 决定把文件展示给 LLM 时,一个小调度器根据 MIME 类型和扩展名挑出正确的 适配器,适配器输出模型能读取的内容块:

    适配器 处理 输出
    Image JPG、PNG、WebP、GIF、HEIC(iPhone)、AVIF,以及任何 Pillow 能打开的格式 缩放到长边 1568 px,以 JPEG q85 重编码,在模型上下文中 base64 内联
    PDF .pdf ≤ 32 MB 作为原生 PDF 进行 base64 内联(Anthropic 系模型可直接读取)
    Text .md.csv.json.yaml,源代码(.py.js.ts.go.rs、…),日志,diff 以 UTF-8 解码(latin-1 兜底),文本内联到大小上限
    Audio .mp3.ogg.opus.m4a.wav.flac Telegram 语音条 bot 已经内联转写;直接上传目前是占位,Whisper STT 在下一波上线
    Video .mp4.mov.webm.mkv 目前是占位;ffmpeg 关键帧 + 音频转写在下一波上线
    Office docs .docx.xlsx.pptx.odt.ods.odp 目前是占位;原生文本抽取(python-docx / openpyxl / python-pptx)在下一波上线
    Unknown 其他一切 文本占位:"用户附了一个 <mime> 文件,磁盘上以上传 ID <id> 保留" —— 让模型至少能就 "发了什么" 这件事进行推理

    每一次转换都缓存在原件旁边 <sha256>.cache/v<N>.json,模型第二次需要这个文件时就是秒载入。提升适配器版本会自动让缓存失效。

  4. 模型上下文里不会出现会过期的 URL。 当图片或 PDF 进入 LLM 时,它在同一轮里就被 base64 内联 —— 没有以后可能变 404 的 URL,也没有带计时器的签名链接。对于更大的文件、模型只需要一个指针的情况,URL 是内部的 https://agent<id>.<domain>/<panel_token>/api/local/uploads/<upload_id>/raw —— 由你自己 agent 的面板 token 守护,只要文件还在盘上就一直有效。

为什么这比消费级 LLM 聊天体验更强

当你把一张照片上传到 ChatGPT,或者把一份 PDF 丢给 Claude.ai,文件进入的是 服务商的 存储,绑定在那个会话上,何时消失由服务商的保留策略说了算。过了一定时间文件就没了,哪怕你仍然能看到当时那场对话。换一家服务商,意味着一切从头来过。

一个常见的 Telegram bot 坑能把这种反差讲得很具体。Telegram 本身为每张照片保留一个永久的 file_id,但 第三方 bot 拿这个 file_id 去取文件时,得到的是一个 24 小时就失效的临时 URL。 引用昨天那张照片的旧 bot 会返回 404。mintbot 一次性把这件事解决了:第一次见到 Telegram 文件时,它通过永久有效的 file_id 重新拉一遍字节,复制到 你的 agent 归档里。从那一刻起,这张照片就是你的了。

这个设计带来三件事:

  • 文件属于你,不属于 LLM 服务商。 下个月你从 Claude 换到 GPT-5,文件历史会原封不动跟着你走 —— 因为它在你的 VPS 上,而不是在某家厂商的桶里。
  • 你以后还能再问。 "三个月前你帮我分析过一份合同 —— 能不能拿来跟这份新草稿比一比?" 是说得通的,因为原件还在磁盘上。消费级聊天里,那份旧文件通常已经没了。
  • 模型总是拿到它最擅长处理的版本。 视觉模型拿到缩放后的 JPEG,文本读取者拿到 UTF-8,PDF 读取者拿到原生 PDF。手机能直接传 HEIC 而且就是能用 —— Pillow 的 HEIF 插件启动时加载,magic byte 嗅探器会逮住那些把上传错标成 application/octet-stream 的手机。

在哪里管理你的文件

agent Web 面板顶栏带一个 文件管理器。它能浏览整台 agent VPS,而 /var/lib/mintbot-agent/uploads/ 那个上传归档就是你的对话不断填进去的地方。在那里你可以:

  • 重命名、删除、移动已上传的文件
  • 按日期、来源或文件名浏览
  • 拖拽上传新文件(分块,支持几 GB 的大文件)
  • 在线编辑小型文本文件

从面板删除文件会同时移除 blob 和目录里那一行。agent 再也无法把它展示给 LLM 了。这件事 才是让原件 "属于你" 的关键 —— 拥有删除权的只有你。

结语

大多数 LLM 聊天产品把你的上传当作短暂的对话上下文。mintbot 把它当作 你的数据 —— 存在你的 VPS 上,由你拥有,按需变形成模型那一轮最擅长处理的形状。mintbot 大部分有意思的能力,都是建在这块地基上的。