Diffuser/lib/diffuser/generator/prompt_request_worker.ex

86 lines
2.4 KiB
Elixir

defmodule Diffuser.Generator.PromptRequestWorker do
alias Diffuser.Generator
alias Diffuser.Generator.PromptRequest
alias DiffuserWeb.Endpoint
alias Diffuser.Repo
@path [:code.priv_dir(:diffuser), "python"] |> Path.join()
@steps 10
@guidance_scale 7.5
def start(%PromptRequest{} = prompt_request) do
with {:ok, active_prompt} <-
update_and_broadcast_progress(prompt_request, "in_progress"),
{:ok, _file_location} <- call_python(:test_script, :test_func, active_prompt),
%PromptRequest{} = prompt_request_with_results <-
write_and_save_images(active_prompt),
{:ok, completed_prompt} <-
update_and_broadcast_progress(prompt_request_with_results, "finished") do
{:ok, completed_prompt |> Repo.preload(:images)}
else
nil ->
raise("prompt not found")
{:error, message} ->
raise(message)
end
end
defp update_and_broadcast_progress(%PromptRequest{id: id} = prompt_request, new_status) do
{:ok, new_prompt} =
Generator.update_prompt_request(prompt_request, %{
status: new_status,
steps: @steps,
guidance_scale: @guidance_scale
})
:ok = Endpoint.broadcast("request:#{id}", "request", %{prompt_request: new_prompt})
{:ok, new_prompt}
end
defp call_python(_module, _func, %{id: prompt_id, prompt: prompt}) do
port =
Port.open(
{:spawn,
~s(python #{@path}/stable_diffusion.py --prompt "#{prompt}" --output "#{@path}/#{prompt_id}.png" --num-inference-steps #{@steps})},
[:binary]
)
python_loop(port, prompt_id)
end
defp python_loop(port, prompt_id) do
receive do
{^port, {:data, ":finished" <> msg}} ->
{:ok, msg}
{^port, {:data, ":step" <> step}} ->
Endpoint.broadcast("request:#{prompt_id}", "progress", step)
python_loop(port, prompt_id)
{^port, result} ->
IO.inspect(result, label: "RESULT")
python_loop(port, prompt_id)
end
end
defp write_and_save_images(%PromptRequest{id: id}) do
file_path = "#{@path}/#{id}.png"
with {:ok, body} <- File.read(file_path),
{:ok, _result} <-
Generator.create_prompt_request_result(
id,
%{
file_name: "#{id}.png",
filename: "#{id}.png",
binary: body
}
),
:ok <- File.rm(file_path) do
Generator.get_prompt_request!(id)
end
end
end