search

Semantic image search using FastEmbed and sqlite-vec

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  10. 10
  11. 11
  12. 12
  13. 13
  14. 14
  15. 15
  16. 16
  17. 17
  18. 18
  19. 19
  20. 20
  21. 21
  22. 22
  23. 23
  24. 24
  25. 25
  26. 26
  27. 27
  28. 28
  29. 29
  30. 30
  31. 31
  32. 32
  33. 33
  34. 34
  35. 35
# search

Semantic image search using FastEmbed and sqlite-vec

## Installation

This section is for people who just want to use search. For developers, see the development section below.

This project uses [uv](https://github.com/astral-sh/uv). To install it, run `uv tool install git+https://git.unnamed.website/search/`. For GPU support, run `uv tool install --excludes <(echo onnxruntime) git+https://git.unnamed.website/search/[GPU_VENDOR]` using one of `intel`, `nvidia`, or `amd`. You may need to install drivers for your OS such as `intel-compute-runtime`. For AMD, add the flag `-f https://repo.radeon.com/rocm/manylinux/rocm-rel-7.1.1/`.

## Usage

This program uses a client-server architecture to watch directories with inotify and keep the model in memory so the client doesn't have to wait several seconds to load the model. It uses file inodes and modification times to avoid unnecessary re-indexing.

Run `search-server DIRS_TO_INDEX` to start the server. Make sure you don't include nested directories or weird stuff will happen. The server currently only indexes images although more modalities may be supported in the future. There are probably some weird race condition bugs if you modify a lot of files at the same time.

Then run `search-client SEARCH_TEXT NUM_RESULTS` to get a list of the most similar files, or search for a path instead of text for a file to similar file search. You can pass the list of results to an image viewer such as Gwenview to view image results (unfortunately Gwenview doesn't preserve the order of the images). Alternatively, add a third parameter to `search-client` and it will create a temporary directory containing symlinks to the search results and return the directory name. This works great with the Dolphin integrated terminal, for instance run `cd $(search-client "a cute fox" 10 link)`.

Check out [TIDY](https://github.com/slavabarkov/tidy) (for Android) and [rclip](https://github.com/yurijmikhalevich/rclip) for similar projects, although this one is probably fastest!

## Development

Clone this repo and run `uv sync` or `uv sync --no-install-package onnxruntime --extra GPU_VENDOR`. Now you can run it using `uv run search-server` and `uv run search-client`.

## TODO

- Test portability
- Investigate race condition bugs and stress test this more
- Detect if `DIRS_TO_INDEX` contains nested dirs
- Unload the image embedding model to save RAM unless doing a file to file search
- Write a systemd `.service` and `.socket` for running the server with socket activation
- Parallelize indexing? Not sure if this will help. I might need to batch embedding queries instead, but that sounds like a huge pain to implement.
- Fix the Python packaging to be less janky
- Weird bugs if an image file gets modified to no longer be an image and vice versa?
- Inodes are only unique in a single filesystem, so indexing dirs on multiple FSes won't work currently