Skip to content

Commit

Permalink
update docs and file structure
Browse files Browse the repository at this point in the history
  • Loading branch information
deepfates committed Sep 27, 2021
1 parent 20f47c9 commit c2bc91f
Show file tree
Hide file tree
Showing 94 changed files with 936 additions and 35 deletions.
2 changes: 1 addition & 1 deletion 00_core.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@
"\n",
"For now, calling the `queryFlow` process directly is the simplest gateway.\n",
"\n",
"*Meaningless. Explain how to use it closer to where it is implemented. Also show an example of it in use. Terrible sentence really."
"*Meaningless. Explain how to use it closer to where it is implemented. Also show an example of it in use. Terrible sentence really.*"
]
},
{
Expand Down
66 changes: 57 additions & 9 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@
> Search over large image datasets with natural language and computer vision!

*^ that is so nerdy. can we do something like "Local-first AI image search"? or is that still too opaque*

![meme about having too many memes](images/E2GoeMyWEAAkcLz.jpeg)

You know the problem. You have a huge folder of images: memes, screenshots, datasets, product photos, inspo albums, anything. You know that somewhere in that folder is the exact image you want, but you can't remember the filename or what day you saved it. There's nothing you can do. You have to scroll through the folder, skimming hundreds of thumbnails, hoping you don't accidentally miss it, hoping you'll recognize it when you do see it.
The problem: you have a huge folder of images. Memes, screenshots, datasets, product photos, inspo albums, anything. You know that somewhere in that folder is the exact image you want, but you can't remember the filename or what day you saved it. There's nothing you can do buit scroll through the folder, skimming hundreds of thumbnails, hoping you don't accidentally miss it, hoping you'll recognize it when you do see it.

Humans can do this amazingly well, all things considered. But even with computers, local image search is still pretty much a manual effort - you're still sorting through folders of images, like an archivist of old.
Humans do this amazingly well. But even with computers, local image search is still a manual effort - you're still sorting through folders of images, like an archivist of old.

Until now.
**Until memery**.

The `memery` package provides natural language search over local images. You can use it to search for things like "a line drawing of a woman facing to the left" and get _reasonably good results!_

Expand Down Expand Up @@ -45,16 +47,43 @@ Outline:

## Install

The necessary CLIP and torch packages will be installed by pip. You might want to make sure you have a sane CUDA environment before and after this step if you're trying to use GPU. If you don't have a GPU, `memery` should still work on your CPU.
The necessary CLIP and torch packages will be installed by pip.

*what does this mean? why are you telling me this? what if they aren't?*

You might want to make sure you have a sane CUDA environment before and after this step if you're trying to use GPU. If you don't have a GPU, `memery` should still work on your CPU.

*this is backwards and also impenetrable if you're not a nerd*

If you have any trouble please **open an issue on Github**! I want to make this package useful for as many people as possible. Help me know what's going wrong :)

*still true, pretty clear. use emoji or go home though*

If you have any trouble please **open an issue on Github**! I want to make this package useful for as many people as possible. Help me know what's going wrong :)
*This is the crucial command, huh? Seems a little far down the page. Maybe a quick-start section earlier, then a more in-depth Installation section here*

`pip install memery`

If you don't have a GPU for PyTorch, this command might help

If you don't have a GPU for PyTorch, this command might help:
`pip install torch==1.7.1+cpu torchvision==0.8.2+cpu torchaudio==0.7.2 -f https://download.pytorch.org/whl/torch_stable.html`

*did you scrape this from stackoverflow? or the CLIP source code or what. it looks very specific and arbitrary. I think it's meant to install pytorch CPU version, but the average user shouldn't have to know that! if you are trying to use CUDA and GPU it should be an easy toggle, and if you're a regular person wihtout a data science project you shouldn't have to go through a bunch of weird command line stuff.*

*In fact, how can we package this in a way that you don't have to type a single command? There has to be ways to wrap up a whole python setup and install it on a different computer, with all the same dependencies. Right? Ugh, unfortunately this is Python, so it might not exist. But I can at least scale the difficulty level with the user story.*

*Yes, user stories. We have to think about the interface between human and computer as another API, and look for the endpoints we can serve to different users with different protocols.*

*This means thinking about the reasons people come to the program, and how they expect it to respond. Currently I see three user stories:*
* *i have images and want to search them with a GUI app*
* *streamlit GUI*
* *i have a program/workflow and want to use image search as one part of it*
* *CLI tool*
* *python module*
* *jupyter GUI*
* *i want to improve on and/or contribute to memery development*
* *clone the repo*


*Each one has an increasing level of complexity and expected knowledge.*

## How to use

Expand All @@ -66,7 +95,10 @@ The browser GUI is a Streamlit app. You can run it from the command line with

or set up a desktop shortcut to use it from your menu.

If you're in a Jupyter environment, you can summon the GUI directly into an output cell like this:

*Why do I have to use a CLI to get a GUI? This is very annoying. In any case, this does not provide instructuions on how to use the GUI or any of its particular quirks. There should be a screenshot, also*

If you're in a Jupyter environment, you can summon an ipywidgets GUI directly into an output cell like this:


```python
Expand All @@ -80,22 +112,34 @@ display(app)
```


<memery.gui.appPage at 0x7f6c0e7c80d0>
<memery.gui.appPage at 0x7ff3072db110>


*This doesn't transfer to the README, so it should be fixed or be scrapped. Screenshots would work fine. Also I'm not sure if the interactive widgets would make sense without a kernel behind them anyway.*

### Use CLI

From the command line, you can use `memery` on any folder and it will search for images recursively, returning a list object to stdout.

*Why is it that behavior? Is it possible to make it not recursive? What is the usual behavior of a search in POSIX? What is the use case for a CLI memery: is it shell scripts? in-console image browsing? risk-tolerant batch modification? Think about this further*

*at least you can control how much output it spews to your terminal*

Pass the --n flag to control how many images are returned (default 10).

`memery recall PATH/TO/IMAGE/FOLDER 'query' --n 20
`

### Use as a library

*the following paragrah cannot be comprehended by any human mind. if you can even read to the end of it you should go touch grass*

Simply use `queryFlow` to search over a folder recursively! The folder will be indexed, if an index doesn't already exist. Then any new images will be CLIP-encoded, an Annoy treemap built, and a list of ranked filenames returned.

*okay, we survived. What are we supposed to say here instead?*

*I think what he's trying to get at is explaining the underlying mechanism of the search. Really all we need here is a function signature, as anyone who's going to use it as a library will probably also be looking at the docs for further information. Have a link here too, that goes to the `core` file where the main flows and executors are explained.*

```python
from memery.core import queryFlow
from memery.gui import get_grid
Expand All @@ -109,6 +153,10 @@ print(ranked[:5])

---

*Okay, now we need a whole part about development.

---

*Compile this notebook*

```python
Expand Down
3 changes: 3 additions & 0 deletions docs/_data/sidebars/home_sidebar.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,9 @@ entries:
- output: web,pdf
title: Streamlit app
url: streamlit_app.html
- output: web,pdf
title: memery
url: index-Copy1.html
output: web
title: memery
output: web
Expand Down
20 changes: 20 additions & 0 deletions docs/core.html
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,10 @@
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>This is the core module, which loads the CLIP model and the encodings of all the images in the folder, then tokenizes the search text or image, and finally returns a sorted list of filenames.</p>
<p><em>Express this as a process and nouns, instead of a blob sentence. The next part doesn't count because it's a whole new heading and it's crufted with nerd talk. Say clearly what the core flow is here. Something like:</em></p>
<p><em>Memery takes a folder of images, and a search query, and returns a list of nearest neighbors to the query.</em></p>
<p><em>The query flow and index flow can be used separately, but by default the query flow calls the indexing flow on each search. Image encodings are saved to disk. Only new images will be encoded with each indexing.</em></p>
<p>d</p>

</div>
</div>
Expand Down Expand Up @@ -62,13 +66,15 @@ <h2 id="Modular-flow-system">Modular flow system<a class="anchor-link" href="#Mo
<p>Takes a query and processes it through either Indexing Flow or Querying Flow, passing along arguments. The main entrypoint for each iteration of the index/query process.</p>
<p>Querying Flow can technically process either text or image search, becuase the CLIP encoder will put them into the same embedding space. So we might as well build in a method for either, and make it available to the user, since it's impressive and useful and relatively easy to build.</p>
<p>Eventually the Gateway process probably needs to be quite complicated, for serving all the different users and for delivering REST APIs to different clients. We'll need a way to accept text and images as HTTP requests and return JSON dictionaries (especially at the encoder, which will remain server-bound more than any other executor).</p>
<p><em>Do i actually need any of this? Perhaps if i'm going to implement it myself. But won't i just end up using Jina oonce it gets implemented fully? Or something similar? Well in any case this is meant to be a readable document, so i can explain how this is meant to owrk in the future without being so obtuse that it becomes an obstacle to reading further...</em></p>

</div>
</div>
</div>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<h3 id="Usage">Usage<a class="anchor-link" href="#Usage"> </a></h3><p>For now, calling the <a href="/memery/core.html#queryFlow"><code>queryFlow</code></a> process directly is the simplest gateway.</p>
<p><em>Meaningless. Explain how to use it closer to where it is implemented. Also show an example of it in use. Terrible sentence really.</em></p>

</div>
</div>
Expand All @@ -89,6 +95,7 @@ <h2 id="Flows">Flows<a class="anchor-link" href="#Flows"> </a></h2>
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The <a href="/memery/core.html#indexFlow"><code>indexFlow</code></a> checks the local directory for files with image extensions, loads the archive, splits out any new images to be encoded and encodes them, then finally builds a treemap and saves it along with the new archive. It returns a tuple with the locations of the archive and treemap.</p>
<p><em>Split this up into small chunks with code tests. No blob sentences!</em></p>

</div>
</div>
Expand Down Expand Up @@ -181,6 +188,7 @@ <h4 id="indexFlow" class="doc_header"><code>indexFlow</code><a href="https://git
<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p>The <a href="/memery/core.html#queryFlow"><code>queryFlow</code></a> takes a path and a query, checks for an index, loads it and searches through the treemap if it exists, and calls <a href="/memery/core.html#indexFlow"><code>indexFlow</code></a> to index it first if it hasn't been.</p>
<p><em>BLOB!</em></p>

</div>
</div>
Expand Down Expand Up @@ -216,6 +224,18 @@ <h4 id="queryFlow" class="doc_header"><code>queryFlow</code><a href="https://git
</div>
{% endraw %}

<div class="cell border-box-sizing text_cell rendered"><div class="inner_cell">
<div class="text_cell_render border-box-sizing rendered_html">
<p><em>Then what?! What are the limitations of this system? What are its options? What configuration can i do if i'm a power user? Why did you organize things this way instead of a different way?</em></p>
<p><em>This, and probably each of the following notebooks, would benefit from a small recording session where I try to explain it to an imaginary audience. So that I can get the narrative of how it works, and then arrange the code around that.</em></p>

</div>
</div>
</div>
</div>


<script type="application/vnd.jupyter.widget-state+json">
{"state": {}, "version_major": 2, "version_minor": 0}
</script>

Loading

0 comments on commit c2bc91f

Please sign in to comment.