# triple-modal-search **Repository Path**: kml/triple-modal-search ## Basic Information - **Project Name**: triple-modal-search - **Description**: Triple-modal similarity search: image / text / audio retrieval with SigLIP, BGE and ECAPA embeddings + FAISS - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-08-26 - **Last Updated**: 2026-08-26 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 🖼️📝🎤 三模态分离检索系统(Triple-Modal Search) **图搜图 · 文搜文 · 音搜音 —— 三个完全隔离的向量空间中的相似度检索。** > English version: [README.md](README.md) 本项目是一个**完全本地化、隐私安全**的相似内容搜索引擎:从你自己的素材库中,找到与查询最相似的图片、文本和音频。 每个模态由独立的深度学习嵌入模型 + FAISS 向量索引支撑,三个空间互不干扰。 | 模态 | 检索方式 | 嵌入模型 | 向量维度 | |------|---------|---------|---------| | 🖼️ 图像 | 上传图片 → 搜相似图片 | [SigLIP](https://huggingface.co/google/siglip-so400m-patch14-384) (so400m, 384px) | 1152 | | 📝 文本 | 输入语句 → 搜相似文本 | [BGE-base-zh-v1.5](https://huggingface.co/BAAI/bge-base-zh-v1.5)(中文优化) | 768 | | 🎤 语音 | 上传音频/录音 → 搜相似音频 | [ECAPA-TDNN](https://huggingface.co/speechbrain/spkrec-ecapa-voxceleb)(SpeechBrain 声纹) | 1024 | ## ✨ 特性 - **三独立面板**:图像 / 文本 / 语音检索完全隔离,互不干扰 - **相似度阈值可调**:每次查询可调阈值,返回 Top-K 结果 - **双界面** - 🌐 **Web 前端**:纯手写原生 JS 前端(检索 / 模型管理 / 仪表盘 / 存储后端切换) - 💻 **CLI 命令行**:功能完整的命令行工具,便于脚本化与自动化 - 🧪 另附 Gradio WebUI(`main.py`) - **可插拔存储后端**:本地 FAISS / Redis / MySQL / Elasticsearch,通过 `data/storage_config.json` 一键切换 - **GPU 加速**:FP16 半精度推理,无 GPU 时自动回退 CPU - **完全本地离线**:模型缓存于磁盘,无需 API Key,数据不出本机 - **可迁移**:所有路径基于项目根目录相对定位;模型可打包,解压后 `restore.py` 一键恢复 - **一键启动**:`start.py` 自动完成建虚拟环境 → 装依赖 → 下模型 → 启动服务 → 打开浏览器 ## 🏗️ 架构 ``` ┌─────────────────────────────────────────────┐ │ Web 前端 (原生 JS) │ │ 图像页 · 文本页 · 语音页 · 仪表盘 │ └──────────────────────┬──────────────────────┘ │ REST /api/* ┌──────────────────────▼──────────────────────┐ │ FastAPI 后端 (api_server.py) │ │ Gradio WebUI (main.py) │ │ CLI 命令行 (cli.py) │ └──────────────────────┬──────────────────────┘ ┌────────────────┬─────────────┼──────────────┬────────────────┐ ▼ ▼ ▼ ▼ ▼ ┌───────────┐ ┌───────────┐ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ SigLIP │ │ BGE │ │ ECAPA │ │ FAISS │ │ Redis / │ │ (图像) │ │ (文本) │ │ (语音) │ │ 索引 │ │ MySQL/ES │ └───────────┘ └───────────┘ └──────────┘ └──────────┘ └──────────┘ 嵌入向量 嵌入向量 嵌入向量 向量存储 ``` 数据流:素材放入 `data/{image,text,audio}_lib` → 扫描入库(模型提向量 → FAISS 索引)→ 查询(上传/输入/录音) → 按相似度返回排序结果。 ## 🚀 快速开始 ### 环境要求 - Python **3.9+** - 约 6 GB 磁盘空间(模型:SigLIP ~2.2 GB、BGE ~1.1 GB、ECAPA ~0.2 GB) - 可选:NVIDIA GPU + CUDA(无 GPU 也可用 CPU 模式,速度较慢) ### 安装与启动 ```bash # 一键启动(自动建虚拟环境、装依赖、下模型、启动服务、打开浏览器) python start.py # 或手动安装 pip install -r requirements.txt python api_server.py # FastAPI + Web 前端,地址 http://127.0.0.1:7860 # python main.py # 或使用 Gradio WebUI ``` ### 首次使用 1. 将素材放入素材库目录:`data/image_lib/`、`data/text_lib/`(`.txt`)、`data/audio_lib/` 2. 在 Web 界面点击「扫描导入」,或运行 `python cli.py scan` 3. 开始检索!上传图片 / 输入语句 / 上传或录制音频 ## 💻 CLI 用法 `cli.py` 仅使用 Python 标准库(argparse),零额外依赖。 ```bash # 查看系统状态:库规模、设备、存储后端、模型缓存情况 python cli.py status # 扫描素材库并导入新文件(递归、自动去重) python cli.py scan # 全部模态 python cli.py scan --modality image # 仅图像 python cli.py scan --folder 子目录 # 仅指定子文件夹 # 相似度检索 python cli.py search image query.jpg # 图搜图 python cli.py search text "深度学习" # 文搜文 python cli.py search audio query.wav # 音搜音 python cli.py search image q.jpg --top-k 10 --threshold 0.8 --json # 手动录入文本 python cli.py add text "要入库的文本" # 清空索引(带确认) python cli.py clear image --yes # 启动 Web 服务 python cli.py serve # FastAPI + 前端(默认) python cli.py serve --webui # Gradio WebUI # 模型管理 python cli.py models # 查看当前模型 python cli.py models --set image google/siglip-base-patch16-224 # 切换模型 # 预下载模型(适合离线环境准备) python cli.py download --modality all ``` ### JSON 输出 `search` 命令加 `--json` 即可输出机器可读结果: ```bash python cli.py search text "机器学习" --json ``` ## 📡 REST API(端口 7860) | 方法 | 端点 | 说明 | |------|------|------| | `POST` | `/api/image/search` | 上传图片 → 检索相似图片 | | `POST` | `/api/image/scan` | 扫描 `image_lib` 导入新图片 | | `POST` | `/api/image/upload` | 直接上传图片入库 | | `GET` | `/api/image/count` | 图像库总数 | | `DELETE` | `/api/image/clear` | 清空图像索引 | | `POST` | `/api/text/search` | 文本查询 → 相似文本 | | `POST` | `/api/text/add` | 手动录入文本 | | `POST` | `/api/text/scan` | 扫描 `text_lib` 导入新文本 | | `POST` | `/api/audio/search` | 上传音频 → 相似音频 | | `POST` | `/api/audio/scan` | 扫描 `audio_lib` 导入新音频 | | `GET` | `/api/status` | 系统状态(模型加载、设备、库规模) | ## 📁 项目结构 ``` ├── api_server.py # FastAPI 后端 + 托管前端静态文件 ├── main.py # Gradio WebUI 入口 ├── cli.py # 命令行工具 ├── start.py # 一键安装/启动(venv、依赖、模型、服务) ├── restore.py # 解压便携包后恢复模型缓存 ├── config.py # 全局配置(路径、阈值、维度、设备) ├── model_config.py # 分模态模型注册与切换 ├── download_tracker.py # 模型下载进度监控 ├── image_db.py / text_db.py / audio_db.py # 模态数据库(存储可插拔) ├── image_utils.py / text_utils.py / audio_utils.py # 嵌入向量提取 ├── storage/ # 向量存储抽象:FAISS / Redis / MySQL / ES ├── frontend/ # 原生 JS Web 前端 ├── data/ │ ├── image_lib/ # 图片素材 │ ├── text_lib/ # 文本素材(.txt) │ ├── audio_lib/ # 音频素材 │ ├── index/ # FAISS 索引文件(运行时生成) │ └── storage_config.json # 存储后端配置 └── requirements.txt ``` ## ⚙️ 配置 ### 存储后端 编辑 `data/storage_config.json`: ```json { "backend": "local", "local": {"index_dir": "data/index"}, "redis": {"host": "127.0.0.1", "port": 6379, "password": "", "db": 0}, "mysql": {"host": "127.0.0.1", "port": 3306, "user": "root", "password": "", "database": "vector_db"}, "es": {"host": "http://127.0.0.1:9200", "user": "", "password": ""} } ``` 将 `"backend"` 改为 `redis` / `mysql` / `es` 即可切换,上层 `*_db.py` 接口完全不变。 ### 嵌入模型 模型 ID 持久化在 `data/model_config.json`(首次运行自动生成)。切换方式: ```bash python cli.py models --set image google/siglip-base-patch16-224 python cli.py models --set text BAAI/bge-small-zh-v1.5 ``` > ⚠️ 切换模型会改变向量空间,切换后需要重新扫描入库。 ### 阈值与设备 见 `config.py`:`IMAGE_THRESHOLD`、`TEXT_THRESHOLD`、`AUDIO_THRESHOLD`、`MAX_RESULTS`、`FP16_INFER`、`DEVICE`。 ## ❓ 常见问题 **为什么第一次查询很慢?** 模型是懒加载的,首次使用时才加载到显存,之后查询很快。 **如何离线运行?** 在有网机器上执行一次 `python cli.py download`,然后拷贝 `~/.cache/huggingface` 与 `~/.cache/speechbrain`(或便携包 `.model_cache` + `restore.py` 恢复)。 **可以换模型吗?** 可以,见「嵌入模型」一节;`model_config.py` 里预置了部分备选轻量模型。 **语音检索是声纹识别,不是语音转写。** ECAPA 直接从波形提取声音特征——它找的是*音色相似*的音频,全程不做 ASR 文字转写。 ## 💖 支持项目 如果这个项目对你有帮助,欢迎请我喝杯咖啡: | 支付宝 | 微信 | |:------:|:----:| | 支付宝收款码 | 微信收款码 | ## 📄 License MIT