[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"similar-neonwatty--meme-search":3,"tool-neonwatty--meme-search":62},[4,18,26,36,46,54],{"id":5,"name":6,"github_repo":7,"description_zh":8,"stars":9,"difficulty_score":10,"last_commit_at":11,"category_tags":12,"status":17},4358,"openclaw","openclaw\u002Fopenclaw","OpenClaw 是一款专为个人打造的本地化 AI 助手，旨在让你在自己的设备上拥有完全可控的智能伙伴。它打破了传统 AI 助手局限于特定网页或应用的束缚，能够直接接入你日常使用的各类通讯渠道，包括微信、WhatsApp、Telegram、Discord、iMessage 等数十种平台。无论你在哪个聊天软件中发送消息，OpenClaw 都能即时响应，甚至支持在 macOS、iOS 和 Android 设备上进行语音交互，并提供实时的画布渲染功能供你操控。\n\n这款工具主要解决了用户对数据隐私、响应速度以及“始终在线”体验的需求。通过将 AI 部署在本地，用户无需依赖云端服务即可享受快速、私密的智能辅助，真正实现了“你的数据，你做主”。其独特的技术亮点在于强大的网关架构，将控制平面与核心助手分离，确保跨平台通信的流畅性与扩展性。\n\nOpenClaw 非常适合希望构建个性化工作流的技术爱好者、开发者，以及注重隐私保护且不愿被单一生态绑定的普通用户。只要具备基础的终端操作能力（支持 macOS、Linux 及 Windows WSL2），即可通过简单的命令行引导完成部署。如果你渴望拥有一个懂你",349277,3,"2026-04-06T06:32:30",[13,14,15,16],"Agent","开发框架","图像","数据工具","ready",{"id":19,"name":20,"github_repo":21,"description_zh":22,"stars":23,"difficulty_score":10,"last_commit_at":24,"category_tags":25,"status":17},3808,"stable-diffusion-webui","AUTOMATIC1111\u002Fstable-diffusion-webui","stable-diffusion-webui 是一个基于 Gradio 构建的网页版操作界面，旨在让用户能够轻松地在本地运行和使用强大的 Stable Diffusion 图像生成模型。它解决了原始模型依赖命令行、操作门槛高且功能分散的痛点，将复杂的 AI 绘图流程整合进一个直观易用的图形化平台。\n\n无论是希望快速上手的普通创作者、需要精细控制画面细节的设计师，还是想要深入探索模型潜力的开发者与研究人员，都能从中获益。其核心亮点在于极高的功能丰富度：不仅支持文生图、图生图、局部重绘（Inpainting）和外绘（Outpainting）等基础模式，还独创了注意力机制调整、提示词矩阵、负向提示词以及“高清修复”等高级功能。此外，它内置了 GFPGAN 和 CodeFormer 等人脸修复工具，支持多种神经网络放大算法，并允许用户通过插件系统无限扩展能力。即使是显存有限的设备，stable-diffusion-webui 也提供了相应的优化选项，让高质量的 AI 艺术创作变得触手可及。",162132,"2026-04-05T11:01:52",[14,15,13],{"id":27,"name":28,"github_repo":29,"description_zh":30,"stars":31,"difficulty_score":32,"last_commit_at":33,"category_tags":34,"status":17},1381,"everything-claude-code","affaan-m\u002Feverything-claude-code","everything-claude-code 是一套专为 AI 编程助手（如 Claude Code、Codex、Cursor 等）打造的高性能优化系统。它不仅仅是一组配置文件，而是一个经过长期实战打磨的完整框架，旨在解决 AI 代理在实际开发中面临的效率低下、记忆丢失、安全隐患及缺乏持续学习能力等核心痛点。\n\n通过引入技能模块化、直觉增强、记忆持久化机制以及内置的安全扫描功能，everything-claude-code 能显著提升 AI 在复杂任务中的表现，帮助开发者构建更稳定、更智能的生产级 AI 代理。其独特的“研究优先”开发理念和针对 Token 消耗的优化策略，使得模型响应更快、成本更低，同时有效防御潜在的攻击向量。\n\n这套工具特别适合软件开发者、AI 研究人员以及希望深度定制 AI 工作流的技术团队使用。无论您是在构建大型代码库，还是需要 AI 协助进行安全审计与自动化测试，everything-claude-code 都能提供强大的底层支持。作为一个曾荣获 Anthropic 黑客大奖的开源项目，它融合了多语言支持与丰富的实战钩子（hooks），让 AI 真正成长为懂上",160015,2,"2026-04-18T11:30:52",[14,13,35],"语言模型",{"id":37,"name":38,"github_repo":39,"description_zh":40,"stars":41,"difficulty_score":42,"last_commit_at":43,"category_tags":44,"status":17},8272,"opencode","anomalyco\u002Fopencode","OpenCode 是一款开源的 AI 编程助手（Coding Agent），旨在像一位智能搭档一样融入您的开发流程。它不仅仅是一个代码补全插件，而是一个能够理解项目上下文、自主规划任务并执行复杂编码操作的智能体。无论是生成全新功能、重构现有代码，还是排查难以定位的 Bug，OpenCode 都能通过自然语言交互高效完成，显著减少开发者在重复性劳动和上下文切换上的时间消耗。\n\n这款工具专为软件开发者、工程师及技术研究人员设计，特别适合希望利用大模型能力来提升编码效率、加速原型开发或处理遗留代码维护的专业人群。其核心亮点在于完全开源的架构，这意味着用户可以审查代码逻辑、自定义行为策略，甚至私有化部署以保障数据安全，彻底打破了传统闭源 AI 助手的“黑盒”限制。\n\n在技术体验上，OpenCode 提供了灵活的终端界面（Terminal UI）和正在测试中的桌面应用程序，支持 macOS、Windows 及 Linux 全平台。它兼容多种包管理工具，安装便捷，并能无缝集成到现有的开发环境中。无论您是追求极致控制权的资深极客，还是渴望提升产出的独立开发者，OpenCode 都提供了一个透明、可信",144296,1,"2026-04-16T14:50:03",[13,45],"插件",{"id":47,"name":48,"github_repo":49,"description_zh":50,"stars":51,"difficulty_score":32,"last_commit_at":52,"category_tags":53,"status":17},2271,"ComfyUI","Comfy-Org\u002FComfyUI","ComfyUI 是一款功能强大且高度模块化的视觉 AI 引擎，专为设计和执行复杂的 Stable Diffusion 图像生成流程而打造。它摒弃了传统的代码编写模式，采用直观的节点式流程图界面，让用户通过连接不同的功能模块即可构建个性化的生成管线。\n\n这一设计巧妙解决了高级 AI 绘图工作流配置复杂、灵活性不足的痛点。用户无需具备编程背景，也能自由组合模型、调整参数并实时预览效果，轻松实现从基础文生图到多步骤高清修复等各类复杂任务。ComfyUI 拥有极佳的兼容性，不仅支持 Windows、macOS 和 Linux 全平台，还广泛适配 NVIDIA、AMD、Intel 及苹果 Silicon 等多种硬件架构，并率先支持 SDXL、Flux、SD3 等前沿模型。\n\n无论是希望深入探索算法潜力的研究人员和开发者，还是追求极致创作自由度的设计师与资深 AI 绘画爱好者，ComfyUI 都能提供强大的支持。其独特的模块化架构允许社区不断扩展新功能，使其成为当前最灵活、生态最丰富的开源扩散模型工具之一，帮助用户将创意高效转化为现实。",109154,"2026-04-18T11:18:24",[14,15,13],{"id":55,"name":56,"github_repo":57,"description_zh":58,"stars":59,"difficulty_score":32,"last_commit_at":60,"category_tags":61,"status":17},6121,"gemini-cli","google-gemini\u002Fgemini-cli","gemini-cli 是一款由谷歌推出的开源 AI 命令行工具，它将强大的 Gemini 大模型能力直接集成到用户的终端环境中。对于习惯在命令行工作的开发者而言，它提供了一条从输入提示词到获取模型响应的最短路径，无需切换窗口即可享受智能辅助。\n\n这款工具主要解决了开发过程中频繁上下文切换的痛点，让用户能在熟悉的终端界面内直接完成代码理解、生成、调试以及自动化运维任务。无论是查询大型代码库、根据草图生成应用，还是执行复杂的 Git 操作，gemini-cli 都能通过自然语言指令高效处理。\n\n它特别适合广大软件工程师、DevOps 人员及技术研究人员使用。其核心亮点包括支持高达 100 万 token 的超长上下文窗口，具备出色的逻辑推理能力；内置 Google 搜索、文件操作及 Shell 命令执行等实用工具；更独特的是，它支持 MCP（模型上下文协议），允许用户灵活扩展自定义集成，连接如图像生成等外部能力。此外，个人谷歌账号即可享受免费的额度支持，且项目基于 Apache 2.0 协议完全开源，是提升终端工作效率的理想助手。",100752,"2026-04-10T01:20:03",[45,13,15,14],{"id":63,"github_repo":64,"name":65,"description_en":66,"description_zh":67,"ai_summary_zh":67,"readme_en":68,"readme_zh":69,"quickstart_zh":70,"use_case_zh":71,"hero_image_url":72,"owner_login":73,"owner_name":74,"owner_avatar_url":75,"owner_bio":76,"owner_company":76,"owner_location":76,"owner_email":76,"owner_twitter":73,"owner_website":77,"owner_url":78,"languages":79,"stars":112,"forks":113,"last_commit_at":114,"license":115,"difficulty_score":10,"env_os":116,"env_gpu":117,"env_ram":118,"env_deps":119,"category_tags":129,"github_topics":130,"view_count":32,"oss_zip_url":76,"oss_zip_packed_at":76,"status":17,"created_at":139,"updated_at":140,"faqs":141,"releases":175},9185,"neonwatty\u002Fmeme-search","meme-search","The open source Meme Search Engine and Finder.  Free and built to self-host locally with Python, Ruby, and Docker.","meme-search 是一款开源的表情包搜索引擎，旨在帮助用户高效管理和检索本地存储的海量表情包。面对日益增多的图片素材，传统文件夹分类往往难以快速定位特定内容，而 meme-search 利用人工智能技术，自动提取图片中的文字并分析视觉语义，建立本地索引。用户只需输入自然语言描述，即可通过语义搜索瞬间找到目标表情包，彻底解决了“存图容易找图难”的痛点。\n\n该工具最大的亮点在于完全本地化运行。从图像文字识别、向量嵌入到搜索匹配，所有数据处理均在用户自己的设备上完成，无需上传云端，充分保障了隐私安全与数据主权。它支持多种规模的图像转文本模型，用户可根据硬件配置灵活选择，同时提供 Docker 容器化部署方案，简化了安装与维护流程。此外，它还具备批量生成、拖拽上传、深色模式及自定义筛选等实用功能。\n\nmeme-search 非常适合注重隐私的技术爱好者、开发者以及拥有大量表情包收藏的普通用户使用。对于希望搭建私有化媒体库的个人或团队，它也是一个轻量级且强大的解决方案。无论是为了日常聊天快速调图，还是进行本地图像数据的语义分析实验，meme-search 都能提供流畅、安全的体验。","# A Meme Search Engine built to self-host in Python, Ruby, and Docker\n\n[![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Server-7289da?style=flat&logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002FdamGu7aEHH)\n\nUse AI to index your memes by their content and text, making them easily retrievable for your meme warfare pleasures.\n\nAll processing - from image-to-text extraction, to vector embedding, to search - is performed locally.\n\n  \u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_23d984300bc6.png\"\n  alt=\"meme-search-2.0-demo\">\n  \u003C\u002Fp>\n  \nThis repository contains code, a walkthrough notebook, and apps for indexing, searching, and easily retrieving your memes based on semantic search of their content and text.\n\nA table of contents for the remainder of this README:\n\n- [Meme search](#meme-search)\n\n  - [Features](#features)\n  - [Requirements](#requirements)\n  - [Installation instructions](#installation-instructions)\n  - [Time to first generation \u002F downloading models](#time-to-first-generation--downloading-models)\n  - [Index your memes](#index-your-memes)\n  - [Custom app port](#custom-app-port)\n  - [Building the app locally with Docker](#building-the-app-locally-with-docker)\n  - [Running tests](#running-tests)\n- [Discord server](#discord-server)\n- [Changelog](#changelog)\n- [Feature requests and contributing](#feature-requests-and-contributing)\n\n\n## Meme search\n\n### Features\n\n\u003Cp align=\"center\">\n  \u003Cdiv style=\"display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;\">\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_8e7740784138.gif\" height=\"225\">\n      \u003Cfigcaption>Search\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_b1da18ebcf2a.gif\" height=\"225\">\n      \u003Cfigcaption>Edit\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_3ae30ee0b179.gif\" height=\"225\">\n      \u003Cfigcaption>Filter\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_05a22f59cb4e.gif\" height=\"225\">\n      \u003Cfigcaption>Generate\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_6b262f102e0b.gif\" height=\"225\">\n      \u003Cfigcaption>Bulk Generation\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_07363310a07a.gif\" height=\"225\">\n      \u003Cfigcaption>Dark Mode\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_706c1648887e.png\" height=\"225\">\n      \u003Cfigcaption>Rescan\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_4e2e2cc7594b.png\" height=\"225\">\n      \u003Cfigcaption>Rescan Status\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_41449936a5d9.png\" height=\"225\">\n      \u003Cfigcaption>Rescan Options\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_40008198b9da.gif\" height=\"225\">\n      \u003Cfigcaption>Drag-and-Drop Upload\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n  \u003C\u002Fdiv>\n\u003C\u002Fp>\n\nFeatures of Meme Search include:\n\n1. **Multiple Image-to-Text Models**\n\n   Choose the right size image to text model for your needs \u002F resources - from small (~200 Million parameters) to large (~2 Billion parameters).\n\n   Current available image-to-text models for Meme Search include the following, starting with the default model:\n\n   - [Florence-2-base](https:\u002F\u002Fhuggingface.co\u002Fmicrosoft\u002FFlorence-2-base) - a popular series of small vision language models built by Microsoft, including a 250 Million (base) and a 700 Million (large) parameter variant. \\*This is the default model used in Meme Search\\*.\n   - [Florence-2-large](https:\u002F\u002Fhuggingface.co\u002Fmicrosoft\u002FFlorence-2-large) - the 700 Million parameter vision language model variant of the Florence-2 series\n   - [SmolVLM-256](https:\u002F\u002Fhuggingface.co\u002Fcollections\u002FHuggingFaceTB\u002Fsmolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) - a 256 Million parameter vision language model built by Hugging Face\n   - [SmolVLM-500](https:\u002F\u002Fhuggingface.co\u002Fcollections\u002FHuggingFaceTB\u002Fsmolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) - a 500 Million parameter vision language model built by Hugging Face\n   - [Moondream2](https:\u002F\u002Fhuggingface.co\u002Fvikhyatk\u002Fmoondream2) - a 2 Billion parameter vision language model used for image captioning \u002F extracting image text\n   - [Moondream2-INT8](https:\u002F\u002Fhuggingface.co\u002Fvikhyatk\u002Fmoondream2) - INT8 quantized version of Moondream2 for memory-constrained hardware. Reduces memory from ~5GB to ~1.5-2GB with minimal quality loss. Ideal for CPU-only machines.\n\n2. **Auto-Generate Meme Descriptions**\n\n   Target specific memes for auto-description generation (instead of applying to your entire directory).\n\n3. **Manual Meme Description Editing**\n\n   Edit or add descriptions manually for better search results, no need to wait for auto-generation if you don't want to.\n\n4. **Tags**\n\n   Create, edit, and assign tags to memes for better organization and search filtering.\n\n5. **Fast Vector Search**\n\n   Powered by Postgres and pgvector, enjoy faster keyword and vector searches with streamlined database transactions.\n\n6. **Directory Paths**\n\n   Organize your memes across multiple subdirectories—no need to store everything in one folder.\n\n7. **New Organizational Tools**\n\n   Filter by tags, directory paths, and description embeddings, plus toggle between keyword and vector search for more control.\n\n8. **Bulk Description Generation**\n\n   Generate descriptions for multiple memes at once for faster indexing.\n\n9. **Dark Mode**\n\n   Toggle between light and dark themes for comfortable viewing in any environment.\n\n10. **Directory Rescan**\n\n   Automatically detect and index new memes added to your directories.\n\n11. **Drag-and-Drop Upload**\n\n   Upload memes directly through the web interface with drag-and-drop support. Files are stored in the `direct-uploads` directory (configurable via Docker volume mount) and automatically scanned for indexing. Supports JPG, PNG, and WEBP formats with bulk upload (up to 50 files), real-time progress tracking, and automatic duplicate filename handling.\n\n### Requirements\n\n**For Docker deployment** (recommended):\n- Docker and Docker Compose\n\n**For local development**:\n- Ruby 3.4.2\n- Rails 8.0.4\n- Python 3.12\n- Node.js 20 LTS\n- PostgreSQL 17 with pgvector extension\n\nWe recommend using [mise](https:\u002F\u002Fmise.jdx.dev\u002F) for managing Ruby, Python, and Node.js versions. See [CLAUDE.md](CLAUDE.md) for detailed setup instructions.\n\n### Installation instructions\n\nTo start up the app pull this repository and start the server cluster with docker-compose\n\n```sh\ndocker compose up\n```\n\nThis pulls and starts containers for the app, database, and auto description generator. The app itself will run on port `3000` and is available at\n\n```sh\nhttp:\u002F\u002Flocalhost:3000\n```\n\nTo start the app alone pull the repo and cd into the `meme_search\u002Fmeme_search\u002Fmeme_search_app`. Once there execute the following to start the app in development mode\n\n```sh\n.\u002Fbin\u002Fdev\n```\n\nWhen doing this ensure you have an available Postgres instance running locally on port `5432`.\n\n**Note Linux users:** you may need to add the following `extra_hosts` to your `meme_search` service for inter-container communication\n\n```sh\nextra_hosts:\n    - \"host.docker.internal:host-gateway\"\n```\n\n### Time to first generation \u002F downloading models\n\nThe first auto generation of description of a meme takes longer than average, as image-to-text model weights are downloaded and cached. Subsequent generations are faster.\n\nYou can download additional models in the settings tab of the app.\n\n### Index your memes\n\nYou can index your memes by creating your own descriptions, or by generating descriptions automatically, as illustrated below.\n\n\u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_05a22f59cb4e.gif\" height=\"225\">\n\nTo start indexing your own memes, first adjust the [compose file](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fdocker-compose.yml) by adding `volume` mount to the `meme_search` and `image_to_text_generator` services to properly connect your local meme subdirectory to the app.\n\nFor example, if suppose (one of your) meme directories was called `new_memes` and was located at the following path on your machine: `\u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes`.\n\nTo properly mount this subdirectory to the `meme_search` service adjust the `volumes` portion of its configuration to the following:\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- example meme directory from the repository\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Frails\u002Fpublic\u002Fmemes\u002Fnew_memes # \u003C-- personal meme collection - must be placed inside \u002Frails\u002Fpublic\u002Fmemes in the container\n```\n\nNote: your `new_memes` directory must be mounted internally in the `\u002Frails\u002Fpublic\u002Fmemes` directory, as shown above.\n\nTo properly mount this same subdirectory to the `image_to_text_generator` service adjust the `volumes` portion of its configuration to the following:\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- example meme directory from the repository\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\u002Fnew_memes # \u003C-- personal meme collection - must be placed inside \u002Fapp\u002Fpublic\u002Fmemes in the container\n...\n```\n\nNote: your `new_memes` directory must be mounted internally in the `\u002Fapp\u002Fpublic\u002Fmemes` directory, as shown above.\n\nIf you are concerned about the application altering your existing meme library, as a precaution you can make the mount read only by adding \"ro\" to the volume line as follows:\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- example meme directory from the repository\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\u002Fnew_memes:ro\n...\n```\n\nNow restart the app, and register the `new_memes` via the UX by traversing to the `settings -> paths -> create new` as illustrated below.  Type in `new_memes` in the field provided and press `enter`.\n\n\u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_3c2b68fcc6aa.webp\" height=\"225\">\n\nOnce registered in the app, your memes are ready for indexing \u002F tagging \u002F etc.,!\n\n### Model downloads\n\nThe image-to-text models used to auto generate descriptions for your memes are all open source, and vary in size.\n\n### Custom app port\n\nEasily customize the app's port to more easily use the it with tools like [Unraid](https:\u002F\u002Funraid.net\u002F?srsltid=AfmBOorvWvSZbCHKnqdR__AcllotnsLR6did_FhAaNfUowqqU2IprD1v) or [Portainer](https:\u002F\u002Fwww.portainer.io\u002F), or because you already have services running on the default `meme_search` app port `3000`.\n\nTo customize the main app port create a `.env` file locally in the root of the directory. In this file you can define the following custom environment variables which define how the app, image to text generator, and database are accessed. These values are:\n\n```sh\nAPP_PORT= # the port for the app - defaults to 3000\n```\n\nThis value is automatically detected and loaded into each service via the `docker-compose-pro.yml` file.\n\n### Building the app locally with Docker\n\n**Docker images are built manually only** - there are no automated CI builds on releases or tags.\n\nTo build the app - including all services defined in the `docker-compose.yml` file - locally run the local compose file at your terminal as\n\n```sh\ndocker compose -f docker-compose-local-build.yml up --build\n```\n\nFor multi-platform builds (AMD64 + ARM64) and pushing to GitHub Container Registry, use the local build script:\n\n```sh\nbash scripts\u002Fbuild_and_push.sh\n```\n\nThis will build the docker images for the app, database, and auto description generator, and start the app at `http:\u002F\u002Flocalhost:3000`.\n\n### Running tests\n\nTo run tests locally pull the repo and cd into the `meme_search\u002Fmeme_search\u002Fmeme_search_app` directory. Install the required gems as\n\n```sh\nbundle install\n```\n\nTests can then be run as\n\n```sh\nbash run_tests.sh\n```\n\nWhen doing this ensure you have an available Postgres instance running locally on port `5432`.\n\nRun linting tests on the `\u002Fapp` subdirectory as\n\n```sh\nrubocop app\n```\n\nto ensure the code is clean and well formatted.\n\n#### Running CI Locally (Optional)\n\nYou can run the complete GitHub Actions CI workflow locally using [act](https:\u002F\u002Fgithub.com\u002Fnektos\u002Fact):\n\n```bash\n# Install act (macOS)\nbrew install act\n\n# Run all CI jobs\nact --container-architecture linux\u002Famd64 -P ubuntu-latest=catthehacker\u002Fubuntu:act-latest\n\n# Run specific job\nact -j pro_app_unit_tests --container-architecture linux\u002Famd64 -P ubuntu-latest=catthehacker\u002Fubuntu:act-latest\n```\n\nThis validates your changes match CI before pushing to GitHub.\n\n#### Docker E2E Tests (Local Validation Only)\n\n**Docker E2E tests validate the complete microservices stack** (Rails + Python + PostgreSQL) in isolated Docker containers. These tests run against fresh Docker builds and test cross-service communication, webhooks, and production-like deployment.\n\n**Current Status**: 6\u002F7 smoke tests passing (85% coverage) - see `playwright-docker\u002FREADME.md` for details\n\n```bash\n# Run all Docker E2E tests\nnpm run test:e2e:docker\n\n# Run with UI mode (recommended for debugging)\nnpm run test:e2e:docker:ui\n```\n\n**What these tests cover**:\n- Complete image processing pipeline (Rails → Python → Rails webhooks)\n- Vector search with embedding generation\n- Keyword search functionality\n- Concurrent processing and job queueing\n- Embedding refresh operations\n\n**Important**: These tests **DO NOT run in CI** due to Docker build time (~10-15 minutes) and resource requirements. **Contributors MUST run these tests locally** before submitting PRs that affect:\n- Docker configurations\n- Cross-service communication\n- Image-to-text generation workflow\n- Embedding generation\n\nSee `playwright-docker\u002FREADME.md` for comprehensive documentation.\n\n## Discord server\n\nJoin our Discord server [![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Server-7289da?style=flat&logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002FdamGu7aEHH) to discuss new features, bug fixes, and other open source projects (like [ytgify](https:\u002F\u002Fchromewebstore.google.com\u002Fdetail\u002Fytgify\u002Fdnljofakogbecppbkmnoffppkfdmpfje) - a browser extension for clipping GIFs from YouTube right from the YT Player!).\n\n## Changelog\n\nMeme Search is under active development! See the `CHANGELOG.md` in this repo for a record of the most recent changes.\n\n## Feature requests and contributing\n\nFeature requests and contributions are welcome!\n\nSee [the discussion section of this repository](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme_search\u002Fdiscussions) for suggested enhancements to contribute to \u002F weight in on!\n\nPlease see `CONTRIBUTING.md` for some boilerplate ground rules for contributing.\n\nBelow is a nice diagram of the repo [generated using gitdiagram](https:\u002F\u002Fgithub.com\u002Fahmedkhaleel2004\u002Fgitdiagram), laying out its main components and interactions.\n\n```mermaid\nflowchart TD\n    %% Global Entities\n    User[\"User\"]:::user\n\n    %% Docker & Compose Orchestration\n    Docker[\"Docker & Compose Orchestration\"]:::docker\n\n    %% Main Services\n    Rails[\"Rails Meme Search Application\"]:::rails\n    Python[\"Image-to-Text Generator (Python)\"]:::python\n    DB[\"PostgreSQL Database (with pgvector)\"]:::database\n\n    %% Shared File Volumes Subgraph\n    subgraph \"Shared Meme Files\"\n        PublicMemes[\"Public Memes\"]:::volume\n        MemeDir[\"Meme Directory\"]:::volume\n    end\n\n    %% Interactions\n    User -->|\"interaction\"| Rails\n    Rails -->|\"DBQueryUpdate\"| DB\n    Rails -->|\"APIRequest\"| Python\n    Python -->|\"APIResponse\"| Rails\n\n    %% Volume Access\n    Rails ---|\"VolumeMountAccess\"| PublicMemes\n    Python ---|\"VolumeMountAccess\"| MemeDir\n\n    %% Docker Orchestration Links\n    Docker ---|\"orchestrates\"| Rails\n    Docker ---|\"orchestrates\"| Python\n    Docker ---|\"orchestrates\"| DB\n\n    %% Click Events\n    click Rails \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\"\n    click Python \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fimage_to_text_generator\"\n    click DB \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\u002Fconfig\u002Fdatabase.yml\"\n    click Docker \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fdocker-compose.yml\"\n    click PublicMemes \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\u002Fpublic\u002Fmemes\"\n    click MemeDir \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmemes\"\n\n    %% Styles\n    classDef user fill:#fceabb,stroke:#d79b00,stroke-width:2px;\n    classDef rails fill:#c8e6c9,stroke:#388e3c,stroke-width:2px;\n    classDef python fill:#bbdefb,stroke:#1976d2,stroke-width:2px;\n    classDef database fill:#ffe082,stroke:#f9a825,stroke-width:2px,stroke-dasharray: 5 5;\n    classDef docker fill:#d1c4e9,stroke:#673ab7,stroke-width:2px,stroke-dasharray: 3 3;\n    classDef volume fill:#ffcdd2,stroke:#e53935,stroke-width:2px,stroke-dasharray: 2 2;\n```\n","# 一款用 Python、Ruby 和 Docker 自托管的迷因搜索引擎\n\n[![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Server-7289da?style=flat&logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002FdamGu7aEHH)\n\n利用 AI 根据内容和文本为你的迷因建立索引，让你轻松检索，尽享迷因大战的乐趣。\n\n所有处理——从图像转文本提取、向量嵌入到搜索——均在本地完成。\n\n  \u003Cp align=\"center\">\n    \u003Cimg src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_23d984300bc6.png\"\n  alt=\"meme-search-2.0-demo\">\n  \u003C\u002Fp>\n  \n本仓库包含代码、教程笔记本以及用于索引、搜索和基于语义搜索内容与文本轻松检索迷因的应用程序。\n\n本 README 剩余部分的目录：\n\n- [迷因搜索](#meme-search)\n\n  - [功能](#features)\n  - [要求](#requirements)\n  - [安装说明](#installation-instructions)\n  - [首次生成\u002F下载模型所需时间](#time-to-first-generation--downloading-models)\n  - [索引你的迷因](#index-your-memes)\n  - [自定义应用端口](#custom-app-port)\n  - [使用 Docker 在本地构建应用](#building-the-app-locally-with-docker)\n  - [运行测试](#running-tests)\n- [Discord 服务器](#discord-server)\n- [更新日志](#changelog)\n- [功能请求与贡献](#feature-requests-and-contributing)\n\n\n## 迷因搜索\n\n### 功能\n\n\u003Cp align=\"center\">\n  \u003Cdiv style=\"display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;\">\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_8e7740784138.gif\" height=\"225\">\n      \u003Cfigcaption>搜索\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_b1da18ebcf2a.gif\" height=\"225\">\n      \u003Cfigcaption>编辑\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_3ae30ee0b179.gif\" height=\"225\">\n      \u003Cfigcaption>筛选\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_05a22f59cb4e.gif\" height=\"225\">\n      \u003Cfigcaption>生成\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_6b262f102e0b.gif\" height=\"225\">\n      \u003Cfigcaption>批量生成\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_07363310a07a.gif\" height=\"225\">\n      \u003Cfigcaption>暗色模式\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_706c1648887e.png\" height=\"225\">\n      \u003Cfigcaption>重新扫描\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_4e2e2cc7594b.png\" height=\"225\">\n      \u003Cfigcaption>重新扫描状态\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_41449936a5d9.png\" height=\"225\">\n      \u003Cfigcaption>重新扫描选项\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_40008198b9da.gif\" height=\"225\">\n      \u003Cfigcaption>拖放上传\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n  \u003C\u002Fdiv>\n\u003C\u002Fp>\n\n迷因搜索的功能包括：\n\n1. **多种图像转文本模型**\n\n   根据你的需求和资源选择合适的图像转文本模型——从小型（约 2 亿参数）到大型（约 20 亿参数）。\n\n   目前迷因搜索可用的图像转文本模型如下，以默认模型开始：\n\n   - [Florence-2-base](https:\u002F\u002Fhuggingface.co\u002Fmicrosoft\u002FFlorence-2-base) —— 微软开发的一系列流行的轻量级视觉语言模型，包括 2.5 亿参数的基础版和 7 亿参数的大版。\\*这是迷因搜索中使用的默认模型\\*。\n   - [Florence-2-large](https:\u002F\u002Fhuggingface.co\u002Fmicrosoft\u002FFlorence-2-large) —— Florence-2 系列中的 7 亿参数视觉语言模型变体。\n   - [SmolVLM-256](https:\u002F\u002Fhuggingface.co\u002Fcollections\u002FHuggingFaceTB\u002Fsmolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) —— Hugging Face 开发的 2.56 亿参数视觉语言模型。\n   - [SmolVLM-500](https:\u002F\u002Fhuggingface.co\u002Fcollections\u002FHuggingFaceTB\u002Fsmolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) —— Hugging Face 开发的 5 亿参数视觉语言模型。\n   - [Moondream2](https:\u002F\u002Fhuggingface.co\u002Fvikhyatk\u002Fmoondream2) —— 用于图像描述或提取图像文本的 20 亿参数视觉语言模型。\n   - [Moondream2-INT8](https:\u002F\u002Fhuggingface.co\u002Fvikhyatk\u002Fmoondream2) —— 针对内存受限硬件的 Moondream2 INT8 量化版本。可在几乎不损失质量的情况下将内存占用从约 5GB 降至 1.5–2GB，非常适合仅配备 CPU 的设备。\n\n2. **自动生成迷因描述**\n\n   可以针对特定迷因而非整个目录进行自动描述生成。\n\n3. **手动编辑迷因描述**\n\n   为了获得更好的搜索结果，可以手动编辑或添加描述；如果你不想等待自动生成功能，也可以直接进行操作。\n\n4. **标签**\n\n   为迷因创建、编辑并分配标签，以便更好地组织和筛选搜索结果。\n\n5. **快速向量搜索**\n\n   基于 Postgres 和 pgvector，享受更快速的关键词和向量搜索，同时优化数据库事务流程。\n\n6. **目录路径**\n\n   可以将迷因组织到多个子目录中，无需全部存储在一个文件夹内。\n\n7. **新的组织工具**\n\n   按标签、目录路径和描述嵌入进行筛选，并在关键词搜索和向量搜索之间切换，以实现更精细的控制。\n\n8. **批量描述生成**\n\n   可以一次性为多个迷因生成描述，从而加快索引速度。\n\n9. **暗色模式**\n\n   在任何环境下都能舒适浏览，可切换浅色和暗色主题。\n\n10. **目录重新扫描**\n\n    自动检测并索引你目录中新添加的迷因。\n\n11. **拖放上传**\n\n    通过网页界面支持拖放上传迷因。文件会存储在 `direct-uploads` 目录中（可通过 Docker 卷挂载进行配置），并自动扫描以进行索引。支持 JPG、PNG 和 WEBP 格式，可批量上传（最多 50 个文件），实时跟踪进度，并自动处理重复文件名问题。\n\n### 要求\n\n**对于 Docker 部署**（推荐）：\n- Docker 和 Docker Compose\n\n**对于本地开发**：\n- Ruby 3.4.2\n- Rails 8.0.4\n- Python 3.12\n- Node.js 20 LTS\n- PostgreSQL 17 并带有 pgvector 扩展\n\n我们建议使用 [mise](https:\u002F\u002Fmise.jdx.dev\u002F) 来管理 Ruby、Python 和 Node.js 的版本。详细设置说明请参阅 [CLAUDE.md](CLAUDE.md)。\n\n### 安装说明\n\n要启动应用，请拉取此仓库并使用 `docker-compose` 启动服务器集群：\n\n```sh\ndocker compose up\n```\n\n这将拉取并启动应用、数据库和自动描述生成器的容器。应用本身将在端口 `3000` 上运行，可通过以下地址访问：\n\n```sh\nhttp:\u002F\u002Flocalhost:3000\n```\n\n如果只想单独启动应用，请拉取仓库并进入 `meme_search\u002Fmeme_search\u002Fmeme_search_app` 目录。进入后，执行以下命令以在开发模式下启动应用：\n\n```sh\n.\u002Fbin\u002Fdev\n```\n\n执行此操作时，请确保本地已运行一个可用的 PostgreSQL 实例，且监听端口为 `5432`。\n\n**注意：Linux 用户**：为了实现容器间的通信，您可能需要在 `meme_search` 服务中添加以下 `extra_hosts` 配置：\n\n```sh\nextra_hosts:\n    - \"host.docker.internal:host-gateway\"\n```\n\n### 首次生成\u002F模型下载时间\n\n首次自动生成表情包描述所需的时间会比平时更长，因为此时需要下载并缓存图像转文本模型的权重。后续的生成速度会更快。\n\n您可以在应用的设置选项卡中下载其他模型。\n\n### 索引您的表情包\n\n您可以通过创建自己的描述或自动生成功能来索引您的表情包，如下所示。\n\n![自动生成功能示例](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_05a22f59cb4e.gif)\n\n要开始索引您自己的表情包，首先调整 [compose 文件](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fdocker-compose.yml)，在 `meme_search` 和 `image_to_text_generator` 服务中添加 `volume` 挂载，以便将您本地的表情包子目录正确连接到应用。\n\n例如，假设您的某个表情包目录名为 `new_memes`，位于您机器上的以下路径：`\u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes`。\n\n要将该子目录正确挂载到 `meme_search` 服务，需将其配置中的 `volumes` 部分调整为如下内容：\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- 示例仓库中的表情包目录\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Frails\u002Fpublic\u002Fmemes\u002Fnew_memes # \u003C-- 您的个人表情包集合，必须挂载到容器内的 \u002Frails\u002Fpublic\u002Fmemes 目录下\n```\n\n注意：您的 `new_memes` 目录必须挂载到容器内部的 `\u002Frails\u002Fpublic\u002Fmemes` 目录中，如上所示。\n\n同样，要将该子目录正确挂载到 `image_to_text_generator` 服务，需将其配置中的 `volumes` 部分调整为如下内容：\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- 示例仓库中的表情包目录\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\u002Fnew_memes # \u003C-- 您的个人表情包集合，必须挂载到容器内的 \u002Fapp\u002Fpublic\u002Fmemes 目录下\n...\n```\n\n注意：您的 `new_memes` 目录必须挂载到容器内部的 `\u002Fapp\u002Fpublic\u002Fmemes` 目录中，如上所示。\n\n如果您担心应用程序会修改您现有的表情包库，作为预防措施，您可以在卷挂载行中添加 `ro` 参数，使其变为只读模式，如下所示：\n\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes # \u003C-- 示例仓库中的表情包目录\n  - \u002Flocal\u002Fpath\u002Fto\u002Fmy\u002Fmemes\u002Fnew_memes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\u002Fnew_memes:ro\n...\n```\n\n现在重启应用，并通过 UI 注册 `new_memes` 目录，路径为：`设置 -> 路径 -> 创建新路径`，如下图所示。在提供的字段中输入 `new_memes` 并按回车键。\n\n![注册新表情包目录](https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_readme_3c2b68fcc6aa.webp)\n\n一旦在应用中注册成功，您的表情包就可以进行索引、打标签等操作了！\n\n### 模型下载\n\n用于自动生成表情包描述的图像转文本模型均为开源模型，且大小不一。\n\n### 自定义应用端口\n\n您可以轻松自定义应用的端口，以便更方便地与 [Unraid](https:\u002F\u002Funraid.net\u002F?srsltid=AfmBOorvWvSZbCHKnqdR__AcllotnsLR6did_FhAaNfUowqqU2IprD1v) 或 [Portainer](https:\u002F\u002Fwww.portainer.io\u002F) 等工具配合使用，或者是因为您已经在默认的 `meme_search` 应用端口 `3000` 上运行了其他服务。\n\n要自定义主应用端口，请在目录根目录下创建一个 `.env` 文件。在此文件中，您可以定义以下自定义环境变量，用于指定如何访问应用、图像转文本生成器和数据库。这些值如下：\n\n```sh\nAPP_PORT= # 应用的端口，默认为3000\n```\n\n该值会通过 `docker-compose-pro.yml` 文件自动检测并加载到各个服务中。\n\n### 使用 Docker 在本地构建应用\n\n**Docker 镜像仅支持手动构建**，没有针对发布版本或标签的自动化 CI 构建流程。\n\n要构建应用（包括 `docker-compose.yml` 文件中定义的所有服务），请在终端中运行本地的 compose 文件：\n\n```sh\ndocker compose -f docker-compose-local-build.yml up --build\n```\n\n对于多平台构建（AMD64 + ARM64）以及推送到 GitHub Container Registry 的操作，可以使用本地构建脚本：\n\n```sh\nbash scripts\u002Fbuild_and_push.sh\n```\n\n这将构建应用、数据库和自动描述生成器的 Docker 镜像，并在 `http:\u002F\u002Flocalhost:3000` 启动应用。\n\n### 运行测试\n\n要在本地运行测试，请拉取仓库并进入 `meme_search\u002Fmeme_search\u002Fmeme_search_app` 目录。安装所需的 gem 包：\n\n```sh\nbundle install\n```\n\n然后可以运行测试：\n\n```sh\nbash run_tests.sh\n```\n\n执行此操作时，请确保本地已运行一个可用的 PostgreSQL 实例，且监听端口为 `5432`。\n\n对 `\u002Fapp` 子目录运行代码风格检查：\n\n```sh\nrubocop app\n```\n\n以确保代码整洁且格式规范。\n\n#### 在本地运行 CI（可选）\n\n您可以通过 [act](https:\u002F\u002Fgithub.com\u002Fnektos\u002Fact) 在本地运行完整的 GitHub Actions CI 流程：\n\n```bash\n# 安装 act（macOS）\nbrew install act\n\n# 运行所有 CI 作业\nact --container-architecture linux\u002Famd64 -P ubuntu-latest=catthehacker\u002Fubuntu:act-latest\n\n# 运行特定作业\nact -j pro_app_unit_tests --container-architecture linux\u002Famd64 -P ubuntu-latest=catthehacker\u002Fubuntu:act-latest\n```\n\n这可以帮助您在推送到 GitHub 之前验证更改是否符合 CI 规范。\n\n#### Docker 端到端测试（仅限本地验证）\n\n**Docker 端到端测试会验证完整的微服务栈**（Rails + Python + PostgreSQL）在隔离的 Docker 容器中是否正常工作。这些测试基于全新的 Docker 构建，用于测试服务间的通信、Webhook 以及类似生产环境的部署。\n\n**当前状态**：7 项烟雾测试中有 6 项通过（覆盖率 85%）——详情请参阅 `playwright-docker\u002FREADME.md`。\n\n```bash\n# 运行所有 Docker 端到端测试\nnpm run test:e2e:docker\n\n# 使用 UI 模式运行（推荐用于调试）\nnpm run test:e2e:docker:ui\n```\n\n**这些测试涵盖的内容**：\n- 完整的图像处理流水线（Rails → Python → Rails Webhook）\n- 带有嵌入生成的向量搜索\n- 关键字搜索功能\n- 并发处理与任务队列\n- 嵌入刷新操作\n\n**重要提示**：由于 Docker 构建时间较长（约 10–15 分钟）以及资源需求，这些测试**不会在 CI 环境中运行**。**贡献者必须在本地运行这些测试**，然后再提交以下方面的 Pull Request：\n- Docker 配置\n- 跨服务通信\n- 图像转文本生成工作流\n- 嵌入生成\n\n请参阅 `playwright-docker\u002FREADME.md` 获取完整文档。\n\n## Discord 服务器\n\n加入我们的 Discord 服务器 [![Discord](https:\u002F\u002Fimg.shields.io\u002Fbadge\u002FDiscord-Join%20Server-7289da?style=flat&logo=discord&logoColor=white)](https:\u002F\u002Fdiscord.gg\u002FdamGu7aEHH)，讨论新功能、Bug 修复以及其他开源项目（例如 [ytgify](https:\u002F\u002Fchromewebstore.google.com\u002Fdetail\u002Fytgify\u002Fdnljofakogbecppbkmnoffppkfdmpfje)——一款可以直接从 YouTube 播放器截取 GIF 的浏览器扩展！）\n\n## 更改日志\n\nMeme Search 目前正处于积极开发中！请查看此仓库中的 `CHANGELOG.md` 文件，了解最近的更改记录。\n\n## 功能请求与贡献\n\n我们欢迎功能请求和贡献！\n\n请访问[此仓库的讨论区](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme_search\u002Fdiscussions)，提出您对功能改进的建议，并参与讨论或投票！\n\n有关贡献的基本规则，请参阅 `CONTRIBUTING.md` 文件。\n\n以下是使用 `gitdiagram` 生成的仓库结构图，清晰展示了其主要组件及相互关系：\n\n```mermaid\nflowchart TD\n    %% 全局实体\n    User[\"用户\"]:::user\n\n    %% Docker & Compose 编排\n    Docker[\"Docker & Compose 编排\"]:::docker\n\n    %% 主要服务\n    Rails[\"Rails Meme Search 应用程序\"]:::rails\n    Python[\"图像转文本生成器（Python）\"]:::python\n    DB[\"PostgreSQL 数据库（带 pgvector 插件）\"]:::database\n\n    %% 共享文件卷子图\n    subgraph \"共享模因文件\"\n        PublicMemes[\"公开模因\"]:::volume\n        MemeDir[\"模因目录\"]:::volume\n    end\n\n    %% 相互交互\n    User -->|\"交互\"| Rails\n    Rails -->|\"数据库查询更新\"| DB\n    Rails -->|\"API 请求\"| Python\n    Python -->|\"API 响应\"| Rails\n\n    %% 卷挂载访问\n    Rails ---|\"卷挂载访问\"| PublicMemes\n    Python ---|\"卷挂载访问\"| MemeDir\n\n    %% Docker 编排链接\n    Docker ---|\"编排\"| Rails\n    Docker ---|\"编排\"| Python\n    Docker ---|\"编排\"| DB\n\n    %% 点击事件\n    click Rails \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\"\n    click Python \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fimage_to_text_generator\"\n    click DB \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\u002Fconfig\u002Fdatabase.yml\"\n    click Docker \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002Fdocker-compose.yml\"\n    click PublicMemes \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmeme_search_app\u002Fpublic\u002Fmemes\"\n    click MemeDir \"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain\u002Fmeme_search\u002Fmemes\"\n\n    %% 样式定义\n    classDef user fill:#fceabb,stroke:#d79b00,stroke-width:2px;\n    classDef rails fill:#c8e6c9,stroke:#388e3c,stroke-width:2px;\n    classDef python fill:#bbdefb,stroke:#1976d2,stroke-width:2px;\n    classDef database fill:#ffe082,stroke:#f9a825,stroke-width:2px,stroke-dasharray: 5 5;\n    classDef docker fill:#d1c4e9,stroke:#673ab7,stroke-width:2px,stroke-dasharray: 3 3;\n    classDef volume fill:#ffcdd2,stroke:#e53935,stroke-width:2px,stroke-dasharray: 2 2;\n```","# Meme Search 快速上手指南\n\nMeme Search 是一个支持自托管的 AI 表情包搜索引擎，利用本地运行的视觉语言模型（VLM）自动提取图片中的文字和语义内容，并通过向量数据库实现高效的语义搜索。所有数据处理均在本地完成，无需上传云端。\n\n## 环境准备\n\n### 系统要求\n推荐使用 **Docker** 部署（最简单且隔离性好）。\n\n**前置依赖：**\n- Docker\n- Docker Compose\n\n**本地开发模式（可选，仅用于二次开发）：**\n- Ruby 3.4.2 + Rails 8.0.4\n- Python 3.12\n- Node.js 20 LTS\n- PostgreSQL 17 (需安装 `pgvector` 扩展)\n- 推荐工具：使用 [mise](https:\u002F\u002Fmise.jdx.dev\u002F) 管理多版本运行环境。\n\n> **注意**：首次运行时会自动下载 AI 模型权重（约几百 MB 到几 GB），请确保网络连接通畅。国内用户若遇到 HuggingFace 下载缓慢问题，建议配置镜像源或在宿主机预先下载模型映射到容器内。\n\n## 安装步骤\n\n### 1. 克隆项目\n```sh\ngit clone https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search.git\ncd meme-search\n```\n\n### 2. 启动服务\n使用 Docker Compose 一键启动应用、数据库及 AI 生成器服务：\n```sh\ndocker compose up\n```\n*注：首次启动时，系统会拉取镜像并下载默认的图像转文本模型（Florence-2-base），耗时取决于网络状况。*\n\n### 3. 访问应用\n服务启动完成后，在浏览器中访问：\n```\nhttp:\u002F\u002Flocalhost:3000\n```\n\n### 4. 自定义端口（可选）\n如果 3000 端口被占用，可在项目根目录创建 `.env` 文件指定端口：\n```sh\necho \"APP_PORT=8080\" > .env\ndocker compose up\n```\n\n## 基本使用\n\n### 第一步：挂载表情包目录\n为了索引你本地的表情包，需要修改 `docker-compose.yml` 文件，将本地文件夹映射到容器内部。\n\n假设你的表情包存放在 `\u002Fhome\u002Fuser\u002Fmy_memes`，请按以下方式修改 `volumes` 配置：\n\n**对于 `meme_search` 服务：**\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\n  - \u002Fhome\u002Fuser\u002Fmy_memes:\u002Frails\u002Fpublic\u002Fmemes\u002Fmy_memes\n```\n\n**对于 `image_to_text_generator` 服务：**\n```yaml\nvolumes:\n  - .\u002Fmeme_search\u002Fmemes\u002F:\u002Fapp\u002Fpublic\u002Fmemes\n  - \u002Fhome\u002Fuser\u002Fmy_memes:\u002Fapp\u002Fpublic\u002Fmemes\u002Fmy_memes\n```\n> **关键点**：容器内的路径必须分别位于 `\u002Frails\u002Fpublic\u002Fmemes` 和 `\u002Fapp\u002Fpublic\u002Fmemes` 下，且子目录名称（如 `my_memes`）需保持一致。若担心数据被修改，可在路径后添加 `:ro` 设为只读。\n\n修改配置后重启容器：\n```sh\ndocker compose down\ndocker compose up\n```\n\n### 第二步：注册目录\n1. 登录 Web 界面 (`http:\u002F\u002Flocalhost:3000`)。\n2. 进入 **Settings** (设置) -> **Paths** (路径)。\n3. 点击 **Create New**，输入刚才映射的子目录名称（例如 `my_memes`），按回车确认。\n\n### 第三步：生成描述与搜索\n- **自动生成**：系统会自动扫描新目录，利用 AI 模型为表情包生成文字描述和标签。你可以在界面上看到生成进度。\n- **手动编辑**：点击任意表情包，可手动修正描述或添加自定义标签（Tags）以优化搜索结果。\n- **语义搜索**：在搜索框输入自然语言（如“一只悲伤的猫”或“关于加班的梗图”），系统将基于向量相似度返回结果，而不仅仅是匹配文件名。\n- **拖拽上传**：支持直接将图片拖入网页进行上传（文件将保存至 `direct-uploads` 目录并自动索引）。\n\n### 高级功能提示\n- **切换模型**：在设置中可根据硬件性能切换不同的视觉模型（如显存较小可选择 `Moondream2-INT8` 或 `SmolVLM` 系列）。\n- **批量操作**：支持批量重新生成描述或重新扫描目录以同步新增文件。\n- **深色模式**：界面右上角可切换深色\u002F浅色主题。","某社区运营团队需要管理数万张历史积累的梗图（Meme），以便在社交媒体热点出现时能迅速找到匹配素材进行响应。\n\n### 没有 meme-search 时\n- **检索效率极低**：只能依靠人工记忆或按文件名查找，面对海量图片库，找一张特定主题的梗图往往需要花费半小时以上翻找文件夹。\n- **内容无法识别**：图片内的文字信息未被提取，无法通过搜索图中的“关键台词”或“具体情节”来定位图片，导致大量优质素材沉睡。\n- **语义匹配缺失**：无法理解图片的深层含义，例如搜索“尴尬的沉默”无法关联到画面中人物面面相觑但无文字说明的图片。\n- **隐私与成本顾虑**：若使用在线 AI 服务批量处理图片，不仅面临高昂的 API 调用费用，还存在将内部素材上传至第三方服务器的数据泄露风险。\n\n### 使用 meme-search 后\n- **秒级精准定位**：利用本地部署的 AI 模型建立索引，运营人员输入关键词即可在毫秒级时间内从万张图片中锁定目标，响应速度提升百倍。\n- **图文双重索引**：meme-search 自动提取图片内文字并结合视觉内容进行向量化，无论是搜台词还是搜画面描述，都能准确召回相关结果。\n- **智能语义理解**：基于大模型的语义搜索能力，即使不记得具体文字，仅描述“想表达无奈但好笑”的场景，也能智能推荐最贴切的梗图。\n- **安全低成本运行**：所有图像转文本、向量嵌入及搜索过程均在本地 Docker 容器中完成，无需联网上传数据，既保护了素材隐私又节省了云端算力开支。\n\nmeme-search 通过将非结构化的图片库转化为可语义交互的智能资产，让创意团队从繁琐的文件管理中解放出来，真正实现“梗随心动”。","https:\u002F\u002Foss.gittoolsai.com\u002Fimages\u002Fneonwatty_meme-search_f45dc492.png","neonwatty","Jeremy Watt","https:\u002F\u002Foss.gittoolsai.com\u002Favatars\u002Fneonwatty_7c15cfaa.jpg",null,"www.neonwatty.com","https:\u002F\u002Fgithub.com\u002Fneonwatty",[80,84,88,92,96,100,104,108],{"name":81,"color":82,"percentage":83},"HTML","#e34c26",27.9,{"name":85,"color":86,"percentage":87},"Ruby","#701516",24.4,{"name":89,"color":90,"percentage":91},"TypeScript","#3178c6",23.9,{"name":93,"color":94,"percentage":95},"Python","#3572A5",16.3,{"name":97,"color":98,"percentage":99},"Shell","#89e051",3.4,{"name":101,"color":102,"percentage":103},"JavaScript","#f1e05a",3.3,{"name":105,"color":106,"percentage":107},"Dockerfile","#384d54",0.5,{"name":109,"color":110,"percentage":111},"CSS","#663399",0.4,656,24,"2026-04-17T03:51:55","Apache-2.0","Linux, macOS, Windows","非必需。支持 CPU 运行（推荐使用 Moondream2-INT8 模型，显存需求约 1.5-2GB）。若使用较大模型（如 Moondream2 全精度），可能需要约 5GB 显存。未指定具体 CUDA 版本。","最低约 2GB (使用量化模型且仅 CPU)，推荐 8GB+ 以流畅运行较大模型及数据库服务",{"notes":120,"python":121,"dependencies":122},"推荐使用 Docker Compose 部署。核心功能包括图像转文本（支持 Florence-2, SmolVLM, Moondream2 等模型）、向量搜索和本地处理。首次运行需下载模型权重，耗时较长。可通过挂载卷配置本地表情包目录。Linux 用户可能需要在 Docker 配置中添加 extra_hosts 以解决容器间通信问题。建议使用 mise 管理语言环境版本。","3.12",[123,124,125,126,127,128],"Ruby 3.4.2","Rails 8.0.4","Node.js 20 LTS","PostgreSQL 17 (with pgvector)","Docker","Docker Compose",[14,16,13,15],[131,132,133,134,135,136,137,138],"machine-learning","vector-database","self-hosted","docker","ai","meme","semantic-search","homelab","2026-03-27T02:49:30.150509","2026-04-19T03:07:52.576929",[142,147,152,157,162,166,171],{"id":143,"question_zh":144,"answer_zh":145,"source_url":146},41233,"如何正确配置 Docker 卷挂载路径以便在 GUI 中识别？","容器内的挂载路径与 GUI 中的显示路径存在映射关系。例如，如果在 docker-compose 文件中将本地目录挂载到容器内的 `\u002Frails\u002Fpublic\u002Fmemes`，那么在 GUI 设置中对应的子路径应为 `\u002Fpublic\u002Fmemes`。\n\n具体示例：\n1. Compose 文件配置：`- .\u002Fmeme_search_pro\u002Fmemes\u002F:\u002Frails\u002Fpublic\u002Fmemes`\n2. 若添加新目录 `my_memes`，容器内完整路径为 `\u002Frails\u002Fpublic\u002Fmemes\u002Fmy_memes`。\n3. 在 GUI 中添加路径时，应填写 `\u002Fpublic\u002Fmemes\u002Fmy_memes`。\n\n注意：GUI 路径去掉了容器根目录 `\u002Frails` 前缀，直接对应 `public` 目录下的结构。","https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fissues\u002F104",{"id":148,"question_zh":149,"answer_zh":150,"source_url":151},41234,"点击“刷新索引”时报错“unable to open database file”如何解决？","该错误通常是因为缺少必要的数据库文件或数据目录未正确初始化。解决方案如下：\n1. 确保在部署前已从代码仓库克隆或复制了 `data` 目录到项目文件夹中。\n2. 默认情况下，Docker 镜像不包含预建的数据库文件，需要手动准备。\n3. 检查挂载卷权限，确保容器有权读写 `\u002Fhome\u002Fdata` 及其子目录。\n\n如果使用的是纯 Docker Compose 部署（未克隆源码），请手动创建并初始化数据目录，或参考文档将默认的 `data` 目录内容复制到挂载卷中。","https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fissues\u002F28",{"id":153,"question_zh":154,"answer_zh":155,"source_url":156},41235,"添加新表情包后是否需要重新构建整个索引？如何自动更新？","不需要重新构建整个索引。从最新版本开始，应用支持增量更新：\n1. **手动更新**：点击 Web 界面中的“Refresh Index”（刷新索引）按钮。该操作只会添加新图片或移除已删除的图片，不会重建整个数据库。\n2. **自动上传**：版本 2.0.1 及以上支持拖拽上传功能，可直接通过界面添加新图。\n3. **全量生成**：如果需要为所有图片生成描述，可以使用“Index All”功能。\n\n此前建议的 cron 定时任务或 inotifywait 监控方案已被内置的刷新按钮取代，更加用户友好。","https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fissues\u002F116",{"id":158,"question_zh":159,"answer_zh":160,"source_url":161},41236,"首次部署 Pro 版本容器时启动失败并报“RecordNotFound”错误怎么办？","这是一个已知的首次部署初始化问题。如果在 Portainer 或其他环境中首次启动 `meme_search_pro` 容器时遇到 `ActiveRecord::RecordNotFound: Couldn't find ImageCore with 'id'=1` 错误并退出：\n\n**解决方法**：\n无需修改配置，只需**重新部署（重启）容器一次**。第二次启动时，数据库种子数据（seeds）通常能正确加载，容器即可正常启动。\n\n此问题在多台主机上均可能出现，属于初始化竞态条件，重试即可解决。","https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fissues\u002F113",{"id":163,"question_zh":164,"answer_zh":165,"source_url":146},41237,"如何实现只读（RO）挂载外部表情包目录而不赋予写权限？","项目支持索引只读数据卷。虽然早期文档不够清晰，但现在可以通过以下方式实现：\n1. 在 Docker Compose 的 volumes 配置中，将外部目录以只读模式挂载到容器内（例如添加 `:ro` 后缀）。\n2. 确保挂载点指向正确的容器内部路径（参考 `\u002Frails\u002Fpublic\u002Fmemes` 结构）。\n3. 应用仅读取图片文件进行索引和描述生成，不需要对源图片目录进行写入操作。\n\n维护者已在 README 和 compose 文件注释中更新了相关说明，明确支持此类只读挂载场景。",{"id":167,"question_zh":168,"answer_zh":169,"source_url":170},41238,"桌面端是否有网格视图（Grid View）来同时查看多个表情包？","是的，该功能已实现。针对用户提出的“希望在桌面端以网格视图查看多个表情包”的需求，维护者已在后续更新中（通过 PR #73）添加了网格视图功能。\n\n现在您可以在桌面浏览器中使用网格布局浏览表情包库，提升浏览效率。请确保您的应用版本已更新至包含此功能的最新版本。","https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fissues\u002F55",{"id":172,"question_zh":173,"answer_zh":174,"source_url":156},41239,"是否支持深色模式（Dark Mode）？","支持。在最新发布的版本中，应用已经增加了深色\u002F浅色模式切换功能。\n\n您可以在界面设置或主题选项中找到切换开关，根据喜好选择深色模式以获得更好的夜间浏览体验。",[176,181,186,191,196,201,206],{"id":177,"version":178,"summary_zh":179,"released_at":180},333200,"v2.0.2","## 变更内容\n* 功能\u002F添加 Discord 社区链接，由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F140 中完成\n* 更新 README.md，加入 Discord 服务器徽章，由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F141 中完成\n* 更新 README.md，由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F142 中完成\n* 更新 Discord 链接，并在 CI 中添加链接有效性验证，由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F143 中完成\n* 修复图片转文本服务在处理无效图片时卡死的问题，由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F145 中完成\n\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fcompare\u002F2.0.0...v2.0.2","2026-01-09T17:58:46",{"id":182,"version":183,"summary_zh":184,"released_at":185},333201,"2.0.1","## 变更内容\n* @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F136 中添加了拖放上传图片的功能\n* @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F138 中修复了 Docker 构建中 VERSION 文件的可见性问题\n\n全新拖放上传功能的 GIF 动图！\n\n \u003Cp>\n   \u003Cdiv>\n    \u003Cfigure>\n      \u003Cimg align=\"center\" src=\"https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Freadme_gifs\u002Fblob\u002Fmain\u002Fuploads-trimmed.gif\" height=\"225\">\n\u003Cfigcaption>拖放上传\u003C\u002Ffigcaption>\n    \u003C\u002Ffigure>\n  \u003C\u002Fdiv>\n\u003C\u002Fp>\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fcompare\u002F2.2.0...2.0.1","2025-11-19T13:21:50",{"id":187,"version":188,"summary_zh":189,"released_at":190},333202,"2.0.0","## 变更内容\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F100 中更新\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F102 中更新 README.md\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F103 中删除 meme_search_walkthrough.ipynb\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F105 中更新 README.md\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F106 中更新 README，以澄清挂载路径，并在生产 Compose 文件中添加了类似注释\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F110 中进行首次推送——清理——将 standard 移至 legacy\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F112 中更新 README.md\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F114 中简化容器间的网络配置\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F115 中更新 README.md\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F119 中修复测试\u002FRails 8 单元测试问题\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F121 中从 README 中移除“版本 2.0 新增内容”部分\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F122 中修复 ARM64 Docker 构建卡顿问题：移除 Ruby 平台并修复 bundle 作业\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F123 中为发布配置构建工作流，并延长超时时间\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F124 中添加构建脚本，并更新 docker-compose 以使用新的镜像名称\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F125 中禁用自动化 CI 构建\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F127 中实现暗色\u002F亮色模式切换功能\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F126 中添加测试模型增强及批量描述生成计划\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F128 中实现自动扫描端到端测试功能\n* 由 @neonwatty 在 https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fpull\u002F130 中实现批量生成功能\n\n\n## 新功能展示\n\n- 批量生成\n\n![meme-search-bulk](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Fc75f6203-8c98-4341-a174-6588e3b11850)\n\n- 暗色\u002F亮色模式\n\n![meme-search-dark-mode](https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F04e316e5-f448-4890-b311-84486b17f84c)\n\n- 手动与自动路径扫描\n\n\u003Cimg width=\"588\" height=\"536\" alt=\"截图 2025-11-11 上午9:32:26\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002Feed490e0-74d2-4cad-abdf-4dd63740ac5a\" \u002F>\n\n\u003Cimg width=\"613\" height=\"622\" alt=\"截图 2025-11-11 上午9:32:20\" src=\"https:\u002F\u002Fgithub.com\u002Fuser-attachments\u002Fassets\u002F3deee3c9-db2b-4fed-8fdd-6249453287c0\" \u002F>\n\n\n**完整变更日志**: https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fcompare\u002Fv1.1.5...2.2.0","2025-11-13T21:32:49",{"id":192,"version":193,"summary_zh":194,"released_at":195},333203,"v1.1.5","# Meme Search v 1.1.5 发行说明\n\n更新日期：2025年2月20日\n\n对专业版应用进行了重大更新和体验优化，新增了图文转换模型、改进了用户界面，并升级了本地构建与测试功能，具体包括：\n\n**体验优化：**\n- 应用服务的 Docker 镜像大小缩减至原来的十分之一\n- 更轻松地为本地 NAS、Portainer、Unraid 等环境进行自定义配置，现已支持通过新启用的[自定义主机名和端口](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain?tab=readme-ov-file#custom-hosts-and-ports)功能\n- 新增一款更小（200MB，比之前小十倍）的前沿默认图文转换模型，可在大多数设备上实现更快的本地处理速度\n\n\n**新增图文转换模型：**\n- 新增4款前沿的[图文转换模型](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search?tab=readme-ov-file#features---pro-version)，参数量从2亿到20亿不等\n- Moondream2 更新至 2.0 版本\n\n\n**用户界面改进：**\n- 在设置中新增模型选择面板，可随时切换图文转换模型（如下图所示）\n\n\u003Cp align=\"center\">\n\u003Cimg align=\"center\" src=\"https:\u002F\u002Fgithub.com\u002Fjermwatt\u002Freadme_gifs\u002Fblob\u002Fmain\u002Fmeme-search-model-selection-screen-demo.webp\" height=\"225\">\n\u003C\u002Fp>\n\n- 在首页和搜索页面新增“网格视图”，以便更全面地浏览您的模因内容（如下图所示）\n\n\u003Cp align=\"center\">\n\u003Cimg align=\"center\" src=\"https:\u002F\u002Fgithub.com\u002Fjermwatt\u002Freadme_gifs\u002Fblob\u002Fmain\u002Fmeme-search-grid-view-medium.webp\" height=\"225\">\n\u003C\u002Fp>\n\n\n**本地构建与测试优化：**\n- 新增用于本地构建和测试的 Compose 文件 `docker-compose-pro-local-build.yml`\n- 为图文转换服务添加了新的测试数据库，以支持更全面的测试\n- 新增[本地 Docker Compose 文件](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Ftree\u002Fmain?tab=readme-ov-file#building-the-app-locally-with-docker)，使本地构建和测试更加便捷\n- 重构了 GitHub Actions 的测试与构建脚本，以简化（本地）测试流程\n\n\n有关更新和错误修复的更多详细信息，请参阅 [README.md](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002FREADME.md) 和 [CHANGELOG.md](https:\u002F\u002Fgithub.com\u002Fneonwatty\u002Fmeme-search\u002Fblob\u002Fmain\u002FCHANGELOG.md)。","2025-02-20T17:34:40",{"id":197,"version":198,"summary_zh":199,"released_at":200},333204,"v1.1.4","全新专业版 1.0 发布！\r\n\r\nMeme Search 专业版新增以下功能：\n\n1.  **自动生成表情包描述**\n\n    可以针对特定的表情包自动生成功能描述（而不必对整个目录生效）。\n\n2.  **手动编辑表情包描述**\n\n    您可以手动编辑或添加描述，以获得更精准的搜索结果；如果您不想等待自动生成功能，也可以随时自行操作。\n\n3.  **标签功能**\n\n    为表情包创建、编辑和分配标签，以便更好地进行分类和搜索筛选。\n\n4.  **更快的向量搜索**\n\n    基于 Postgres 和 pgvector 引擎，通过优化的数据库事务，实现更快速的关键词和向量搜索。\n\n5.  **关键词搜索**\n\n    专业版在语义\u002F向量搜索的基础上，新增了传统的关键词搜索功能。\n\n6.  **目录路径支持**\n\n    您可以将表情包组织到多个子目录中，无需全部存放在一个文件夹内。\n\n7.  **全新管理工具**\n\n    支持按标签、目录路径和描述嵌入向量进行筛选，并可在关键词搜索和向量搜索之间自由切换，为您提供更灵活的控制方式。","2024-11-08T15:12:59",{"id":202,"version":203,"summary_zh":204,"released_at":205},333205,"v1.1.3","- 在 compose 文件中添加了在 Docker 容器内使用 Nvidia GPU 的支持，并由 @thijsvanloef 进行了其他有益的清理工作。  \n- 现在，用于 docker build 和 docker-compose 的新操作会默认从 ghcr 仓库拉取镜像，这要感谢 @jasonyang-ee 的贡献。  \n- 由于 @StroescuTheo 提交的分阶段构建优化，Docker 镜像的大小大约减少了一半。","2024-07-24T15:29:30",{"id":207,"version":208,"summary_zh":209,"released_at":210},333206,"1.1.2","- 新增了一个“刷新索引”按钮，用于在数据\u002F输入图像目录中添加或移除图片时更新索引，仅影响新添加或移除的图片。\n\n\u003Cp align=\"center\">\n\u003Cimg align=\"center\" src=\"https:\u002F\u002Fgithub.com\u002Fjermwatt\u002Freadme_gifs\u002Fblob\u002Fmain\u002Fmeme_search_refresh_button.gif\" height=\"200\">\n\u003C\u002Fp>\n\n- 为查询模块和图片模块添加了核心测试，并增加了对新增图片重新索引以及移除图片后重新索引的功能测试。","2024-07-19T03:13:59"]