The code below is the core functionality used in the app gpt-lab.lamdera.app. It is based on choonkeat/elm-openai, which I highly recommend. The other reference is the api-reference/images part of OpenAI's docs.
— jxxcarlson
The data flow goes like this:
Send the following command from frontend with your prompt and the number of images to be generated:
Lamdera.sendToBackend (AskGPTForGeneratedImages
model.inputPrompt
model.imagesPerPrompt)
In clause AskGPTForGeneratedImages
of Backend.updateFromFrontend
,
function generateImages
(see below) is called. It requests image urls
from OpenAI. This function uses the library choonkeat/elm-openai. Function generateImages
has to be called from the backend to keep it away from bad people.
OpenAI's response is processed at clause GotGeneratedImagesAtBE
in Backend.update
. It sends the urls received to the frontend where
they are captured at clause GotImageUrls
in Frontend.updateFromBackend
.
The type is GotImageUrls (List String)
-- Imports rom Choonkeat's library:
import OpenAI
import OpenAI.Image
generateImages : Lamdera.ClientId -> String -> Int -> Task String ( OpenAI.Image.Output, Lamdera.ClientId )
generateImages clientId userInput n =
let
cfg =
{ organizationId = "MY-ORGANIZATIONAL-ID"
, apiKey = Env.gptLabAPIKey
, baseUrl = Nothing -- defaults to "https://api.openai.com/v1"
}
in
OpenAI.Image.create
{ prompt = userInput
, n = Just n
, size = Just OpenAI.Image.Size1024x1024
, response_format = Just OpenAI.Image.ImageURL
, user = Nothing
}
|> OpenAI.withConfig cfg
|> Http.task
|> Task.mapError Ext.Http.errorString
|> Task.map (\result -> ( result, clientId ))
AskGPTForGeneratedImages prompt imagesToGenerate ->
( model,
Task.attempt GotGeneratedImagesAtBE
(AI.Image.generateImages clientId prompt imagesToGenerate) )
This is a clause in Backend.update
. It sends the image urls
received from OpenAI to the frontene:
GotGeneratedImagesAtBE result ->
case result of
Err errMessage ->
( model, Cmd.none )
Ok imageData ->
case imageData of
( OpenAI.Image.ImageURLOutput _ imageUrls, clientId ) ->
( model,
Lamdera.sendToFrontend
clientId
(GotImageUrls (imageUrls |> List.map Url.toString)))