图片索引与文章自动插图
安装位置要求(重要)
本技能只安装到项目级,不要安装到全局目录(~/.claude/skills/、~/.agents/skills/ 等):
- 多数工具(Codex、Kimi Code、Cursor 等):解压到项目根目录的
.agents/skills/image-indexer/(Agent Skills 开放标准 universal 目录,工具自动发现) - Claude Code:解压到项目根目录的
.claude/skills/image-indexer/
安装方式:从技能中心页面下载 zip 解压到上述项目目录;或安装 content-system-setup 技能后运行 python3 scripts/setup.py --install-skills,自动下载安装全部配套技能(项目级)。
Overview
这是一个本地照片管理与写作辅助工具。核心能力是将你的本地照片库转化为可语义搜索的向量索引,然后在写 Markdown 文章时,自动分析段落内容,从你的照片库中匹配最合适的照片插入。
核心原理:
- 视觉模型看懂每张照片 → 生成中文描述 + 标签 + 场景 + 氛围
- Embedding 模型将描述转为 1024 维向量 → 存为索引
- 搜索时将查询文本同样转为向量 → 余弦相似度匹配 → 返回 Top-K
与华为相册缓存的类比:华为用缩略图做"替身"快速预览,这个系统用向量描述做"替身"快速搜索。
Usage
/image-indexer index # 构建图片索引
/image-indexer search "日落海边" # 搜索照片
/image-indexer insert 文章.md # 文章自动配图
/image-indexer status # 查看索引状态
每次使用前需确保 SILICONFLOW_API_KEY 环境变量已设置。
Example
从头构建索引到文章配图的完整示例:
# 1. 构建索引(先测试 20 张)
cd scripts && python3 scan_images.py --limit 20
SILICONFLOW_API_KEY="sk-xxx" python3 generate_descriptions.py --limit 20
SILICONFLOW_API_KEY="sk-xxx" python3 build_embeddings.py
# 2. 搜索照片
SILICONFLOW_API_KEY="sk-xxx" python3 search_images.py "木桌上的茶具" --top-k 3
# 3. 为文章配图
SILICONFLOW_API_KEY="sk-xxx" python3 insert_images.py ~/article.md ~/article_illustrated.md
When to Use
- 写完一篇 Markdown 文章,想从自己的照片库里配图(而非网上找图)
- 想搜索手机里有没有某个场景的照片:"有没有日落的照片"
- 第一次使用或新增照片后,需要构建/更新索引
- 查看索引状态和统计
When NOT to Use
- 从网上搜索图片 → 用浏览器或图库网站
- 批量修图/管理照片 → 用照片管理软件
- 文章排版/发布 → 用配套的排版/发布技能
- 只需要一篇文章的快速配图且不关心图片来源 → 直接用 Pexels/Unsplash
Quick Reference
| 操作 | 命令(在 skill 根目录下执行) | 说明 |
|------|------|------|
| 构建索引(全量) | cd scripts && python3 scan_images.py && python3 generate_descriptions.py && python3 build_embeddings.py | 首次使用,约需 30-60 分钟 |
| 构建索引(测试) | 同上,加 --limit 20 | 先跑 20 张验证流程 |
| 搜索照片 | cd scripts && SILICONFLOW_API_KEY="sk-xxx" python3 search_images.py "日落海边" --top-k 5 | 自然语言搜索 |
| 文章配图 | cd scripts && SILICONFLOW_API_KEY="sk-xxx" python3 insert_images.py 文章.md 输出.md | 自动在段落间插入照片 |
| 查看状态 | python3 -c "import json; d=json.load(open('$HOME/image-indexer/data/image_descriptions.json')); print(f'已索引: {len(d)} 张')" | 索引进度查询 |
环境要求
API Key
需要 SiliconFlow API Key(免费注册 https://cloud.siliconflow.cn),设为环境变量:
export SILICONFLOW_API_KEY="sk-xxxxxxxx"
Python 依赖
pip3 install numpy Pillow requests
目录结构
image-indexer/
├── SKILL.md # 本文件
└── scripts/
├── config.py # 配置(路径、API、过滤规则)
├── scan_images.py # 步骤1:扫描图片,过滤缓存
├── generate_descriptions.py # 步骤2:AI 生成描述
├── build_embeddings.py # 步骤3:构建向量索引
├── search_images.py # 步骤4:语义搜索(含 ImageSearcher 类)
└── insert_images.py # 步骤5:文章自动插图
~/image-indexer/data/ # 索引数据(不随 skill 走)
├── image_inventory.json # 图片清单
├── image_descriptions.json # AI 生成的描述
├── image_embeddings.npy # 向量数组 (N×1024)
├── image_paths.json # 路径列表(与向量对应)
└── error_log.json # 处理失败记录
Workflow
操作 1:构建图片索引(一次性)
用户说"索引照片"、"构建图片索引"时执行。
Step 1: 确认 API Key
echo $SILICONFLOW_API_KEY
如果为空,引导用户设置。
Step 2: 扫描图片
cd scripts && python3 scan_images.py --limit 20
过滤规则:
- 必须为 jpg/jpeg/png/heic/webp/bmp 格式
- 宽或高 < 200px 的缩略图不收录
- 纯数字名、hash 名、
_compv2、.tmp/.dat/.xml/.bak等缓存文件过滤
Step 3: 生成描述
SILICONFLOW_API_KEY="sk-xxx" python3 generate_descriptions.py --limit 20
- 图片压缩到最长边 512px,转 base64 发给 SiliconFlow
- 5 线程并发,每 50 张保存进度
- 支持断点续传(重新运行自动跳过已处理)
- 失败记录写入
error_log.json
Step 4: 构建向量索引
SILICONFLOW_API_KEY="sk-xxx" python3 build_embeddings.py
- 拼接 caption + tags + scene + mood → 输入 BAAI/bge-m3
- 输出 1024 维向量,批量 32 条,存为 numpy 数组
测试验证后,去掉 --limit 跑全量。
操作 2:搜索照片
用户说"找一张...的照片"、"搜索我的照片"、"有没有...的图"时执行。
cd scripts && SILICONFLOW_API_KEY="sk-xxx" python3 search_images.py "用户的自然语言查询" --top-k 5 --min-score 0.2
返回结果包含:文件名、描述、标签、场景、氛围、相似度分数。
在对话中直接展示匹配结果表格,让用户确认选哪张。
操作 3:文章自动配图
用户说"给这篇文章配图"、"插图"、"把我的照片插到文章里"时执行。
cd scripts && SILICONFLOW_API_KEY="sk-xxx" python3 insert_images.py /path/to/article.md /path/to/output.md --density 3 --max-images 6 --min-score 0.3
参数说明:
--density 3:每 3 个段落插入一张图(默认 4)--min-score 0.3:最低相似度阈值,低于此分数宁可不插图--max-images 10:单篇文章最多插图数
系统会:
- 解析文章段落结构,跳过标题/列表/代码块
- 提取每个候选位置的上下文(上下各 2 段)
- 语义搜索最匹配的照片
- 同一文章不重复使用同一张图
- 分数低于阈值的位置主动跳过
完成后展示匹配结果表格:
| 位置 | 照片 | 分数 | 说明 |
|------|------|------|------|
| 段落2 | 沙朴树.jpg | 0.59 | 匹配"树林"上下文 |
配置说明
scripts/config.py 中的关键配置:
| 配置项 | 默认值 | 说明 |
|--------|--------|------|
| PHOTOS_DIR | ~/Pictures/照片 | 照片目录(需自行修改;内容创作系统建议指向 07_视觉与排版/图片库/) |
| DATA_DIR | ~/image-indexer/data/ | 索引数据目录 |
| VISION_MODELS | GLM-4.1V-9B → Qwen3-VL-8B → Qwen3-VL-30B | 视觉模型优先级 |
| EMBEDDING_MODEL | BAAI/bge-m3 | 向量模型 |
| CONCURRENCY | 5 | 并发数 |
| SAVE_INTERVAL | 50 | 断点保存间隔 |
| MIN_SCORE | 0.3 | 搜索最低相似度 |
Common Mistakes
| 错误 | 原因 | 修复 |
|------|------|------|
| API 超时 | SiliconFlow 免费额度限速 | 已内置 3 次重试 + 60s 超时 |
| 描述生成中断 | 网络波动/API 异常 | 重新运行,自动断点续传 |
| 插图不匹配 | 索引照片太少 | 索引照片足够多后匹配度大幅提升 |
| 找不到合适的图 | 候选照片与文章主题无关 | 系统会主动跳过(分数低于阈值),不会强行插入 |
| ModuleNotFoundError | 缺少 Python 依赖 | pip3 install numpy Pillow requests |
Resources
- scripts/scan_images.py — 图片扫描,过滤缓存/缩略图
- scripts/generate_descriptions.py — 批量 AI 描述生成(支持断点续传)
- scripts/build_embeddings.py — 向量索引构建
- scripts/search_images.py — 语义搜索(ImageSearcher 类)
- scripts/insert_images.py — 文章自动插图
- scripts/config.py — 统一配置
微信扫一扫