1. 前言

Lobechat 就不做过多介绍了,一个开源、现代设计的人工智能聊天框架。

今天就来聊聊同步的问题,Lobechat 分为社区版和正式版,正式版需要付费订阅套餐,支持全局云同步,但是最便宜的套餐都要 4.9 刀,这让我 API 用户感觉有点难以接受。因为我需要的功能社区版都已经满足了,并不打算单独对云同步付费。

官方之前有通过 WebRTC 同步数据的方案,但在某个版本被废弃了,其实我也能理解,WebRTC 同步方案太过麻烦,且具有不稳定性,必须保证同时两台设备在线,而且实现原理让我感觉有一丝不安全性。

对 WebRTC 概念感兴趣的话可以看下官方的一篇文章:
https://github.com/lobehub/lobe-chat/discussions/368


其实除了正式版之外,还有服务器自建数据库等同步方法,但都需要一定的成本和技术壁垒。

因此我在社区版的基础上构思了一个脚本,通过 Webdav 技术实现对话记录、设置等同步。此方案成本基本为零,坚果云免费额度都绰绰有余。

2. Webdav / Tampermonkey

但研究开始之前,有两个概念需要先了解一下。

  1. Webdav

大多数网盘都支持通过 Webdav 技术进行同步,网盘会提供一套账号密码以及服务器地址,在前端调用 API,能够实现增删改查等操作。

  1. 油猴管理器(Tampermonkey)

油猴管理器(Tampermonkey)无疑是浏览器插件的伟大创作之一,可以对网页注入 js 脚本来实现一些功能。

3. 那么如何获取 Lobechat 数据呢?

我研究过 Lobechat 源码,它数据都存放在本地的 IndexedDB 数据库中,这是浏览器的一个存储机制,可以存放大量的数据,显示则是以数据库的格式。

1731404378265

然后我先手动导出一份 json 格式的全局数据(社区版只支持手动导入导出文件),拿这份文件跟 IndexedDB 数据库 做对比,发现字段基本保持一致,数据格式也不用转,全部都在其中。

于是我翻阅了一下官方文档,有可以利用的 API,操作查询这些数据,下面是我的一些思路。

先声明我想要拿到的数据,这些都在上面的截图中存在。

const dbName = "LOBE_CHAT_DB";
const storeNames = ["messages", "sessionGroups", "sessions", "topics", "users"];
let request = indexedDB.open(dbName);

request.onsuccess = (event) => {
  const db = event.target.result;
  let state = {
    messages: [],
    sessionGroups: [],
    sessions: [],
    topics: [],
    users: [],
  };

  let pendingStores = 0;

  storeNames.forEach((storeName) => {
    if (db.objectStoreNames.contains(storeName)) {
      pendingStores++;
      const transaction = db.transaction([storeName], "readonly");
      const objectStore = transaction.objectStore(storeName);
      const allRecords = objectStore.getAll();

      allRecords.onsuccess = (event) => {
        const result = event.target.result;
        state[storeName] = result;
        pendingStores--;

        if (pendingStores === 0) {
          /*
          * 整个数据库的数据都可以导出
          * 在此回调执行操作
          */ 
        }
      };
    } 
  });
};

4. 操作流程原型

既然可以查询,就可以覆盖,同样也有 API 支持,所以我就构思了一下流程,利用 Webdav 的增删改查,把这些数据传到网盘中,然后在另一台设备拉取,最后优化一下整个流程,让它更加可视化。

大致原型如下:

1731404855162

点击同步到云端,会通过 Webdav API 在网盘创建一个指定的文件夹 lobechat-webdav-backup(我自己随意命名的),在本地程序中生成一个 json 文件,IndexedDB 数据会被放入该文件中,然后通过 Webdav API 传输到网盘中。

点击下载到本地,会先通过 Webdav API 获取lobechat-webdav-backup下的 json 文件内容,利用 IndexedDB API 覆盖在浏览器 IndexedDB 数据库中。


在实际体验中,可以随时保存本地数据到云端,下载数据到本地,同步就很方便,使用了三天,没有出现同步出错的问题,脚本很稳定。

最终我把该脚本发布到 Greasyfork,可供大家直接使用,代码也已开源。