Self-hosted service
MemeMeow-Studio/MemeMeow avatar
MemeMeow-Studio/MemeMeow

MemeMeow: finding a reaction image by describing the feeling

MemeMeow 是一个基于自然语言的表情包检索工具。基于agent自动标注表情包含义,只需描述想要的场景或心情,快速找到合适的表情包。

1,262 stars38 forksPythonAGPL-3.0

At a glance

What is it?
MemeMeow is a FastAPI and Vue 3 application that indexes a library of reaction images with text embeddings and a local DINOv2 model, so a search for a mood or a situation returns pictures instead of filenames. The labelling is done by an OpenCode agent, and the whole stack runs under Docker Compose with PostgreSQL and pgvector.
Who is it for?
Adopt MemeMeow if you are building a chat client, a bot or a community tool that needs to pick a reaction image from a described mood, and you are willing to run Docker, PostgreSQL with pgvector and a local vision model. Do not adopt it if you need image generation rather than retrieval, or if you need the tagging to be deterministic and reviewable, since the labels are produced by a model and the project warns that the results are generated by AI.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
Is it still maintained?
Yes. The repository last received commits 11 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Searching for a feeling instead of a filename

MemeMeow is a natural language retrieval tool for reaction images. The premise is simple and slightly unusual: instead of organising a library of stickers by filename or by hand-written tags, you describe the situation you want to express and the system returns images that fit. The README gives the everyday examples of searching for helplessness and for a tired commuter on a morning, and the mechanism behind it is an embedding model that turns your sentence and the images into a shared vector space, so a question-and-answer style query returns matching pictures. The point is stated plainly: you do not need to remember the exact file name or a fixed set of labels. The result of that design is that the hard part of a sticker library, which is the metadata, is generated for you. The project runs a Vue 3 web interface over a unified API, is packaged as an image search workbench with FastAPI and Vue, and is published under the GNU Affero General Public License version 3 or later. There is also a hosted instance at mememeow.cc that you can use in a browser without deploying anything, with downloads for Windows, Android, macOS and Linux.

Two embedding spaces, one for meaning and one for looks

The retrieval design uses two different representations, and the distinction is the technically interesting part of the project. The first is a text embedding, which is what makes the question-and-answer search work: a sentence about a mood is mapped close to the sentences that describe images with that mood. The second is a visual embedding from a local DINOv2 model, which is used for visual nearest-neighbour search, that is, finding images that look like each other rather than images that mean the same thing. DINOv2 is not a hosted API here, it is a set of weights you download and run yourself, which is why the deployment steps include fetching the model file. The upload path is where the two meet. When you upload an image you can choose a direct upload, in which case a text vector is generated from the file name and a visual vector is generated from the image, with a background step attempting to rename the file based on its content and updating the text vector once a usable name exists. The README is honest about the failure mode: if the file name is a meaningless hash and there is no other usable text, the text vector waits for a valid name while the visual vector is still produced. That is a design that degrades in a defined way rather than indexing garbage.

The agent does the annotating, and you can watch it fail

The other upload mode is full analysis, where an agent runs over the image and produces its source, usage and meaning, generating the context and description used for retrieval, along with the vectors needed to find it. The project uses a built-in OpenCode agent for this, and the README says the whole point of the mode is that you do not have to categorise and tag stickers by hand. Two options can be configured for that batch. One is a reverse image search strategy, which allows the agent to use Google to search for the image when it cannot make sense of it, to recover the source and background. The other is auto-naming, which allows a generated file name based on the image content. The design consequence is that the labelling is probabilistic, and the project does not hide that. The library view shows a status icon per image for each background task, such as visual vectorisation, metadata extraction and text vector generation, so you can tell whether a stage succeeded or failed, and you can select the failures and press a retry button to push them back onto the task queue. A separate tasks view lists the long-running background records, with a filter by task type and execution status, and a detail drawer that shows the individual steps and the error log. That level of visibility is what you need when a model is doing the indexing.

Four containers, a Postgres with pgvector and a model download

MemeMeow is a container-first project and says so, requiring Docker Engine 28 or newer and the Compose v2 plugin. The deployment starts with the clone and the environment file, and the scripts use uv to synchronise the environment:

bash
git clone https://github.com/MemeMeow-Studio/MemeMeow.git
cd MemeMeow

uv run python -m scripts.sync_env

You then edit the .env file with the model configuration, specifically MEMEMEOW_OPENCODE_BASE_URL and MEMEMEOW_OPENCODE_API_KEY, which are what the agent uses to process image context. The start command brings up the stack:

bash
./start.sh start

which launches PostgreSQL with pgvector, the agent executor, the visual service and the backend API container, and the interface is then at http://127.0.0.1:8275/. The visual model is not part of the image, so it has to be fetched separately:

bash
mkdir -p data/models
curl -L --fail --output data/models/dinov2_vitb14_pretrain.pth \
  https://dl.fbaipublicfiles.com/dinov2/dinov2_vitb14/dinov2_vitb14_pretrain.pth

The day to day commands are the same script with a subcommand, with status, logs, a follow mode for the main backend and a stop that shuts the services down without losing data. The compose file shows how the pieces fit: a pgvector/pgvector:pg16 database with a health check, an init service that runs alembic upgrade head, a runtime init service that sets the non-root user and group identifiers the containers run as, and a db-viewer service behind a profile so it only starts when you ask for it.

The API is the product surface, and the search endpoint is simple

The README makes a point of framing MemeMeow as an API-driven service, and gives the endpoint contract directly. The search endpoint is a POST to the local server on port 8275 with a JSON body carrying a query string, a result count and a boolean that toggles whether the query is enhanced by a language model, and the response is a JSON object with a results array of media paths. The project notes that the official hosted API is still in development while welcoming discussion of use cases through issues or the community chat. The engineering underneath is a fairly standard modern Python stack, and the dependency list says a lot about the shape of the service. FastAPI and uvicorn serve the API, SQLAlchemy with psycopg and Alembic handle the database, pgvector provides the vector search, pydantic-settings and python-dotenv handle configuration, Pillow and numpy handle images, the openai client and google-auth cover the model access, and there is a full OpenTelemetry stack pinned to specific versions with instrumentation for FastAPI, httpx, requests, urllib, SQLAlchemy and threading. The Dockerfile builds the Vue frontend in a node stage and the service in a python:3.12-slim stage that runs as a non-root user and starts uvicorn on 0.0.0.0:8275.

Community derivatives, and an early-stage warning

Two things in the README set expectations. The first is a caution that the returned results are understood and generated by AI and do not represent the developer's own views, which is the right thing to say about a system that ranks images by a model's reading of their meaning. The second is that the project is at an early testing stage, with issues and a community chat invited for bug reports, and the official API still in development. Against that, the repository is unusually complete for an early project, with a Dockerfile, a docker-compose file, a start.sh wrapper, a requirements.txt kept alongside a pyproject.toml with a uv lock file, a database.sh and a db-viewer.sh, alembic migrations, a tests/ directory with pytest configured, and separate product, design and API documents in PRODUCT.md, DESIGN.md and api.md, plus skills/, openspec/ and a legacy/ directory. The community section lists derivative projects built on it, including a web front end, an iOS shortcut, a command for a chat bot, a userscript extension and a bot plugin, and the project invites pull requests to add more. That pattern, a core service with community clients, is how a tool like this tends to spread.

Where MemeMeow is the wrong tool

Four limits are visible from the documentation. The first is that this is retrieval, not generation, and it is worth being blunt about that, because the name invites the other reading. The tool finds images that are already in the library; it does not draw you a new one. A team that wants the latter needs a different tool entirely. The second is that the quality of the search is the quality of the labelling, and the labelling is done by a model that reads an image and infers its meaning. A sticker with an obscure or regional reference will be indexed by whatever the model thought it was, and if the model is wrong the image becomes unfindable rather than mislabelled in an obvious way, since nothing in the interface lets a user edit a description. The third is operational weight. A single user wanting to find one reaction image does not need PostgreSQL with pgvector, an agent executor, a visual service, an API container and a locally hosted DINOv2 checkpoint, and the project offers a hosted site for that case. The fourth is the licence and the model dependency: AGPL-3.0-or-later is a serious commitment for a service that others can build on, and the retrieval quality depends on a third party model endpoint that you configure and pay for, which means the deployment inherits that service's cost, its limits and its availability.

Editorial conclusion

Adopt MemeMeow if you are building a chat client, a bot or a community tool that needs to pick a reaction image from a described mood, and you are willing to run Docker, PostgreSQL with pgvector and a local vision model. Do not adopt it if you need image generation rather than retrieval, or if you need the tagging to be deterministic and reviewable, since the labels are produced by a model and the project warns that the results are generated by AI. Before you deploy, expect to supply your own model credentials through MEMEMEOW_OPENCODE_BASE_URL and MEMEMEOW_OPENCODE_API_KEY, download the DINOv2 weights separately, and note that the project describes itself as being at an early testing stage with no GitHub releases.

Frequently asked questions

What is MemeMeow and how does it search?

It is a natural language image search workbench built on FastAPI and Vue 3 that retrieves reaction images from a description of a scene or a mood, using an embedding model for the text side and a local DINOv2 model for visual similarity between images.

What does the Docker deployment need?

Docker Engine 28 or newer with the Compose v2 plugin. You clone the repository, run `uv run python -m scripts.sync_env`, fill in the .env file with the model settings including MEMEMEOW_OPENCODE_BASE_URL and MEMEMEOW_OPENCODE_API_KEY, then run `./start.sh start` and open http://127.0.0.1:8275/.

How are the images labelled?

By a built-in OpenCode agent in the full analysis mode, which produces the source, usage and meaning of the image plus the vectors used for retrieval, with options for reverse image search through Google and for AI-generated file names. The direct upload mode skips that and derives the text vector from the file name instead.

What API does MemeMeow expose?

A search endpoint at POST http://localhost:8275/search taking a query, a result count and a flag for whether the query is enhanced by a language model, returning a results array of media paths. The README says the official hosted API is still in development, while the local search API is available for integration as long as administrative functions are not involved.

What licence is MemeMeow released under?

The GNU Affero General Public License v3.0 or later, with the LICENSE file in the repository root. The project describes itself as being at an early testing stage, publishes no GitHub releases, and the last push to the repository was on 2026-10-12.

Official sources

  1. Issues
  2. License: AGPL-3.0
  3. MemeMeow-Studio/MemeMeow on GitHub
  4. Project website
  5. README
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/mememeow-studio-mememeow.svg)](https://hysenlabs.com/projects/mememeow-studio-mememeow)

Was this useful?