mirror of
https://github.com/storytold/artcraft.git
synced 2026-11-10 20:11:49 +00:00
grok generation modes
This commit is contained in:
1 parent
21a30bde2d
commit
736ac055cc
13 files changed
+312
-5
No files matched your search
@@ -1,6 +1,7 @@
|
||||
pub mod aspect_ratio;
|
||||
pub mod baggage;
|
||||
pub mod file_id;
|
||||
pub mod video_generation_mode;
|
||||
pub mod post_id;
|
||||
pub mod request_id;
|
||||
pub mod sentry_trace;
|
||||
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
/// The video generation mode selector.
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub enum VideoGenerationMode {
|
||||
/// Supposedly the "NSFW" mode.
|
||||
Spicy,
|
||||
|
||||
Fun,
|
||||
|
||||
Normal,
|
||||
|
||||
/// This might be the only mode that allows for a custom text prompt
|
||||
Custom,
|
||||
}
|
||||
|
||||
impl VideoGenerationMode {
|
||||
|
||||
/// This is the value for `--mode` in video generation chats.
|
||||
pub fn as_api_mode_arg(&self) -> &'static str {
|
||||
match self {
|
||||
Self::Spicy => "extremely-spicy-or-crazy",
|
||||
Self::Fun => "extremely-crazy",
|
||||
Self::Normal => "normal",
|
||||
Self::Custom => "custom",
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,6 +92,8 @@ mod tests {
|
||||
cookies: cookies.as_str(),
|
||||
}).await?;
|
||||
|
||||
let prompt = "A dinosaur on stilts walking on the beach";
|
||||
|
||||
//let websocket = GrokWrappedWebsocket::new(websocket);
|
||||
let mut websocket = GrokWebsocket::new(websocket);
|
||||
|
||||
@@ -106,7 +108,7 @@ mod tests {
|
||||
|
||||
let result = prompt_websocket_image_with_retry(PromptWebsocketImageWithRetryArgs {
|
||||
websocket: &mut websocket,
|
||||
prompt: "a dog riding a motorcycle",
|
||||
prompt,
|
||||
aspect_ratio: ClientMessageAspectRatio::WideThreeByTwo,
|
||||
cookies: &cookies,
|
||||
}).await?;
|
||||
@@ -152,9 +154,19 @@ mod tests {
|
||||
match message {
|
||||
WebsocketServerMessage::Image(image) => {
|
||||
println!("IMAGE: {:?}", image.percentage_complete);
|
||||
if let Some(percent) = image.percentage_complete {
|
||||
if percent > 90.0 {
|
||||
println!("Image: {:?}", image);
|
||||
}
|
||||
}
|
||||
}
|
||||
WebsocketServerMessage::Json(json) => {
|
||||
println!("JSON : {:?}", json.percentage_complete);
|
||||
if let Some(percent) = json.percentage_complete {
|
||||
if percent > 90.0 {
|
||||
println!("Image: {:?}", json);
|
||||
}
|
||||
}
|
||||
}
|
||||
WebsocketServerMessage::Unknown(unknown) => {
|
||||
//let typ = unknown.get("type");
|
||||
|
||||
@@ -2,6 +2,7 @@ use crate::credentials::grok_full_credentials::GrokFullCredentials;
|
||||
use crate::datatypes::api::aspect_ratio::AspectRatio;
|
||||
use crate::datatypes::api::file_id::FileId;
|
||||
use crate::datatypes::api::post_id::PostId;
|
||||
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
|
||||
use crate::datatypes::file_upload_spec::FileUploadSpec;
|
||||
use crate::error::grok_error::GrokError;
|
||||
use crate::error::grok_generic_api_error::GrokGenericApiError;
|
||||
@@ -27,6 +28,9 @@ pub struct UploadImageAndGenerateVideo<'a, P: AsRef<Path>> {
|
||||
/// Aspect ratio for the video.
|
||||
pub aspect_ratio: Option<AspectRatio>,
|
||||
|
||||
/// Mode to generate the video: normal, fun, spicy, etc.
|
||||
pub mode: Option<VideoGenerationMode>,
|
||||
|
||||
/// Wait for the full video to be generated before returning
|
||||
/// By default, the endpoint stays open for 30-ish seconds while
|
||||
/// the video generates and streams back JSON progress updates.
|
||||
@@ -116,6 +120,7 @@ pub async fn upload_image_and_generate_video<P: AsRef<Path>>(args: UploadImageAn
|
||||
media_type: VideoMediaPostType::UserUploadedImage,
|
||||
cookie: args.full_credentials.cookies.as_str(),
|
||||
prompt: args.prompt,
|
||||
mode: args.mode,
|
||||
aspect_ratio: args.aspect_ratio,
|
||||
request_timeout: args.individual_request_timeout,
|
||||
baggage: &args.full_credentials.client_secrets.baggage,
|
||||
@@ -178,6 +183,7 @@ pub async fn upload_image_and_generate_video<P: AsRef<Path>>(args: UploadImageAn
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use crate::credentials::grok_full_credentials::GrokFullCredentials;
|
||||
use crate::datatypes::api::aspect_ratio::AspectRatio;
|
||||
use crate::datatypes::file_upload_spec::FileUploadSpec;
|
||||
use crate::recipes::request_client_secrets::{request_client_secrets, RequestClientSecretsArgs};
|
||||
use crate::recipes::upload_image_and_generate_video::{upload_image_and_generate_video, UploadImageAndGenerateVideo};
|
||||
@@ -185,7 +191,6 @@ mod tests {
|
||||
use crate::test_utils::setup_test_logging::setup_test_logging;
|
||||
use errors::AnyhowResult;
|
||||
use log::LevelFilter;
|
||||
use crate::datatypes::api::aspect_ratio::AspectRatio;
|
||||
// Result: GrokUploadFileResponse { file_metadata_id:
|
||||
// Some("acdee48f-9d6f-4bc6-9d06-fcc97dd4418a"), file_uri:
|
||||
// Some("users/85980643-ffab-4984-a3de-59a608c47d7f/acdee48f-9d6f-4bc6-9d06-fcc97dd4418a/content") }
|
||||
@@ -220,6 +225,7 @@ mod tests {
|
||||
file: FileUploadSpec::Path(image_path),
|
||||
prompt: maybe_prompt,
|
||||
aspect_ratio: Some(AspectRatio::Square),
|
||||
mode: None,
|
||||
individual_request_timeout: None,
|
||||
wait_for_generation: false,
|
||||
}).await?;
|
||||
|
||||
+8
-1
@@ -1,6 +1,7 @@
|
||||
use crate::credentials::grok_client_secrets::GrokClientSecrets;
|
||||
use crate::credentials::grok_full_credentials::GrokFullCredentials;
|
||||
use crate::datatypes::api::aspect_ratio::AspectRatio;
|
||||
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
|
||||
use crate::datatypes::file_upload_spec::FileUploadSpec;
|
||||
use crate::error::grok_client_error::GrokClientError;
|
||||
use crate::error::grok_error::GrokError;
|
||||
@@ -30,6 +31,9 @@ pub struct UploadImageAndGenerateVideoWithRetry<'a, P: AsRef<Path>> {
|
||||
/// Aspect ratio for the video.
|
||||
pub aspect_ratio: Option<AspectRatio>,
|
||||
|
||||
/// Mode to generate the video: normal, fun, spicy, etc.
|
||||
pub mode: Option<VideoGenerationMode>,
|
||||
|
||||
/// Wait for the full video to be generated before returning
|
||||
/// By default, the endpoint stays open for 30-ish seconds while
|
||||
/// the video generates and streams back JSON progress updates.
|
||||
@@ -116,6 +120,7 @@ pub async fn upload_image_and_generate_video_with_retry<P: AsRef<Path>>(
|
||||
media_type: VideoMediaPostType::UserUploadedImage,
|
||||
cookie: current_full_credentials_ref.cookies.as_str(),
|
||||
prompt: args.prompt,
|
||||
mode: args.mode,
|
||||
aspect_ratio: args.aspect_ratio,
|
||||
request_timeout: args.individual_request_timeout,
|
||||
baggage: ¤t_full_credentials_ref.client_secrets.baggage,
|
||||
@@ -271,6 +276,7 @@ pub async fn upload_image_and_generate_video_with_retry<P: AsRef<Path>>(
|
||||
mod tests {
|
||||
use crate::credentials::grok_full_credentials::GrokFullCredentials;
|
||||
use crate::datatypes::api::aspect_ratio::AspectRatio;
|
||||
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
|
||||
use crate::datatypes::file_upload_spec::FileUploadSpec;
|
||||
use crate::recipes::request_client_secrets::{request_client_secrets, RequestClientSecretsArgs};
|
||||
use crate::recipes::upload_image_and_generate_video_with_retry::{upload_image_and_generate_video_with_retry, UploadImageAndGenerateVideoWithRetry};
|
||||
@@ -310,7 +316,8 @@ mod tests {
|
||||
credentials: &credentials,
|
||||
file: FileUploadSpec::Path(image_path),
|
||||
prompt: maybe_prompt,
|
||||
aspect_ratio: Some(AspectRatio::Square),
|
||||
mode: Some(VideoGenerationMode::Custom),
|
||||
aspect_ratio: Some(AspectRatio::TallTwoByThree),
|
||||
individual_request_timeout: None,
|
||||
wait_for_generation: false,
|
||||
}).await?;
|
||||
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
curl 'https://grok.com/rest/app-chat/conversations/new' \
|
||||
-H 'accept: */*' \
|
||||
-H 'accept-language: en-US,en;q=0.9' \
|
||||
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=7798e88fd61243ba8985ca9f589f5113,sentry-org_id=4508179396558848,sentry-transaction=%2F%3Aslug*%3F,sentry-sampled=false,sentry-sample_rand=0.01740155041905489,sentry-sample_rate=0' \
|
||||
-H 'cache-control: no-cache' \
|
||||
-H 'content-type: application/json' \
|
||||
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764646543$j57$l0$h0' \
|
||||
-H 'origin: https://grok.com' \
|
||||
-H 'pragma: no-cache' \
|
||||
-H 'priority: u=1, i' \
|
||||
-H 'referer: https://grok.com/imagine/post/463eb5f6-7485-495a-a344-70ab4fe454a9' \
|
||||
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
|
||||
-H 'sec-ch-ua-mobile: ?0' \
|
||||
-H 'sec-ch-ua-platform: "macOS"' \
|
||||
-H 'sec-fetch-dest: empty' \
|
||||
-H 'sec-fetch-mode: cors' \
|
||||
-H 'sec-fetch-site: same-origin' \
|
||||
-H 'sentry-trace: 7798e88fd61243ba8985ca9f589f5113-889cac2356ac270b-0' \
|
||||
-H 'traceparent: 00-9698441276035e5f4414a5c7b7cde4e7-043b158b0070e175-00' \
|
||||
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
|
||||
-H 'x-statsig-id: eVTlFkyAcCo5RWxUQOUfzewYmzWMb/GbAFj4n2ymSal+UQwbGGxtFMSDrd+DdsVB0EaFp33Dd+aDMEmMn9Ay0MCCa8Bqeg' \
|
||||
-H 'x-xai-request-id: ac5e2fc3-daed-4967-a9ff-1d12b60ee0e1' \
|
||||
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=extremely-crazy","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9","aspectRatio":"2:3","videoLength":6}}}}}'
|
||||
|
||||
|
||||
--data-raw
|
||||
{
|
||||
"temporary":true,
|
||||
"modelName":"grok-3",
|
||||
"message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=extremely-crazy",
|
||||
"toolOverrides": {
|
||||
"videoGen":true
|
||||
},
|
||||
"responseMetadata": {
|
||||
"modelConfigOverride": {
|
||||
"modelMap": {
|
||||
"videoGenModelConfig": {
|
||||
"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9",
|
||||
"aspectRatio": "2:3",
|
||||
"videoLength":6
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
curl 'https://grok.com/rest/app-chat/conversations/new' \
|
||||
-H 'accept: */*' \
|
||||
-H 'accept-language: en-US,en;q=0.9' \
|
||||
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=7798e88fd61243ba8985ca9f589f5113,sentry-org_id=4508179396558848,sentry-transaction=%2F%3Aslug*%3F,sentry-sampled=false,sentry-sample_rand=0.01740155041905489,sentry-sample_rate=0' \
|
||||
-H 'cache-control: no-cache' \
|
||||
-H 'content-type: application/json' \
|
||||
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764646543$j57$l0$h0' \
|
||||
-H 'origin: https://grok.com' \
|
||||
-H 'pragma: no-cache' \
|
||||
-H 'priority: u=1, i' \
|
||||
-H 'referer: https://grok.com/imagine/post/463eb5f6-7485-495a-a344-70ab4fe454a9' \
|
||||
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
|
||||
-H 'sec-ch-ua-mobile: ?0' \
|
||||
-H 'sec-ch-ua-platform: "macOS"' \
|
||||
-H 'sec-fetch-dest: empty' \
|
||||
-H 'sec-fetch-mode: cors' \
|
||||
-H 'sec-fetch-site: same-origin' \
|
||||
-H 'sentry-trace: 7798e88fd61243ba8985ca9f589f5113-ac16ba34e7a9e3c2-0' \
|
||||
-H 'traceparent: 00-017b734e99d0585d4e05bf0376ef9ffb-c5854dfb0968df83-00' \
|
||||
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
|
||||
-H 'x-statsig-id: 8dxtnsQI+KKxzeTcyG2XRWSQE70E53kTiNBwF+QuwSH22YSTkOTlnEwLJVcL/k3JWIkNL/XNm7U/U87VShlyvfCIJ01k8g' \
|
||||
-H 'x-xai-request-id: c2eab60f-859f-4963-8ef8-b5eefaaf5966' \
|
||||
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/463eb5f6-7485-495a-a344-70ab4fe454a9.png --mode=normal","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"463eb5f6-7485-495a-a344-70ab4fe454a9","aspectRatio":"2:3","videoLength":6}}}}}'
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
curl 'https://grok.com/rest/app-chat/conversations/new' \
|
||||
-H 'accept: */*' \
|
||||
-H 'accept-language: en-US,en;q=0.9' \
|
||||
-H 'baggage: sentry-environment=production,sentry-public_key=b311e0f2690c81f25e2c4cf6d4f7ce1c,sentry-trace_id=277d6351c5063fd659b51b77b50bb453,sentry-org_id=4508179396558848,sentry-sampled=false,sentry-sample_rand=0.9765826569629004,sentry-sample_rate=0' \
|
||||
-H 'cache-control: no-cache' \
|
||||
-H 'content-type: application/json' \
|
||||
-b '_ga=GA1.1.1232202746.1760710013; i18nextLng=en; sso=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; sso-rw=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzZXNzaW9uX2lkIjoiOGU3MDFiNzctOTdkNC00ZjM0LWExOTctOWFmMDU1MzY3NDAwIn0.-a6x0InxbGzfTVfUlrdzxskxCnvMDI8lC90z4wHeGIk; stblid=b3331fc1-45d7-466b-83df-67427c0b2367; x-userid=85980643-ffab-4984-a3de-59a608c47d7f; mp_ea93da913ddb66b6372b89d97b1029ac_mixpanel=%7B%22distinct_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%2C%22%24device_id%22%3A%2279ce237a-a0f3-4913-bf4b-519ac8a98263%22%2C%22%24initial_referrer%22%3A%22%24direct%22%2C%22%24initial_referring_domain%22%3A%22%24direct%22%2C%22__mps%22%3A%7B%7D%2C%22__mpso%22%3A%7B%7D%2C%22__mpus%22%3A%7B%7D%2C%22__mpa%22%3A%7B%7D%2C%22__mpu%22%3A%7B%7D%2C%22__mpr%22%3A%5B%5D%2C%22__mpap%22%3A%5B%5D%2C%22%24user_id%22%3A%2285980643-ffab-4984-a3de-59a608c47d7f%22%7D; cf_clearance=5QPOzLWH8eEniaDlJR23k9VB4XjRPHdR.kfVR15BRkI-1764645588-1.2.1.1-WBy8wpvS9.Q.ofWBIMTLHDrKRIPt0Xrn5kAQ6I7xf4u0JSbB.E4CRd.fK6kEZo8OTXMAdt.F0YkoLJzB0TufxM79dMu63TKLmorKB.gSgUWJcea1eQcLJ1WG80uhv4VCMrSJ_HHAaq6fqiNNvS7pArgMT4tvoaQXShfDuV8ivYsRp31LYMgNnRFdtiCiJ5mxhf7uUMpSS_UbvCSaYe7CysUr472alMjEYUd.QhKpb8E; _ga_8FEWB057YH=GS2.1.s1764645588$o22$g1$t1764645617$j31$l0$h0' \
|
||||
-H 'origin: https://grok.com' \
|
||||
-H 'pragma: no-cache' \
|
||||
-H 'priority: u=1, i' \
|
||||
-H 'referer: https://grok.com/imagine/post/6136f31a-4aaf-48e0-ab86-fe9871feca91' \
|
||||
-H 'sec-ch-ua: "Chromium";v="142", "Google Chrome";v="142", "Not_A Brand";v="99"' \
|
||||
-H 'sec-ch-ua-mobile: ?0' \
|
||||
-H 'sec-ch-ua-platform: "macOS"' \
|
||||
-H 'sec-fetch-dest: empty' \
|
||||
-H 'sec-fetch-mode: cors' \
|
||||
-H 'sec-fetch-site: same-origin' \
|
||||
-H 'sentry-trace: 277d6351c5063fd659b51b77b50bb453-928bfb8d1221fde1-0' \
|
||||
-H 'traceparent: 00-b0bd9846c2990e253ecca887fdfba8a2-c415282f4b74bf60-00' \
|
||||
-H 'user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' \
|
||||
-H 'x-statsig-id: HjOCcSvnF01eIgszJ4J4qot//FLrCJb8Zz+f+AvBLs4ZNmt8fwsKc6PkyrjkEaImt9npwBpAUCrYQeeYTG/5jRWOKfLdHQ' \
|
||||
-H 'x-xai-request-id: d5ac2ce6-ed77-4a5d-8905-613a498035d3' \
|
||||
--data-raw '{"temporary":true,"modelName":"grok-3","message":"https://imagine-public.x.ai/imagine-public/images/6136f31a-4aaf-48e0-ab86-fe9871feca91.png --mode=extremely-spicy-or-crazy","toolOverrides":{"videoGen":true},"responseMetadata":{"modelConfigOverride":{"modelMap":{"videoGenModelConfig":{"parentPostId":"6136f31a-4aaf-48e0-ab86-fe9871feca91","aspectRatio":"2:3","videoLength":6}}}}}'
|
||||
|
||||
|
||||
--data-raw
|
||||
{
|
||||
"temporary":true,
|
||||
"modelName":"grok-3",
|
||||
"message":"https://imagine-public.x.ai/imagine-public/images/6136f31a-4aaf-48e0-ab86-fe9871feca91.png --mode=extremely-spicy-or-crazy",
|
||||
"toolOverrides": {
|
||||
"videoGen":true
|
||||
},
|
||||
"responseMetadata": {
|
||||
"modelConfigOverride": {
|
||||
"modelMap": {
|
||||
"videoGenModelConfig": {
|
||||
"parentPostId": "6136f31a-4aaf-48e0-ab86-fe9871feca91",
|
||||
"aspectRatio": "2:3",
|
||||
"videoLength":6
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+17
-2
@@ -6,6 +6,7 @@ use crate::datatypes::api::sentry_trace::SentryTrace;
|
||||
use crate::datatypes::api::svg_path_data::SvgPathData;
|
||||
use crate::datatypes::api::user_id::UserId;
|
||||
use crate::datatypes::api::verification_token::VerificationToken;
|
||||
use crate::datatypes::api::video_generation_mode::VideoGenerationMode;
|
||||
use crate::datatypes::api::xsid_numbers::XsidNumbers;
|
||||
use crate::error::categorize_grok_http_error::categorize_grok_http_error;
|
||||
use crate::error::grok_client_error::GrokClientError;
|
||||
@@ -33,6 +34,7 @@ pub struct GrokVideoGenChatConversationBuilder<'a> {
|
||||
pub file_id: &'a FileId,
|
||||
pub media_type: VideoMediaPostType,
|
||||
pub prompt: Option<&'a str>,
|
||||
pub mode: Option<VideoGenerationMode>,
|
||||
pub aspect_ratio: Option<AspectRatio>,
|
||||
|
||||
pub cookie: &'a str,
|
||||
@@ -232,12 +234,23 @@ impl <'a> GrokVideoGenChatConversationBuilder<'a> {
|
||||
VideoMediaPostType::Video => unimplemented!("implement for videos"),
|
||||
};
|
||||
|
||||
let mut prompt = format!("{media_url} --mode=normal");
|
||||
let mode_string = self.mode
|
||||
.unwrap_or(VideoGenerationMode::Normal)
|
||||
.as_api_mode_arg();
|
||||
|
||||
let mut prompt = format!("{media_url} --mode={mode_string}");
|
||||
|
||||
if let Some(user_prompt) = self.prompt {
|
||||
prompt = format!("{media_url} {user_prompt} --mode=custom");
|
||||
// If a text prompt is set, mode seems to typically be "custom".
|
||||
let mode_string = self.mode
|
||||
.unwrap_or(VideoGenerationMode::Custom)
|
||||
.as_api_mode_arg();
|
||||
|
||||
prompt = format!("{media_url} {user_prompt} --mode={mode_string}");
|
||||
}
|
||||
|
||||
info!("Grok video prompt: {prompt}");
|
||||
|
||||
let aspect_ratio = match self.aspect_ratio {
|
||||
Some(AspectRatio::Square) => VideoGenAspectRatio::Square,
|
||||
Some(AspectRatio::WideThreeByTwo) => VideoGenAspectRatio::WideThreeByTwo,
|
||||
@@ -351,6 +364,7 @@ mod tests {
|
||||
file_id: &file_id,
|
||||
media_type: VideoMediaPostType::UserUploadedImage,
|
||||
prompt: maybe_prompt,
|
||||
mode: Some(VideoGenerationMode::Custom),
|
||||
aspect_ratio: Some(AspectRatio::TallTwoByThree),
|
||||
|
||||
cookie: cookies.as_str(),
|
||||
@@ -414,6 +428,7 @@ mod tests {
|
||||
file_id: &file_id,
|
||||
media_type: VideoMediaPostType::UserUploadedImage,
|
||||
prompt: maybe_prompt,
|
||||
mode: None,
|
||||
aspect_ratio: Some(AspectRatio::Square),
|
||||
|
||||
cookie: cookies.as_str(),
|
||||
|
||||
@@ -2408,3 +2408,4 @@ pub mod yue;
|
||||
pub mod zonos;
|
||||
|
||||
pub mod qwen_image_edit;
|
||||
pub mod nano_banana_pro;
|
||||
@@ -0,0 +1,2 @@
|
||||
pub mod nano_banana_pro_text_to_image;
|
||||
pub mod nano_banana_pro_image_edit;
|
||||
+69
@@ -0,0 +1,69 @@
|
||||
use crate::prelude::{Deserialize, FalRequest, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct NanoBananaProImageEditInput {
|
||||
pub prompt: String,
|
||||
|
||||
pub image_urls: Vec<String>,
|
||||
|
||||
/// Eg. "16:9", "1:1", and a ton of other options. So many options.
|
||||
pub aspect_ratio: String,
|
||||
|
||||
/// Eg. "1K", "2K", "4K"
|
||||
pub resolution: String,
|
||||
|
||||
/// 1 - 4
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub num_images: Option<u8>,
|
||||
|
||||
/// "jpeg", "png", "webp"
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub output_format: Option<String>,
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"prompt": "make a photo of the man driving the car down the california coastline",
|
||||
"num_images": 3,
|
||||
"aspect_ratio": "16:9",
|
||||
"output_format": "png",
|
||||
"image_urls": [
|
||||
"https://storage.googleapis.com/falserverless/example_inputs/nano-banana-edit-input.png",
|
||||
"https://storage.googleapis.com/falserverless/example_inputs/nano-banana-edit-input-2.png"
|
||||
],
|
||||
"resolution": "1K"
|
||||
}
|
||||
*/
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct File {
|
||||
/// The URL where the file can be downloaded from.
|
||||
pub url: String,
|
||||
|
||||
// /// The mime type of the file.
|
||||
// /// "image/png"
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub content_type: Option<String>,
|
||||
// /// File data
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_data: Option<String>,
|
||||
// /// The name of the file. It will be auto-generated if not provided.
|
||||
// /// "z9RV14K95DvU.png"
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_name: Option<String>,
|
||||
// /// The size of the file in bytes.
|
||||
// /// 4404019
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_size: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Gemini25FlashImageEditOutput {
|
||||
pub images: Vec<File>,
|
||||
}
|
||||
|
||||
pub fn gemini_25_flash_image_edit(
|
||||
params: Gemini25FlashImageEditInput,
|
||||
) -> FalRequest<Gemini25FlashImageEditInput, Gemini25FlashImageEditOutput> {
|
||||
FalRequest::new("fal-ai/gemini-25-flash-image/edit", params)
|
||||
}
|
||||
+53
@@ -0,0 +1,53 @@
|
||||
use crate::prelude::{Deserialize, FalRequest, Serialize};
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct Gemini25FlashImageEditInput {
|
||||
pub prompt: String,
|
||||
|
||||
pub image_urls: Vec<String>,
|
||||
|
||||
/// 1 - 4
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub num_images: Option<u8>,
|
||||
|
||||
/// "jpeg" or "png"
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub output_format: Option<String>,
|
||||
|
||||
// /// Resolution, eg. "720p"
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub resolution: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize, Default)]
|
||||
pub struct File {
|
||||
/// The URL where the file can be downloaded from.
|
||||
pub url: String,
|
||||
|
||||
// /// The mime type of the file.
|
||||
// /// "image/png"
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub content_type: Option<String>,
|
||||
// /// File data
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_data: Option<String>,
|
||||
// /// The name of the file. It will be auto-generated if not provided.
|
||||
// /// "z9RV14K95DvU.png"
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_name: Option<String>,
|
||||
// /// The size of the file in bytes.
|
||||
// /// 4404019
|
||||
// #[serde(skip_serializing_if = "Option::is_none")]
|
||||
// pub file_size: Option<i64>,
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize, Deserialize)]
|
||||
pub struct Gemini25FlashImageEditOutput {
|
||||
pub images: Vec<File>,
|
||||
}
|
||||
|
||||
pub fn gemini_25_flash_image_edit(
|
||||
params: Gemini25FlashImageEditInput,
|
||||
) -> FalRequest<Gemini25FlashImageEditInput, Gemini25FlashImageEditOutput> {
|
||||
FalRequest::new("fal-ai/gemini-25-flash-image/edit", params)
|
||||
}
|
||||
Reference in new issue
Block a user