2023-03-15 16:02:20 -04:00
# frozen_string_literal: true
RSpec . describe DiscourseAi :: AiHelper :: AssistantController do
2024-06-19 17:01:35 -04:00
before { assign_fake_provider_to ( :ai_helper_model ) }
2024-01-29 14:04:25 -05:00
2023-03-15 16:02:20 -04:00
describe " # suggest " do
2023-11-27 07:33:31 -05:00
let ( :text_to_proofread ) { " The rain in spain stays mainly in the plane. " }
2024-01-19 06:51:26 -05:00
let ( :proofread_text ) { " The rain in Spain, stays mainly in the Plane. " }
2023-11-27 07:33:31 -05:00
let ( :mode ) { CompletionPrompt :: PROOFREAD }
2023-03-15 16:02:20 -04:00
context " when not logged in " do
it " returns a 403 response " do
2023-11-27 07:33:31 -05:00
post " /discourse-ai/ai-helper/suggest " , params : { text : text_to_proofread , mode : mode }
2023-03-15 16:02:20 -04:00
expect ( response . status ) . to eq ( 403 )
end
end
context " when logged in as an user without enough privileges " do
fab! ( :user ) { Fabricate ( :newuser ) }
before do
sign_in ( user )
SiteSetting . ai_helper_allowed_groups = Group :: AUTO_GROUPS [ :staff ]
end
it " returns a 403 response " do
2023-11-27 07:33:31 -05:00
post " /discourse-ai/ai-helper/suggest " , params : { text : text_to_proofread , mode : mode }
2023-03-15 16:02:20 -04:00
expect ( response . status ) . to eq ( 403 )
end
end
context " when logged in as an allowed user " do
2024-03-05 10:48:28 -05:00
fab! ( :user )
2023-03-15 16:02:20 -04:00
before do
sign_in ( user )
user . group_ids = [ Group :: AUTO_GROUPS [ :trust_level_1 ] ]
SiteSetting . ai_helper_allowed_groups = Group :: AUTO_GROUPS [ :trust_level_1 ]
end
it " returns a 400 if the helper mode is invalid " do
invalid_mode = " asd "
2023-11-27 07:33:31 -05:00
post " /discourse-ai/ai-helper/suggest " ,
params : {
text : text_to_proofread ,
mode : invalid_mode ,
}
2023-03-15 16:02:20 -04:00
expect ( response . status ) . to eq ( 400 )
end
it " returns a 400 if the text is blank " do
post " /discourse-ai/ai-helper/suggest " , params : { mode : mode }
expect ( response . status ) . to eq ( 400 )
end
2023-03-22 15:00:28 -04:00
it " returns a generic error when the completion call fails " do
2023-11-28 23:17:46 -05:00
DiscourseAi :: Completions :: Llm
2023-11-27 07:33:31 -05:00
. any_instance
2024-01-04 07:53:47 -05:00
. expects ( :generate )
2023-11-27 07:33:31 -05:00
. raises ( DiscourseAi :: Completions :: Endpoints :: Base :: CompletionFailed )
2023-03-22 15:00:28 -04:00
2023-11-27 07:33:31 -05:00
post " /discourse-ai/ai-helper/suggest " , params : { mode : mode , text : text_to_proofread }
2023-03-22 15:00:28 -04:00
expect ( response . status ) . to eq ( 502 )
end
2023-03-15 16:02:20 -04:00
it " returns a suggestion " do
2023-11-27 07:33:31 -05:00
expected_diff =
" <div class= \" inline-diff \" ><p>The rain in <ins>Spain</ins><ins>,</ins><ins> </ins><del>spain </del>stays mainly in the <ins>Plane</ins><del>plane</del>.</p></div> "
2023-03-15 16:02:20 -04:00
2024-01-19 06:51:26 -05:00
DiscourseAi :: Completions :: Llm . with_prepared_responses ( [ proofread_text ] ) do
2023-11-27 07:33:31 -05:00
post " /discourse-ai/ai-helper/suggest " , params : { mode : mode , text : text_to_proofread }
2023-03-15 16:02:20 -04:00
2023-11-27 07:33:31 -05:00
expect ( response . status ) . to eq ( 200 )
2024-01-19 06:51:26 -05:00
expect ( response . parsed_body [ " suggestions " ] . first ) . to eq ( proofread_text )
2023-11-27 07:33:31 -05:00
expect ( response . parsed_body [ " diff " ] ) . to eq ( expected_diff )
end
2023-03-15 16:02:20 -04:00
end
2023-12-11 17:26:56 -05:00
it " uses custom instruction when using custom_prompt mode " do
translated_text = " Un usuario escribio esto "
expected_diff =
" <div class= \" inline-diff \" ><p><ins>Un </ins><ins>usuario </ins><ins>escribio </ins><ins>esto</ins><del>A </del><del>user </del><del>wrote </del><del>this</del></p></div> "
2024-01-29 14:04:25 -05:00
DiscourseAi :: Completions :: Llm . with_prepared_responses ( [ translated_text ] ) do
2023-12-11 17:26:56 -05:00
post " /discourse-ai/ai-helper/suggest " ,
params : {
mode : CompletionPrompt :: CUSTOM_PROMPT ,
text : " A user wrote this " ,
custom_prompt : " Translate to Spanish " ,
}
expect ( response . status ) . to eq ( 200 )
expect ( response . parsed_body [ " suggestions " ] . first ) . to eq ( translated_text )
expect ( response . parsed_body [ " diff " ] ) . to eq ( expected_diff )
end
end
2023-03-15 16:02:20 -04:00
end
end
2024-02-19 12:56:28 -05:00
describe " # caption_image " do
2024-03-05 10:48:28 -05:00
fab! ( :upload )
2024-02-19 21:43:39 -05:00
let ( :image_url ) { " #{ Discourse . base_url } #{ upload . url } " }
2024-02-19 12:56:28 -05:00
let ( :caption ) { " A picture of a cat sitting on a table " }
2024-02-21 13:10:22 -05:00
let ( :caption_with_attrs ) do
" A picture of a cat sitting on a table ( #{ I18n . t ( " discourse_ai.ai_helper.image_caption.attribution " ) } ) "
end
2024-02-19 12:56:28 -05:00
context " when logged in as an allowed user " do
2024-02-19 21:43:39 -05:00
fab! ( :user ) { Fabricate ( :user , refresh_auto_groups : true ) }
2024-02-19 12:56:28 -05:00
before do
sign_in ( user )
SiteSetting . ai_helper_allowed_groups = Group :: AUTO_GROUPS [ :trust_level_1 ]
SiteSetting . ai_llava_endpoint = " https://example.com "
stub_request ( :post , " https://example.com/predictions " ) . to_return (
status : 200 ,
body : { output : caption . gsub ( " " , " | " ) . split ( " | " ) } . to_json ,
)
end
it " returns the suggested caption for the image " do
2024-05-27 13:49:24 -04:00
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " long_url " ,
}
2024-02-19 12:56:28 -05:00
expect ( response . status ) . to eq ( 200 )
2024-02-21 13:10:22 -05:00
expect ( response . parsed_body [ " caption " ] ) . to eq ( caption_with_attrs )
2024-02-19 12:56:28 -05:00
end
2024-05-27 13:49:24 -04:00
context " when the image_url is a short_url " do
let ( :image_url ) { upload . short_url }
it " returns the suggested caption for the image " do
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " short_url " ,
}
expect ( response . status ) . to eq ( 200 )
expect ( response . parsed_body [ " caption " ] ) . to eq ( caption_with_attrs )
end
end
context " when the image_url is a short_path " do
let ( :image_url ) { " #{ Discourse . base_url } #{ upload . short_path } " }
it " returns the suggested caption for the image " do
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " short_path " ,
}
expect ( response . status ) . to eq ( 200 )
expect ( response . parsed_body [ " caption " ] ) . to eq ( caption_with_attrs )
end
end
2024-02-19 12:56:28 -05:00
it " returns a 502 error when the completion call fails " do
stub_request ( :post , " https://example.com/predictions " ) . to_return ( status : 502 )
2024-05-27 13:49:24 -04:00
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " long_url " ,
}
2024-02-19 12:56:28 -05:00
expect ( response . status ) . to eq ( 502 )
end
it " returns a 400 error when the image_url is blank " do
post " /discourse-ai/ai-helper/caption_image "
expect ( response . status ) . to eq ( 400 )
end
2024-02-19 21:43:39 -05:00
it " returns a 404 error if no upload is found " do
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : " http://blah.com/img.jpeg " ,
2024-05-27 13:49:24 -04:00
image_url_type : " long_url " ,
2024-02-19 21:43:39 -05:00
}
expect ( response . status ) . to eq ( 404 )
end
context " for secure uploads " do
2024-03-05 10:48:28 -05:00
fab! ( :group )
2024-02-19 21:43:39 -05:00
fab! ( :private_category ) { Fabricate ( :private_category , group : group ) }
fab! ( :post_in_secure_context ) do
Fabricate ( :post , topic : Fabricate ( :topic , category : private_category ) )
end
fab! ( :upload ) { Fabricate ( :secure_upload , access_control_post : post_in_secure_context ) }
let ( :image_url ) { " #{ Discourse . base_url } /secure-uploads/ #{ upload . url } " }
before { enable_secure_uploads }
it " returns a 403 error if the user cannot access the secure upload " do
2024-05-27 13:49:24 -04:00
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " long_url " ,
}
2024-02-19 21:43:39 -05:00
expect ( response . status ) . to eq ( 403 )
end
it " returns a 200 message and caption if user can access the secure upload " do
group . add ( user )
2024-05-27 13:49:24 -04:00
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " long_url " ,
}
2024-02-19 21:43:39 -05:00
expect ( response . status ) . to eq ( 200 )
2024-02-21 13:10:22 -05:00
expect ( response . parsed_body [ " caption " ] ) . to eq ( caption_with_attrs )
2024-02-19 21:43:39 -05:00
end
context " if the input URL is for a secure upload but not on the secure-uploads path " do
let ( :image_url ) { " #{ Discourse . base_url } #{ upload . url } " }
it " creates a signed URL properly and makes the caption " do
group . add ( user )
2024-05-27 13:49:24 -04:00
post " /discourse-ai/ai-helper/caption_image " ,
params : {
image_url : image_url ,
image_url_type : " long_url " ,
}
2024-02-19 21:43:39 -05:00
expect ( response . status ) . to eq ( 200 )
2024-02-21 13:10:22 -05:00
expect ( response . parsed_body [ " caption " ] ) . to eq ( caption_with_attrs )
2024-02-19 21:43:39 -05:00
end
end
end
2024-02-19 12:56:28 -05:00
end
end
2023-03-15 16:02:20 -04:00
end