在上一篇文章《从架构看极简:Lite Agent 如何用零外部依赖打造全功能 AI 助手引擎》中,我分享了如何坚持“0 外部依赖”的极客哲学,纯用 Python 标准库撸出一套具备多通道、长短期记忆和定时任务的智能助手。这套架构运行在廉价的云端 VPS 上,极其稳定。

但随着时间推移,我逐渐发现了一个痛点:它是个“盲人”。

每当我遇到需要解析的数学公式、拍下的纸质文档或是网页截图时,我只能手动把它们转成文字再发给它,十分割裂。于是,我萌生了一个念头——给这套极简系统装上“视觉神经”

拒绝臃肿,寻找极致轻量的视觉方案

提到多模态 OCR,很多人第一时间想到的是接入商业 API,或是部署极其笨重的全家桶方案。但我的原则依然是:大道至简,拒绝臃肿。

经过一番调研,百度飞桨团队开源的 PaddleOCR-VL-1.5 进入了我的视线。
这是一个仅仅只有 0.9B 参数的超轻量级视觉-语言大模型(VLM),与目前百亿参数的模型相比,它小巧得不可思议,但在文档解析、复杂数学公式还原(OmniDocBench 测试)上却表现出了惊人的 94.5% 准确率。

更为关键的是,它可以被编译成 GGUF 格式!这意味着,我那台一直闲置在家里的 Mac Mini(M4 芯片) 终于有了用武之地。通过 llama.cpp,我可以直接利用 Apple Silicon 原生的 Metal 框架进行物理级 GPU 加速,没有任何厚重的 Python 依赖地狱。

极简部署:踩坑与极限优化的实战

原以为部署会一帆风顺,结果却结结实实踩了个坑。

一开始,我试图直接拉取原生 PyTorch 版本的底层环境来跑,结果直接遭遇了 Error loading model: 'default' 报错。更致命的是,在 Mac 的 M 系列芯片上,这套原生底层兼容性极差,纯 CPU 原生跑一页文档将近要 100 秒!

幸好后来查阅到了一篇“救星”文章,直接点破了迷局,并提供了一套专为 Apple Silicon 量身定制的最优解:“前端 paddleocr 客户端 + 底层 llama-server (GGUF格式模型)”

于是我立刻转舵,采用了这套拥抱极速 GGUF 生态的架构方案:

  1. 底层推理引擎启动:放弃 PyTorch,直接掏出 llama.cpp 编译出的 llama-server,挂载视觉投影模块(mmproj)与量化好的 GGUF 模型,开启纯 C++ 的极致性能,并丢入后台永驻:

    
    # 1. 创建模型存放目录
    mkdir -p ~/models/PaddleOCR-VL-1.5-GGUF 
    cd ~/models/PaddleOCR-VL-1.5-GGUF
    
    # 2. 通过 hf-mirror 镜像源直链下载主模型 (约 900MB)
    curl -L -O -C - https://hf-mirror.com/PaddlePaddle/PaddleOCR-VL-1.5-GGUF/resolve/main/PaddleOCR-VL-1.5.gguf
    
    # 3. 下载视觉编码器 mmproj (约 840MB)
    curl -L -O -C - https://hf-mirror.com/PaddlePaddle/PaddleOCR-VL-1.5-GGUF/resolve/main/PaddleOCR-VL-1.5-mmproj.gguf
    
    #4. llama-server  启动
    nohup llama-server -m ~/models/PaddleOCR-VL-1.5-GGUF/PaddleOCR-VL-1.5.gguf \
    --mmproj ~/models/PaddleOCR-VL-1.5-GGUF/PaddleOCR-VL-1.5-mmproj.gguf \
    --port 8080 --host 0.0.0.0 --temp 0 > ~/llama-server.log 2>&1 &
    
    
  2. 前端客户端联动与 API 封装:安装好极其轻量的 paddleocr 客户端后,不再让它自己做重度推理,而是通过 --vl_rec_backend llama-cpp-server 参数,把最核心的识别任务外包给刚刚启动的 8080 端口。 由于最终需要给云端的 Agent 留接口,我又手撸了一个不到 100 行代码的 ocr_web.py(借助 FastAPI),在内部调用官方的 paddleocr doc_parser,向外暴露极简的 /api/ocr 接口。

  3. 极简 API 封装:由于底层只是纯粹的推理引擎,我又用不到 100 行代码手撸了一个 ocr_web.py。它利用 FastAPI 构建了一个超轻量的 Web 壳,并在内部调用官方的 paddleocr doc_parser,最终向外暴露了一个极其干爽的 /api/ocr 接口。随后同样使用 nohup 挂在 8000 端口。

这套组合拳下来,原本 100 秒一页的龟速,被生生压缩到了不到 20 秒一页!一个全本地、不吃带宽的“视觉超算节点”就此在桌面上完美运转。

零入侵打通云端与本地:Tailscale 隧道

现在的局面是:

  • 我的 Lite Agent 运行在公网 VPS(云端)
  • 强大的视觉算力节点 Mac Mini 运行在内网(本地)

如何将两者安全打通?我同样拒绝了复杂的 Nginx 反向代理或花生壳,而是选用了 Tailscale 虚拟局域网。

只要在家里启动服务,云端的 VPS 就能直接通过 100.x.x.x 的 Tailscale 私有 IP 连通家里的 API。没有任何公网暴露的风险,也没有复杂的鉴权,纯粹的点对点通信。

无感拦截:飞书与 Telegram 的“见图就解”

基础建好后,接下来就是改造 Lite Agent 的通道层。
我不想要什么花里胡哨的“图片上传指令”,最优雅的交互应当是隐形的。

channels/feishu.pychannels/telegram.py 中,我仅仅增加了几十行代码:监听消息池。如果发现是 imagephoto 类型的消息,直接在后台新开一个轻量级 threading.Thread

  1. 自动拦截: 无论是通过飞书还是 Telegram 发来的图片,机器人会立即回复一句:“🤔 收到图片,正在调用视觉大模型进行全版面结构化解析…”
  2. 下载透传: 服务端将原图抽离,通过 Socks5/官方 API 拉到内存,随后组装成极简的 HTTP POST 请求,通过 Tailscale 隧道射向我的卧室。
  3. 秒级直出: 家里的 Mac Mini 风扇微转,十几秒后,一篇包含完美 LaTeX 数学公式和排版还原的 Markdown 文本,直接呈现在我的手机屏幕上。
    image
    期间还遇到了一些小插曲。比如在 VPS 上添加 .env 环境变量 OCR_ENDPOINT 时,因为 echo 命令误把 \n 吃进去,导致系统读取了错乱的环境变量名,最后回退到了默认的本地 127.0.0.1 报错。不过这些都是折腾路上的小确幸。

结语

折腾到最后,看着手机屏幕里一张模糊的二次方程作业照,在几秒内变成了极其工整优雅的 LaTeX 代码输出时,那种成就感是难以言喻的。

在算力如此廉价、大模型百花齐放的今天,我们或许不需要用多高大上的企业级架构。只要找准工具的边界,用最简单直接的代码将它们串联起来,你也能拥有一个只属于你的,能够“看透”世间万物的全能智能体。