{"id":22504900,"url":"https://github.com/neonwatty/meme-search","last_synced_at":"2025-05-15T18:06:19.012Z","repository":{"id":243442220,"uuid":"812434636","full_name":"neonwatty/meme-search","owner":"neonwatty","description":"The open source Meme Search Engine and Finder.  Free and built to self-host locally with Python, Ruby, and Docker.","archived":false,"fork":false,"pushed_at":"2025-03-31T13:38:07.000Z","size":15485,"stargazers_count":534,"open_issues_count":5,"forks_count":23,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-04-08T06:34:43.480Z","etag":null,"topics":["docker","machine-learning","python","ruby-on-rails","self-hosted","vector-database","vision-language-model"],"latest_commit_sha":null,"homepage":"https://neonwatty.github.io/meme-search","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/neonwatty.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2024-06-08T22:08:51.000Z","updated_at":"2025-04-07T08:06:12.000Z","dependencies_parsed_at":"2024-07-20T00:13:33.487Z","dependency_job_id":"b6827bc8-4fa0-4b7a-b526-9681258bec8e","html_url":"https://github.com/neonwatty/meme-search","commit_stats":null,"previous_names":["jermwatt/meme_search","neonwatty/meme_search","neonwatty/meme-search"],"tags_count":5,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonwatty%2Fmeme-search","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonwatty%2Fmeme-search/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonwatty%2Fmeme-search/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/neonwatty%2Fmeme-search/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/neonwatty","download_url":"https://codeload.github.com/neonwatty/meme-search/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254394719,"owners_count":22063984,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["docker","machine-learning","python","ruby-on-rails","self-hosted","vector-database","vision-language-model"],"created_at":"2024-12-07T00:11:05.787Z","updated_at":"2025-05-15T18:06:19.007Z","avatar_url":"https://github.com/neonwatty.png","language":"Ruby","funding_links":[],"categories":["By Language","Ruby","ai","Software"],"sub_categories":["Ruby","Search Engines"],"readme":"# A Meme Search Engine built to self-host in Python, Ruby, and Docker\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\"\u003e\n\u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-pro-search-example.gif\" height=\"325\"\u003e\n\u003c/p\u003e\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  - [Installation instructions](#installation-instructions)\n  - [Time to first generation / 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\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\"\u003e\n  \u003cdiv style=\"display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;\"\u003e\n    \u003cfigure\u003e\n      \u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-pro-search-example.gif\" height=\"225\"\u003e\n      \u003cfigcaption\u003eSearch\u003c/figcaption\u003e\n    \u003c/figure\u003e\n    \u003cfigure\u003e\n      \u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-pro-edit-example.gif\" height=\"225\"\u003e\n      \u003cfigcaption\u003eEdit\u003c/figcaption\u003e\n    \u003c/figure\u003e\n    \u003cfigure\u003e\n      \u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-pro-filters-example.gif\" height=\"225\"\u003e\n      \u003cfigcaption\u003eFilter\u003c/figcaption\u003e\n    \u003c/figure\u003e\n    \u003cfigure\u003e\n      \u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-generate-example.gif\" height=\"225\"\u003e\n      \u003cfigcaption\u003eGenerate\u003c/figcaption\u003e\n    \u003c/figure\u003e\n  \u003c/div\u003e\n\u003c/p\u003e\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 / 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://huggingface.co/microsoft/Florence-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://huggingface.co/microsoft/Florence-2-large) - the 700 Million parameter vision language model variant of the Florence-2 series\n   - [SmolVLM-256](https://huggingface.co/collections/HuggingFaceTB/smolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) - a 256 Million parameter vision language model built by Hugging Face\n   - [SmolVLM-500](https://huggingface.co/collections/HuggingFaceTB/smolvlm-256m-and-500m-6791fafc5bb0ab8acc960fb0) - a 500 Million parameter vision language model built by Hugging Face\n   - [Moondream2](https://huggingface.co/vikhyatk/moondream2) - a 2 Billion parameter vision language model used for image captioning / extracting image text\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\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://localhost:3000\n```\n\nTo start the app alone pull the repo and cd into the `meme_search/meme_search_pro/meme_search_app`. Once there execute the following to start the app in development mode\n\n```sh\n./bin/dev\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_pro` service for inter-container communication\n\n```sh\nextra_hosts:\n    - \"host.docker.internal:host-gateway\"\n```\n\n### Time to first generation / 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://github.com/jermwatt/readme_gifs/blob/main/meme-search-generate-example.gif\" height=\"225\"\u003e\n\nTo start indexing your own memes, first adjust the [compose file](https://github.com/neonwatty/meme-search/blob/main/docker-compose.yml) by adding `volume` mount to the `meme_search_pro` 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: `/local/path/to/my/memes/new_memes`.\n\nTo properly mount this subdirectory to the `meme_search_pro` service adjust the `volumes` portion of its configuration to the following:\n\n```yaml\nvolumes:\n  - ./meme_search_pro/memes/:/app/public/memes # \u003c-- example meme directory from the repository\n  -  /route/to/my/personal/additional_memes/:/rails/public/memes/additional_memes # \u003c-- personal meme collection - must be placed inside /rails/public/memes in the container\n```\n\nNote: your `additional_memes` directory must be mounted internally in the `/rails/public/memes` 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  - ./meme_search_pro/memes/:/app/public/memes # \u003c-- example meme directory from the repository\n  -  /route/to/my/personal/additional_memes/:/app/public/memes/additional_memes # \u003c-- personal meme collection - must be placed inside /app/public/memes in the container\n...\n```\n\nNote: your `additional_memes` directory must be mounted internally in the `/app/public/memes` directory, as shown above.\n\nNow restart the app, and register the `additional_memes` via the UX by traversing to the `settings -\u003e paths -\u003e create new` as illustrated below.  Type in `additional_memes` in the field provided and press `enter`.\n\n\u003cimg align=\"center\" src=\"https://github.com/jermwatt/readme_gifs/blob/main/meme-search-add-new-memes.webp\" height=\"225\"\u003e\n\nOnce registered in the app, your memes are ready for indexing / tagging / 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://unraid.net/?srsltid=AfmBOorvWvSZbCHKnqdR__AcllotnsLR6did_FhAaNfUowqqU2IprD1v) or [Portainer](https://www.portainer.io/), or because you already have services running on the default `meme_search_pro` 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\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\nThis will build the docker images for the app, database, and auto description generator, and start the app at `http://localhost:3000`.\n\n### Running tests\n\nTo run tests locally pull the repo and cd into the `meme_search/meme_search_pro/meme_search_app` directory. Install the requird 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 `/app` subdirectory as\n\n```sh\nrubocop app\n```\n\nto ensure the code is clean and well formatted.\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://github.com/neonwatty/meme_search/discussions) for suggested enhancements to contribute to / 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://github.com/ahmedkhaleel2004/gitdiagram), laying out its main components and interactions.\n\n```mermaid\nflowchart TD\n    %% Global Entities\n    User[\"User\"]:::user\n\n    %% Docker \u0026 Compose Orchestration\n    Docker[\"Docker \u0026 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 --\u003e|\"interaction\"| Rails\n    Rails --\u003e|\"DBQueryUpdate\"| DB\n    Rails --\u003e|\"APIRequest\"| Python\n    Python --\u003e|\"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://github.com/neonwatty/meme-search/tree/main/meme_search_pro/meme_search_app\"\n    click Python \"https://github.com/neonwatty/meme-search/tree/main/meme_search_pro/image_to_text_generator\"\n    click DB \"https://github.com/neonwatty/meme-search/blob/main/meme_search_pro/meme_search_app/config/database.yml\"\n    click Docker \"https://github.com/neonwatty/meme-search/blob/main/docker-compose.yml\"\n    click PublicMemes \"https://github.com/neonwatty/meme-search/tree/main/meme_search_pro/meme_search_app/public/memes\"\n    click MemeDir \"https://github.com/neonwatty/meme-search/tree/main/meme_search_pro/memes\"\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","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneonwatty%2Fmeme-search","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fneonwatty%2Fmeme-search","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fneonwatty%2Fmeme-search/lists"}