Metadata-Version: 2.4
Name: memeseeks
Version: 0.5.0
Summary: 迷因捕手 — a free, open-source app for collecting memes and finding them by what they say.
License: MIT
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: pillow>=10.1
Requires-Dist: pillow-heif>=0.16
Requires-Dist: numpy>=1.26
Requires-Dist: pyyaml>=6
Requires-Dist: opencc-python-reimplemented>=0.1.7
Provides-Extra: ml
Requires-Dist: onnxruntime>=1.23; extra == "ml"
Requires-Dist: tokenizers>=0.15; extra == "ml"
Requires-Dist: huggingface_hub>=0.23; extra == "ml"
Requires-Dist: rapidocr_onnxruntime==1.4.4; extra == "ml"
Provides-Extra: torch
Requires-Dist: transformers<5,>=4.51; extra == "torch"
Requires-Dist: accelerate>=0.33; extra == "torch"
Requires-Dist: sentence-transformers>=3.0; extra == "torch"
Provides-Extra: serve
Requires-Dist: fastapi>=0.110; extra == "serve"
Requires-Dist: uvicorn>=0.29; extra == "serve"
Requires-Dist: segno>=1.5; extra == "serve"
Provides-Extra: app
Requires-Dist: pywebview>=6.2; sys_platform == "win32" and extra == "app"
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: httpx2; extra == "dev"
Requires-Dist: fastapi>=0.110; extra == "dev"
Requires-Dist: uvicorn>=0.29; extra == "dev"
Requires-Dist: segno>=1.5; extra == "dev"
Requires-Dist: onnxruntime>=1.23; extra == "dev"
Requires-Dist: tokenizers>=0.15; extra == "dev"
Dynamic: license-file

# 迷因捕手 · memeseeks

[English](https://github.com/tactino/memeseeks/blob/main/README.en.md)

迷因捕手是一款免费开源的梗图收藏与搜索工具，按图中文字的意思找回你存过的梗图，数据全部保存在本地。

- 按语义搜索图中文字，无需一字不差；支持中英文，简繁体通用
- 浏览网页时一键采集，适配百度贴吧、小红书、豆瓣
- 图集、收藏夹与来源记录；图集可导出成文件分享给别人
- 全屏浏览、今日一梗、相似推荐
- 手机扫码访问（同一局域网）
- 数据本地存储，无需账号；联网搜索可选，默认关闭
- Windows、macOS、Linux 一行命令安装，另有 Docker 镜像

当前版本：v0.5

![首页：今日一梗和我的图集](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/home.png)

<sub>截图里的梗图来自网络（多是小红书上的转载，图上的水印原样保留），版权归原作者所有，这里只用来演示软件。如果其中有你的作品、希望撤下，请[开一个 issue](https://github.com/tactino/memeseeks/issues)，我们会尽快替换。</sub>

## 安装

**Windows**：下载 [memeseeks-windows-setup.exe](https://github.com/tactino/memeseeks/releases/latest/download/memeseeks-windows-setup.exe)（约 90 MB），双击安装。

- 可以选装在哪个盘，也可以分别指定图库和模型放在哪；不需要管理员权限。已经下载过模型的话，选那个文件夹就不用再下。
- 双击后可能要等十几秒才出现安装界面：Windows 第一次运行它之前要先检查整个文件，不用重复点。
- 安装包还没有数字签名，Windows 可能提示「Windows 已保护你的电脑」：点「更多信息」，再点「仍要运行」。
- 装好后迷因捕手在自己的窗口里打开，不用浏览器。关掉窗口它还在屏幕右下角运行，点那只猫就回来；右键可以退出，或者改在浏览器里打开。第一次启动会下载约 1 GB 的模型，窗口里能看到进度。
- 卸载：在 Windows「设置 → 应用」里找到「迷因捕手」。你的图库不会被删除。

**用一行命令安装**（Windows 也可以这样装）。Windows 上打开 PowerShell，运行：

```powershell
irm https://raw.githubusercontent.com/tactino/memeseeks/main/scripts/install.ps1 | iex
```

**macOS / Linux：**

```bash
curl -LsSf https://raw.githubusercontent.com/tactino/memeseeks/main/scripts/install.sh | sh
```

安装脚本会把程序和它自带的 Python 放进一个文件夹（Windows 是 `%LOCALAPPDATA%\memeseeks`，macOS 是 `~/Library/Application Support/memeseeks`，Linux 是 `~/.local/share/memeseeks`），建好「迷因捕手」快捷方式，然后启动。

- 第一次启动会下载约 1 GB 的模型，网页上能看到进度；下完就能搜索，其他功能马上就能用。
- 在国内会自动换用镜像（PyPI、Python 和模型都走国内镜像）。
- 不改系统 PATH。想卸载，删掉那个文件夹和快捷方式即可；你的图库默认在 `~/.memeseeks`，不会被删。
- 想更新，再运行一次同一行命令。

**不想装在 C 盘**（或者想装到别处）时，在 Windows 上这样运行：

```powershell
& ([scriptblock]::Create((irm https://raw.githubusercontent.com/tactino/memeseeks/main/scripts/install.ps1))) -Dir D:\memeseeks -Library D:\memeseeks-library
```

- `-Dir`：程序、它的 Python 和模型放在哪。
- `-Library`：你的图库（索引、图集、采集来的图）放在哪。
- `-Models D:\某处\hf-cache`：复用你已经下载过的 Hugging Face 模型缓存，不再重新下载。

macOS / Linux 上对应的是在 `sh` 前面加 `MEMESEEKS_DIR=…`、`MEMESEEKS_LIBRARY=…`、`MEMESEEKS_MODELS=…`。

## 怎么用

打开后先把梗图放进来。可以在任意图集页点「上传」，也可以直接把图片拖进页面；还可以在「设置 → 来源文件夹」里添加电脑上已有的梗图文件夹。放进来的新图会在后台建立索引，页头会显示进度。在笔记本 CPU 上每张大约 3.5 秒，1000 张大约一小时，以后只处理新增的图。

![搜「可爱的小动物」，捕到 4 张，图上都没写「小动物」](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/search.webp)

- **搜索**：输入你记得的话，比如「上班的时候想下班」。把握大的结果排在前面，其余的折叠在「可能相关」里。
- **图集**：有「全部」「我喜欢」和你自己建的图集。在梗图页点「加入图集」；在任意图集页点「上传」，或者把图片拖进页面。
- **分享图集**：在图集页点「分享」，会下载一个 `图集名.memeseeks.zip` 文件，用微信、QQ 或网盘发给别人；对方把文件拖进迷因捕手（或在「图集」页点「导入图集」），就多出一个同样的图集。文件里有原图和采集来源，不含你电脑上的文件路径。
- **刷梗**：全屏一张接一张地看。可以按图集的顺序看，或者随机；在某张梗图上点大图，会接着刷和它相似的梗；从页头进入时，先刷最久没看过的。手机上划动，电脑上用滚轮或方向键。
- **首页**有今日一梗、你的图集和旧梗重温。点开一张梗图可以复制、保存、分享，也能看它的出处。
- **设置**：纸色 / 夜间主题、蒙德里安边框、开场动画、减少动效、网上搜索、来源文件夹、连接浏览器。设置存在图库里，用手机打开也一样。想改得更深，可以在图库文件夹里放一个 `custom.css`。

在运行它的电脑上，还可以从浏览器菜单把它装成一个应用。

![梗图页：图中文字、认出的梗名、出处和所在图集](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/meme.png)

![设置页：夜间主题](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/settings.png)

### 在手机上用

![手机上的梗图页、刷梗和图集](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/phone.png)

![在手机上刷梗，一张接一张](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/feed.webp)

在电脑上打开「设置 → 手机访问」，点「开」，再用手机相机扫出现的二维码。手机和电脑要连在同一个 Wi-Fi 上。

- 二维码里带着一个口令，同一个 Wi-Fi 下只有知道口令的设备能打开你的图库。「换一个口令」会让之前扫过的手机失效。
- 第一次打开时，Windows 可能会问要不要允许它访问网络，选「允许」。
- 手机上能搜索、刷梗和「保存」图片。「复制」「分享」和装成应用需要 HTTPS，这是浏览器的规定，暂时还不行。
- 高级用法：也可以用 `memeseeks serve --host 0.0.0.0 --token <一串足够长的口令>` 启动，自己管理口令。

### 从社区采集梗图

![在网页上点猫头，勾选这一页的图，点「采集」，图就飞进猫嘴里](https://raw.githubusercontent.com/tactino/memeseeks/main/docs/screenshots/collect.webp)

浏览器脚本会在你看的网页上放一只猫。点它，它会列出这一页的图；你勾选的图会连同网站名、帖子链接和标题一起进你的图库，大约一分钟后就能搜到。

脚本对三个站点做了专门适配：百度贴吧（每层楼的原图）、小红书（一篇笔记的全部图片）、豆瓣小组（帖子和回复里的大图）。其他网站用通用模式。

1. 给浏览器装扩展 [Violentmonkey](https://violentmonkey.github.io/)（Firefox 或 Chrome 都行）。
2. 在迷因捕手运行时打开网页，进入「设置 → 连接浏览器 → 安装采集 meme 脚本」。脚本是为你的服务器生成的，带着只有你的图库知道的密钥；没有这把密钥，收件箱不收图。
3. 在任意网页上点那只猫（可以把它拖到你喜欢的位置），勾选图片，在「放进」里选图集，然后点「采集」。
4. 只要一张的时候更快：直接把网页上的图片拖到猫头上，它就吞下去了，放进你上次在「放进」里选的图集。有的网站禁止拖动图片，那就用第 3 步。

字很少（少于 15 个字）的采集图多半是表情包，会先放进页头的「待确认」。点「要」就放进图库；点「不要」会移到 `<图库>/rejected`，不删除，也能一键撤销。你的选择只存在你自己的电脑上，以后用来训练一个只属于你的判别器。你自己文件夹里的图不受这条规则影响。

脚本只在你点它时动作，只采你正在看的这一页，每秒最多下载两张图。它不自动翻页，不在后台抓取，除了图片、网站名、帖子链接、帖子标题和你选的图集，什么也不发送。你可以在 Violentmonkey 的菜单里让它在某个网站上隐藏，或者把猫放回右下角。

### 网上搜索（可选）

你自己的图和网上的图分开显示。网上搜索默认关闭。要打开，先去申请一个免费的 [KLIPY](https://partner.klipy.com) API key，然后运行：

```bash
MEMESEEKS_KLIPY_KEY=<你的 key> memeseeks serve --online klipy     # 或者设置环境变量 MEMESEEKS_ONLINE=klipy
```

打开之后：

- 是**浏览器**把你的搜索词发给 KLIPY，同时发送一个每个图库随机生成的 id 和你的 IP 地址；图片也直接从 KLIPY 加载。迷因捕手的服务器不转发、也不保存这些内容。
- KLIPY 的结果按原样显示，可能包含广告。它的条款不允许过滤或重排结果，内容偏好请在 KLIPY 的合作方后台里调整。
- 能打开你网页的人都能看到这个 key。
- KLIPY 的英文和日文内容很多，中文很少。

## 你的数据在哪、怎么备份

图库文件夹（默认 `~/.memeseeks`，可以用 `-Library`、`--lib` 或 `MEMESEEKS_HOME` 指定）里全是普通文件：

| 内容 | 位置 |
|---|---|
| 图集、我喜欢 | `collections.json` |
| 设置、编号、看过的记录 | `settings.json`、`numbers.json`、`seen.json` |
| 采集和上传的图，以及它们的出处 | `inbox/`、`provenance.jsonl` |
| 待确认的选择；「不要」的图 | `review.jsonl`、`rejected/` |
| 索引（可以重建） | `index/` |

- **你自己文件夹里的图，迷因捕手只读不改。** 「移出图库」对它们也只是隐藏，原图不会动。
- **备份就是复制整个图库文件夹。** 索引丢了能重建，图集和我喜欢丢了就没了，所以这才是需要备份的东西。
- **换电脑**：把图库文件夹复制过去，安装时用 `-Library` 指向它。如果你自己的梗图文件夹换了位置，在「设置 → 来源文件夹」里重新添加一次；图集是按图片内容认图的，不会丢。

## 它是怎么找到梗图的

每张图最多从三个方面读，结果再合并排序（倒数排名融合）：

| 途径 | 用什么 | 要显卡吗 |
|---|---|---|
| 图里的字 | 先识别图中文字（[RapidOCR](https://github.com/RapidAI/RapidOCR)），再用 [BGE-M3](https://huggingface.co/BAAI/bge-m3) 按意思匹配 | 不用 |
| 画面 | [Chinese-CLIP](https://github.com/OFA-Sys/Chinese-CLIP) 图文相似度 | 不用 |
| 描述（可选） | 本地视觉语言模型（[Qwen2.5-VL-7B](https://huggingface.co/Qwen/Qwen2.5-VL-7B-Instruct)）写出主题和笑点 | 要，约 16 GB 显存 |

BGE-M3 和 Chinese-CLIP 用的是它们的 8 位 ONNX 版本（[tactino/memeseeks-models](https://huggingface.co/tactino/memeseeks-models)），在 ONNX Runtime 上运行，不需要 PyTorch；下载量是原版的四分之一，搜索结果和原版一致（`experiments/results/onnx.md`）。

在维护者那批字很多的梗图上，前两个途径已经能把每条查询要找的图排进前五，所以「描述」默认关闭。数字见 `experiments/results/`。

## 命令行

```bash
memeseeks add ~/Pictures/memes            # 为一个文件夹建立索引；随时可以重跑，只处理新图
memeseeks serve                           # 网页在 http://127.0.0.1:8765/
memeseeks serve --open                    # 同上，并打开浏览器（已经在运行的话就直接打开）
memeseeks search "关于熬夜的"              # 在终端里搜
memeseeks status                          # 图库里有什么，以及哪些图某一步失败了
memeseeks eval queries.csv                # 给你自己的查询打分（见下）
memeseeks --lib D:\memes-lib status       # --lib 这类全局选项写在子命令前面
```

`add --vlm` 会另外用本地视觉语言模型给图写描述（需要显卡），`add --tidy` 会让视觉语言模型把图里的文字整理成对话和评论、纠正识别错字（需要约 20 GB 显存的显卡），`--retry-failed` 会重做上次失败的图。整理时模型还会认出知名的梗：梗图页显示「梗：电车难题」，点一下就搜同一个梗的其他图；外文梗图没有中文翻译时，会在文字下面显示「【译】…」。

电脑没有显卡时，可以让另一台有显卡的电脑来整理：`memeseeks tidy-remote --host 主机 --home 目录`。它通过 ssh 连过去（要先配好密钥登录），`目录` 里要有装了 `memeseeks[ml,torch]` 的 `.venv` 和模型缓存 `hf-cache`。之后每次更新图库，没整理过的新图都会自动送过去；结果拿回来后，那边的图会删掉。

**评测你自己的查询**：`queries.csv` 第一行是表头，之后每行一条查询和它应该找到的文件名，多个文件名用 `;` 分隔。文件名可以是相对于添加的文件夹的路径，也可以是不重名的文件名。

```csv
query,expected
关于熬夜的,night_owl.jpg
猫在评判你,cat_judge.png;cat_judge_2.png
```

## 手动安装（开发用）

需要 Python 3.10 或更新版本。

```bash
git clone https://github.com/tactino/memeseeks && cd memeseeks
python -m venv .venv && source .venv/bin/activate        # Windows：.venv\Scripts\activate
pip install -e ".[ml,serve]"
```

- 要用显卡功能（`--vlm`、`--tidy`）时，先装对应显卡的 PyTorch，再 `pip install -e ".[torch]"`。

- 第一次运行会把约 1 GB 的模型下载到 Hugging Face 缓存（`HF_HOME`）。**在国内**请先设置 `HF_ENDPOINT=https://hf-mirror.com`。
- **Windows + Anaconda**：如果装了 torch 2.9 或更新版本，不要用 Anaconda 的 Python 建虚拟环境，否则 torch 会报 `WinError 1114 … c10.dll`。原因是 Anaconda 在 `python.exe` 旁边放了一份旧的 MSVC 运行库。改用 python.org 的 Python，或者 uv 管理的 Python（`uv venv --managed-python --python 3.12`）。

## 用 Docker 运行

不用装 Python，只用 CPU。

```bash
git clone https://github.com/tactino/memeseeks && cd memeseeks
cp .env.example .env        # 然后填好 MEMES_DIR 和口令（文件里写了怎么生成）
docker compose up -d
docker compose logs -f      # 等到出现 "memeseeks is at http://…"
```

- 第一次启动会把约 1 GB 的模型下载到 `models` 卷，并为你的文件夹建立索引。**建完索引之前 8765 端口不会响应**，请看日志。
- 之后在每台设备上打开一次 `http://<这台电脑的局域网地址>:8765/?token=<你的口令>`，浏览器会记住它。
- 以后启动只处理新图。更新代码后运行 `docker compose up -d --build`；`docker compose down -v` 会删掉图库和下载的模型。
- 梗图文件夹以只读方式挂载。容器以 uid 1000 运行；如果你把 `library` 卷换成绑定挂载，要让 uid 1000 能写那个文件夹。

## 许可证

代码：MIT。梗图知识库（将来有了之后）：CC BY-SA 4.0。字体 Noto Serif SC 与 JetBrains Mono 的子集按 SIL OFL 1.1 随附。
