Initial commit with translated description
This commit is contained in:
204
scripts/generate_image.py
Normal file
204
scripts/generate_image.py
Normal file
@@ -0,0 +1,204 @@
|
||||
#!/usr/bin/env python3
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = [
|
||||
# "requests>=2.31.0",
|
||||
# ]
|
||||
# ///
|
||||
"""
|
||||
Generate images using Qwen Image API (Alibaba Cloud DashScope).
|
||||
|
||||
Usage:
|
||||
uv run generate_image.py --prompt "your image description" --filename "output.png" [--model qwen-image-max|qwen-image-turbo] [--size 1664*928|1024*1024|720*1280|1280*720] [--api-key KEY]
|
||||
"""
|
||||
|
||||
import argparse
|
||||
import os
|
||||
import sys
|
||||
import json
|
||||
import base64
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
def get_api_key(provided_key: str | None) -> str | None:
|
||||
"""Get API key from argument first, then environment."""
|
||||
if provided_key:
|
||||
return provided_key
|
||||
return os.environ.get("DASHSCOPE_API_KEY")
|
||||
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Generate images using Qwen Image API"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--prompt", "-p",
|
||||
required=True,
|
||||
help="Image description/prompt"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--filename", "-f",
|
||||
help="Output filename (optional, if not provided will only return URL)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--model", "-m",
|
||||
choices=["qwen-image-max", "qwen-image-turbo", "qwen-image-plus-2026-01-09"],
|
||||
default="qwen-image-max",
|
||||
help="Model to use: qwen-image-max (default) or qwen-image-turbo"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--size", "-s",
|
||||
choices=["1664*928", "1024*1024", "720*1280", "1280*720"],
|
||||
default="1664*928",
|
||||
help="Output size (default: 1664*928 for 16:9 ratio)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--negative-prompt", "-n",
|
||||
default="低分辨率,低画质,肢体畸形,手指畸形,画面过饱和,蜡像感,人脸无细节,过度光滑,画面具有AI感。构图混乱。文字模糊,扭曲。",
|
||||
help="Negative prompt to avoid unwanted elements"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-prompt-extend",
|
||||
action="store_true",
|
||||
help="Disable automatic prompt enhancement"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--watermark",
|
||||
action="store_true",
|
||||
help="Add watermark to generated image"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--api-key", "-k",
|
||||
help="DashScope API key (overrides DASHSCOPE_API_KEY env var)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--no-verify-ssl",
|
||||
action="store_true",
|
||||
help="Disable SSL certificate verification (use with caution)"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Get API key
|
||||
api_key = get_api_key(args.api_key)
|
||||
if not api_key:
|
||||
print("Error: No API key provided.", file=sys.stderr)
|
||||
print("Please either:", file=sys.stderr)
|
||||
print(" 1. Provide --api-key argument", file=sys.stderr)
|
||||
print(" 2. Set DASHSCOPE_API_KEY environment variable", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Import here after checking API key
|
||||
import requests
|
||||
|
||||
# Set up output path
|
||||
|
||||
# Build request payload
|
||||
payload = {
|
||||
"model": args.model,
|
||||
"input": {
|
||||
"messages": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": [
|
||||
{
|
||||
"text": args.prompt
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
},
|
||||
"parameters": {
|
||||
"negative_prompt": args.negative_prompt,
|
||||
"prompt_extend": not args.no_prompt_extend,
|
||||
"watermark": args.watermark,
|
||||
"size": args.size
|
||||
}
|
||||
}
|
||||
|
||||
print(f"Generating image with {args.model}...")
|
||||
print(f"Size: {args.size}")
|
||||
print(f"Prompt: {args.prompt}")
|
||||
|
||||
try:
|
||||
# Make API request
|
||||
response = requests.post(
|
||||
"https://dashscope.aliyuncs.com/api/v1/services/aigc/multimodal-generation/generation",
|
||||
headers={
|
||||
"Content-Type": "application/json",
|
||||
"Authorization": f"Bearer {api_key}"
|
||||
},
|
||||
json=payload,
|
||||
timeout=120,
|
||||
verify=True
|
||||
)
|
||||
|
||||
response.raise_for_status()
|
||||
result = response.json()
|
||||
|
||||
# Check for errors
|
||||
if result.get("code"):
|
||||
error_msg = result.get("message", "Unknown error")
|
||||
print(f"API Error: {error_msg}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Extract image URL from response
|
||||
output_data = result.get("output", {})
|
||||
choices = output_data.get("choices", [])
|
||||
|
||||
if not choices:
|
||||
print("Error: No choices in response", file=sys.stderr)
|
||||
print(f"Response: {json.dumps(result, indent=2, ensure_ascii=False)}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
# Get image URL from first choice
|
||||
message = choices[0].get("message", {})
|
||||
content = message.get("content", [])
|
||||
|
||||
if not content or not content[0].get("image"):
|
||||
print("Error: No image URL in response", file=sys.stderr)
|
||||
print(f"Response: {json.dumps(result, indent=2, ensure_ascii=False)}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
image_url = content[0]["image"]
|
||||
print(f"\nImage URL: {image_url}")
|
||||
|
||||
# If filename is provided, download and save the image
|
||||
if args.filename:
|
||||
output_path = Path(args.filename)
|
||||
output_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
print("Downloading image...")
|
||||
img_response = requests.get(image_url, timeout=30, verify=not args.no_verify_ssl)
|
||||
img_response.raise_for_status()
|
||||
|
||||
# Save the image
|
||||
with open(output_path, "wb") as f:
|
||||
f.write(img_response.content)
|
||||
|
||||
full_path = output_path.resolve()
|
||||
print(f"Image saved: {full_path}")
|
||||
# Clawdbot parses MEDIA tokens and will attach the file on supported providers.
|
||||
print(f"MEDIA: {full_path}")
|
||||
else:
|
||||
# Just return the URL for Clawdbot to display
|
||||
print(f"MEDIA_URL: {image_url}")
|
||||
|
||||
except requests.exceptions.HTTPError as e:
|
||||
print(f"HTTP Error: {e}", file=sys.stderr)
|
||||
try:
|
||||
error_detail = response.json()
|
||||
print(f"Error details: {json.dumps(error_detail, indent=2, ensure_ascii=False)}", file=sys.stderr)
|
||||
except:
|
||||
print(f"Response text: {response.text}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except requests.exceptions.RequestException as e:
|
||||
print(f"Error making API request: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"Error generating image: {e}", file=sys.stderr)
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user