Ecosyste.ms: Awesome
An open API service indexing awesome lists of open source software.
https://github.com/cbh123/stickerbaker
Let's bake some (AI) stickers!
https://github.com/cbh123/stickerbaker
Last synced: 4 days ago
JSON representation
Let's bake some (AI) stickers!
- Host: GitHub
- URL: https://github.com/cbh123/stickerbaker
- Owner: cbh123
- Created: 2024-02-23T18:08:36.000Z (9 months ago)
- Default Branch: main
- Last Pushed: 2024-05-14T18:23:11.000Z (6 months ago)
- Last Synced: 2024-10-28T21:40:40.252Z (16 days ago)
- Language: Elixir
- Homepage: https://stickerbaker.com
- Size: 13.5 MB
- Stars: 1,022
- Watchers: 9
- Forks: 134
- Open Issues: 3
-
Metadata Files:
- Readme: README.md
Awesome Lists containing this project
README
# StickerBaker
Announcing StickerBaker!
— Charlie Holtz (@charliebholtz) February 26, 2024
Make stickers with AI. Powered by @replicate and @flydotio, and 100% open-source.https://t.co/8vucCsHtAd pic.twitter.com/tBhDyGrOx0## How it works
Enter a prompt and generating a sticker using https://replicate.com/fofr/sticker-maker.
Here's an overview of the architecture:
![](./architecture.png)The home page is rendered in `lib/sticker_web/home_live.ex`. When the prompt form is submitted, this handle_event gets called:
```elixir
def handle_event("save", %{"prompt" => prompt}, socket) do
user_id = socket.assigns.local_user_id{:ok, prediction} =
Predictions.create_prediction(%{
prompt: prompt,
local_user_id: user_id
})send(self(), {:kick_off, prediction})
{:noreply,
socket
|> assign(form: to_form(%{"prompt" => ""}))
|> stream_insert(:my_predictions, prediction, at: 0)}
end
```This sends a `:kick_off` message to the LiveView (so there is no lag) which calls `Predictions.moderate/3` in `lib/sticker/predictions.ex`:
```elixir
@doc """
Moderates a prediction.
The logic in replicate_webhook_controller.ex handles
the webhook. Once the moderation is complete, the webhook controller automatically
called gen_image.
"""
def moderate(prompt, user_id, prediction_id) do
"fofr/prompt-classifier"
|> Replicate.Models.get!()
|> Replicate.Models.get_latest_version!()
|> Replicate.Predictions.create(
%{
prompt: "[PROMPT] #{prompt} [/PROMPT] [SAFETY_RANKING]",
max_new_tokens: 128,
temperature: 0.2,
top_p: 0.9,
top_k: 50,
stop_sequences: "[/SAFETY_RANKING]"
},
"#{Sticker.Utils.get_host()}/webhooks/replicate?user_id=#{user_id}&prediction_id=#{prediction_id}"
)
end
```We pass a webhook to [Replicate](https://replicate.com). All the logic for the webhook lives in `lib/sticker_web/controllers/replicate_webhook_controller.ex`. The nice thing about this webhook is that we can refresh the page or disconnect and [Replicate](https://replicate.com) still handles the prediction queue for us. Once the prediction is ready,
we upload it to [Tigris](https://fly.io/docs/reference/tigris/) (Replicate doesn't save our data for us) and then the sticker gets broadcast back to our `home_live.ex`.**Importantly**, because we're passing Replicate a webhook, for local dev you'll need [ngrok](https://ngrok.com) running to tunnel your localhost to a URL. Once you install ngrok run it with `ngrok http 4000` and paste the URL into your copied `.env` file.
## Stack
StickerBaker runs on:
- [Replicate](https://replicate.com/fofr/sticker-maker?utm_source=project&utm_campaign=stickerbaker) to generate the stickers
- [Fly.io](https://fly.io) for infrastructure
- [Tigris](https://www.tigrisdata.com) for image hosting## Dev
To start your Phoenix server:
- Run `mix setup` to install and setup dependencies
- Create an env file with `cp .env.copy .env`
- Add your [Replicate](https://replicate.com) tokens
- Add [Tigris](https://fly.io/docs/reference/tigris/) tokens
- Start ngrok with `ngrok http 4000` and add that to your env
- Start Phoenix endpoint with `mix phx.server` or inside IEx with `iex -S mix phx.server`
- Add a .env file with REPLICATE_API_TOKEN set to your [Replicate](https://replicate.com/) tokenNow you can visit [`localhost:4000`](http://localhost:4000) from your browser.
## Prod
Update the `url` and `check_origin` origin in `prod.exs`
Deploy with `fly launch`
Make sure when you `fly launch` you set up a Postgres DB!