2023-05-20 17:45:54 +10:00
#frozen_string_literal: true
module DiscourseAi::AiBot::Commands
class ImageCommand < Command
class << self
def name
" image "
end
def desc
2023-08-23 07:49:36 +10:00
" Renders an image from the description (remove all connector words, keep it to 40 words or less). Despite being a text based bot you can generate images! (when user asks to draw, paint or other synonyms try this) "
2023-06-20 08:45:31 +10:00
end
def parameters
[
Parameter . new (
name : " prompt " ,
2023-08-09 16:01:48 +10:00
description :
" The prompt used to generate or create or draw the image (40 words or less, be creative) " ,
2023-06-20 08:45:31 +10:00
type : " string " ,
required : true ,
) ,
]
end
2023-05-20 17:45:54 +10:00
end
def result_name
" results "
end
def description_args
2023-06-20 15:44:03 +10:00
{ prompt : @last_prompt }
2023-05-20 17:45:54 +10:00
end
def chain_next_response
2023-08-09 16:01:48 +10:00
false
end
def custom_raw
@custom_raw
2023-05-20 17:45:54 +10:00
end
2023-08-04 09:37:58 +10:00
def process ( prompt : )
@last_prompt = prompt
2023-08-14 16:30:12 +10:00
show_progress ( localized_description )
results = nil
2023-10-25 11:04:16 +11:00
# this ensures multisite safety since background threads
# generate the images
api_key = SiteSetting . ai_stability_api_key
engine = SiteSetting . ai_stability_engine
api_url = SiteSetting . ai_stability_api_url
2023-08-14 16:30:12 +10:00
# API is flaky, so try a few times
3 . times do
begin
thread =
Thread . new do
begin
2023-10-25 11:04:16 +11:00
results =
DiscourseAi :: Inference :: StabilityGenerator . perform! (
prompt ,
engine : engine ,
api_key : api_key ,
api_url : api_url ,
)
2023-08-14 16:30:12 +10:00
rescue = > e
Rails . logger . warn ( " Failed to generate image for prompt #{ prompt } : #{ e } " )
end
end
show_progress ( " . " , progress_caret : true ) while ! thread . join ( 2 )
break if results
end
end
2023-05-20 17:45:54 +10:00
2023-10-25 11:04:16 +11:00
return { prompt : prompt , error : " Something went wrong, could not generate image " } if ! results
2023-05-20 17:45:54 +10:00
uploads = [ ]
results [ :artifacts ] . each_with_index do | image , i |
f = Tempfile . new ( " v1_txt2img_ #{ i } .png " )
f . binmode
f . write ( Base64 . decode64 ( image [ :base64 ] ) )
f . rewind
uploads << UploadCreator . new ( f , " image.png " ) . create_for ( bot_user . id )
f . unlink
end
2023-08-09 16:01:48 +10:00
@custom_raw = << ~ RAW
2023-06-20 08:45:31 +10:00
[ grid ]
#{
2023-05-20 17:45:54 +10:00
uploads
. map { | upload | "  " }
. join ( " " )
2023-06-20 08:45:31 +10:00
}
[ / grid]
RAW
2023-08-09 16:01:48 +10:00
{ prompt : prompt , displayed_to_user : true }
2023-05-20 17:45:54 +10:00
end
end
end