indoxrouter 0.1.21__tar.gz → 0.1.23__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indoxrouter
3
- Version: 0.1.21
3
+ Version: 0.1.23
4
4
  Summary: A unified client for various AI providers
5
5
  Author-email: indoxRouter Team <ashkan.eskandari.dev@gmail.com>
6
6
  License: MIT
@@ -647,10 +647,11 @@ class Client:
647
647
  # Format the model string
648
648
  formatted_model = self._format_model_string(model)
649
649
 
650
- # Extract provider from model string if present
650
+ # Extract provider and model name from model string if present
651
651
  provider = "openai" # Default provider
652
+ model_name = model
652
653
  if "/" in model:
653
- provider, _ = model.split("/", 1)
654
+ provider, model_name = model.split("/", 1)
654
655
 
655
656
  # Filter out problematic parameters
656
657
  filtered_kwargs = {}
@@ -672,20 +673,29 @@ class Client:
672
673
  if provider.lower() == "google":
673
674
  # For Google, use aspect_ratio instead of size
674
675
  if aspect_ratio is not None:
676
+ # Google's imagen-3 has specific supported aspect ratios
677
+ if model_name == "imagen-3.0-generate-002" and aspect_ratio not in [
678
+ "1:1",
679
+ "3:4",
680
+ "4:3",
681
+ "9:16",
682
+ "16:9",
683
+ ]:
684
+ aspect_ratio = "1:1" # Default to 1:1 if not supported
675
685
  data["aspect_ratio"] = aspect_ratio
676
686
  elif size is not None:
677
687
  # Convert size to aspect_ratio
678
688
  formatted_size = self._format_image_size_for_provider(
679
- size, provider, model
689
+ size, provider, model_name
680
690
  )
681
691
  data["aspect_ratio"] = formatted_size
682
692
  else:
683
693
  # Default aspect_ratio for Google
684
694
  data["aspect_ratio"] = "1:1"
685
695
  elif provider.lower() == "xai":
686
- # xAI doesn't support size parameter
696
+ # xAI doesn't support size parameter - do not include it
687
697
  pass
688
- elif size is not None:
698
+ elif size is not None and provider.lower() != "xai":
689
699
  # For other providers (like OpenAI), use size as is
690
700
  data["size"] = size
691
701
 
@@ -696,7 +706,9 @@ class Client:
696
706
 
697
707
  # Add standard parameters if provided
698
708
  if response_format is not None:
709
+ # Only add response_format if explicitly provided by the user
699
710
  data["response_format"] = response_format
711
+
700
712
  if user is not None:
701
713
  data["user"] = user
702
714
 
@@ -738,8 +750,85 @@ class Client:
738
750
  if filtered_kwargs:
739
751
  data["additional_params"] = filtered_kwargs
740
752
 
753
+ # Special case handling for specific models and providers
754
+ # Only include parameters supported by each model based on their JSON definitions
755
+ if provider.lower() == "openai" and "gpt-image" in model_name.lower():
756
+ # For OpenAI's gpt-image models, don't automatically add response_format
757
+ if "response_format" in data and response_format is None:
758
+ del data["response_format"]
759
+
760
+ if provider.lower() == "xai" and "grok-2-image" in model_name.lower():
761
+ # For xAI's grok-2-image models, ensure size is not included
762
+ if "size" in data:
763
+ del data["size"]
764
+
765
+ # Clean up any parameters that shouldn't be sent to specific providers
766
+ # This ensures we only send parameters that each provider supports
767
+ supported_params = self._get_supported_parameters_for_model(
768
+ provider, model_name
769
+ )
770
+ if supported_params:
771
+ for param in list(data.keys()):
772
+ if param not in ["prompt", "model"] and param not in supported_params:
773
+ del data[param]
774
+
741
775
  return self._request("POST", IMAGE_ENDPOINT, data)
742
776
 
777
+ def _get_supported_parameters_for_model(
778
+ self, provider: str, model_name: str
779
+ ) -> List[str]:
780
+ """
781
+ Get the list of supported parameters for a specific model.
782
+ This helps avoid sending unsupported parameters to providers.
783
+
784
+ Args:
785
+ provider: The provider name (e.g., 'openai', 'google', 'xai')
786
+ model_name: The model name (e.g., 'gpt-image-1', 'imagen-3.0-generate-002')
787
+
788
+ Returns:
789
+ List of parameter names supported by the model
790
+ """
791
+ # Define supported parameters for specific models
792
+ if provider.lower() == "openai" and "gpt-image" in model_name.lower():
793
+ return [
794
+ "prompt",
795
+ "size",
796
+ "quality",
797
+ "n",
798
+ "user",
799
+ "background",
800
+ "moderation",
801
+ "output_compression",
802
+ "output_format",
803
+ "style",
804
+ ]
805
+
806
+ elif provider.lower() == "google" and "imagen" in model_name.lower():
807
+ return [
808
+ "prompt",
809
+ "n",
810
+ "negative_prompt",
811
+ "aspect_ratio",
812
+ "guidance_scale",
813
+ "seed",
814
+ "safety_filter_level",
815
+ "person_generation",
816
+ "include_safety_attributes",
817
+ "include_rai_reason",
818
+ "language",
819
+ "output_mime_type",
820
+ "output_compression_quality",
821
+ "add_watermark",
822
+ "enhance_prompt",
823
+ "response_format",
824
+ ]
825
+
826
+ elif provider.lower() == "xai" and "grok-2-image" in model_name.lower():
827
+ return ["prompt", "n", "response_format"]
828
+
829
+ # Default case - allow all parameters
830
+ return []
831
+
743
832
  def models(self, provider: Optional[str] = None) -> Dict[str, Any]:
744
833
  """
745
834
  Get available models.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: indoxrouter
3
- Version: 0.1.21
3
+ Version: 0.1.23
4
4
  Summary: A unified client for various AI providers
5
5
  Author-email: indoxRouter Team <ashkan.eskandari.dev@gmail.com>
6
6
  License: MIT
@@ -3,9 +3,6 @@ README.md
3
3
  pyproject.toml
4
4
  cookbook/README.md
5
5
  cookbook/indoxRouter_cookbook.ipynb
6
- examples/google_image_generation.py
7
- examples/image_generation.py
8
- examples/provider_specific_image_generation.py
9
6
  indoxrouter/__init__.py
10
7
  indoxrouter/client.py
11
8
  indoxrouter/constants.py
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "indoxrouter"
7
- version = "0.1.21"
7
+ version = "0.1.23"
8
8
  authors = [
9
9
  {name = "indoxRouter Team", email = "ashkan.eskandari.dev@gmail.com"},
10
10
  ]
@@ -1,159 +0,0 @@
1
- """
2
- Example script demonstrating image generation with Google's Imagen model through indoxRouter.
3
-
4
- This script shows how to properly format parameters for Google's image generation API,
5
- including the special handling of aspect ratios and other Google-specific parameters.
6
-
7
- Requirements:
8
- - Install indoxRouter: pip install indoxrouter
9
- - Set INDOX_ROUTER_API_KEY environment variable with your API key
10
- """
11
-
12
- import os
13
- import base64
14
- from io import BytesIO
15
- import requests
16
- from datetime import datetime
17
-
18
- from indoxrouter import Client
19
-
20
- # For displaying images in notebooks
21
- try:
22
- from IPython.display import Image, display
23
-
24
- in_notebook = True
25
- except ImportError:
26
- in_notebook = False
27
-
28
- # Initialize client with API key from environment variable
29
- api_key = os.environ.get("INDOX_ROUTER_API_KEY")
30
- if not api_key:
31
- print("Please set the INDOX_ROUTER_API_KEY environment variable")
32
- exit(1)
33
-
34
- client = Client(api_key=api_key)
35
-
36
-
37
- def save_image_from_url(url, filename):
38
- """Download and save an image from a URL."""
39
- response = requests.get(url)
40
- if response.status_code == 200:
41
- with open(filename, "wb") as f:
42
- f.write(response.content)
43
- print(f"Image saved to {filename}")
44
- else:
45
- print(f"Failed to download image: {response.status_code}")
46
-
47
-
48
- def save_image_from_b64(b64_data, filename):
49
- """Save an image from base64 data."""
50
- image_data = base64.b64decode(b64_data)
51
- with open(filename, "wb") as f:
52
- f.write(image_data)
53
- print(f"Image saved to {filename}")
54
-
55
-
56
- def generate_google_image(prompt, aspect_ratio="1:1", **kwargs):
57
- """
58
- Generate an image using Google's Imagen model.
59
-
60
- Args:
61
- prompt: The text prompt to generate an image from
62
- aspect_ratio: The aspect ratio of the image (e.g., "1:1", "4:3", "16:9")
63
- **kwargs: Additional parameters to pass to the API
64
- """
65
- print(f"\n=== Generating image with Google Imagen ===")
66
- print(f"Prompt: {prompt}")
67
- print(f"Aspect ratio: {aspect_ratio}")
68
-
69
- try:
70
- # Generate the image
71
- # Note: The client will automatically convert "1024x1024" to "1:1" for Google models,
72
- # but it's more explicit to use the correct format directly
73
- response = client.images(
74
- prompt=prompt,
75
- model="google/imagen-3.0-generate-002",
76
- size=aspect_ratio, # Google uses aspect ratios instead of pixel dimensions
77
- **kwargs,
78
- )
79
-
80
- print(f"Response received from Google:")
81
- print(f"- Success: {response['success']}")
82
- print(f"- Cost: ${response['usage']['cost']:.4f}")
83
-
84
- # Check if we have image data
85
- if "data" in response and response["data"]:
86
- image_data = response["data"][0]
87
-
88
- # Create a timestamp for unique filenames
89
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
90
-
91
- if "url" in image_data and image_data["url"]:
92
- filename = (
93
- f"google_imagen_{aspect_ratio.replace(':', 'x')}_{timestamp}.png"
94
- )
95
- save_image_from_url(image_data["url"], filename)
96
-
97
- # Display in notebook if possible
98
- if in_notebook:
99
- display(Image(url=image_data["url"]))
100
-
101
- elif "b64_json" in image_data and image_data["b64_json"]:
102
- filename = (
103
- f"google_imagen_{aspect_ratio.replace(':', 'x')}_{timestamp}.png"
104
- )
105
- save_image_from_b64(image_data["b64_json"], filename)
106
-
107
- # Display in notebook if possible
108
- if in_notebook:
109
- display(Image(data=base64.b64decode(image_data["b64_json"])))
110
- else:
111
- print("No image data found in response")
112
- print("Response:", response)
113
-
114
- except Exception as e:
115
- print(f"Error generating image with Google Imagen: {str(e)}")
116
-
117
-
118
- def main():
119
- """Main function demonstrating Google Imagen image generation."""
120
-
121
- # Basic example with 1:1 aspect ratio (square image)
122
- generate_google_image(
123
- prompt="A tranquil zen garden with cherry blossoms and a small pond"
124
- )
125
-
126
- # Example with 16:9 aspect ratio (widescreen)
127
- generate_google_image(
128
- prompt="A wide panoramic view of a futuristic city skyline at sunset with flying vehicles",
129
- aspect_ratio="16:9",
130
- )
131
-
132
- # Example with 9:16 aspect ratio (portrait/mobile)
133
- generate_google_image(
134
- prompt="A tall waterfall surrounded by lush greenery in a tropical forest",
135
- aspect_ratio="9:16",
136
- )
137
-
138
- # Example with negative prompt to influence the generation
139
- generate_google_image(
140
- prompt="A detailed watercolor painting of a coastal village with boats in the harbor",
141
- negative_prompt="dark, moody, sketch, black and white, blurry",
142
- )
143
-
144
- # Example with more parameters
145
- generate_google_image(
146
- prompt="A beautiful tiger resting in a lush jungle environment",
147
- aspect_ratio="4:3",
148
- negative_prompt="cartoon, illustration, low quality",
149
- seed=123456, # Consistent results with the same seed
150
- guidance_scale=7.5, # Controls how closely the model follows the prompt (usually between 1-20)
151
- safety_filter_level="block_none", # Less restrictive safety filter
152
- )
153
-
154
- # Close the client when done
155
- client.close()
156
-
157
-
158
- if __name__ == "__main__":
159
- main()
@@ -1,141 +0,0 @@
1
- """
2
- Example script demonstrating image generation with various providers through indoxRouter.
3
-
4
- This script shows how to generate images using different providers (OpenAI, xAI, Google)
5
- and how to handle the responses to display or save the generated images.
6
-
7
- Requirements:
8
- - Install indoxRouter: pip install indoxrouter
9
- - Set INDOX_ROUTER_API_KEY environment variable with your API key
10
- """
11
-
12
- import os
13
- import base64
14
- from io import BytesIO
15
- import requests
16
- from datetime import datetime
17
-
18
- from indoxrouter import Client
19
-
20
- # For displaying images in notebooks
21
- try:
22
- from IPython.display import Image, display
23
-
24
- in_notebook = True
25
- except ImportError:
26
- in_notebook = False
27
-
28
- # Initialize client with API key from environment variable
29
- client = Client()
30
-
31
-
32
- def save_image_from_url(url, filename):
33
- """Download and save an image from a URL."""
34
- response = requests.get(url)
35
- if response.status_code == 200:
36
- with open(filename, "wb") as f:
37
- f.write(response.content)
38
- print(f"Image saved to {filename}")
39
- else:
40
- print(f"Failed to download image: {response.status_code}")
41
-
42
-
43
- def save_image_from_b64(b64_data, filename):
44
- """Save an image from base64 data."""
45
- image_data = base64.b64decode(b64_data)
46
- with open(filename, "wb") as f:
47
- f.write(image_data)
48
- print(f"Image saved to {filename}")
49
-
50
-
51
- def generate_and_save_image(provider, model, prompt):
52
- """Generate an image and save it to a file."""
53
- print(f"\n=== Generating image with {provider}/{model} ===")
54
- print(f"Prompt: {prompt}")
55
-
56
- try:
57
- # Generate the image
58
- response = client.images(
59
- prompt=prompt,
60
- model=f"{provider}/{model}",
61
- size="1024x1024",
62
- )
63
-
64
- print(f"Response received from {provider}:")
65
- print(f"- Success: {response['success']}")
66
- print(f"- Cost: ${response['usage']['cost']:.4f}")
67
-
68
- # Check if we have image data
69
- if "data" in response and response["data"]:
70
- image_data = response["data"][0]
71
-
72
- # Create a timestamp for unique filenames
73
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
74
-
75
- if "url" in image_data and image_data["url"]:
76
- filename = f"{provider}_{model}_{timestamp}.png"
77
- save_image_from_url(image_data["url"], filename)
78
-
79
- # Display in notebook if possible
80
- if in_notebook:
81
- display(Image(url=image_data["url"]))
82
-
83
- elif "b64_json" in image_data and image_data["b64_json"]:
84
- filename = f"{provider}_{model}_{timestamp}.png"
85
- save_image_from_b64(image_data["b64_json"], filename)
86
-
87
- # Display in notebook if possible
88
- if in_notebook:
89
- display(Image(data=base64.b64decode(image_data["b64_json"])))
90
-
91
- # Check for revised prompt (DALL-E 3 often revises prompts)
92
- if "revised_prompt" in image_data and image_data["revised_prompt"]:
93
- print(f"Revised prompt: {image_data['revised_prompt']}")
94
- else:
95
- print("No image data found in response")
96
- print("Response:", response)
97
-
98
- except Exception as e:
99
- print(f"Error generating image with {provider}/{model}: {str(e)}")
100
-
101
-
102
- # Example prompts
103
- prompts = {
104
- "landscape": "A beautiful mountain landscape with a lake at sunset",
105
- "animal": "A cute puppy playing with a ball in a garden",
106
- "abstract": "An abstract digital art piece with vibrant colors and geometric shapes",
107
- "space": "A realistic view of Earth from space with the moon in the background",
108
- }
109
-
110
-
111
- def main():
112
- # Test OpenAI models
113
- generate_and_save_image("openai", "dall-e-2", prompts["landscape"])
114
- generate_and_save_image("openai", "dall-e-3", prompts["animal"])
115
-
116
- # Test with gpt-image-1 if available
117
- try:
118
- generate_and_save_image("openai", "gpt-image-1", prompts["abstract"])
119
- except Exception as e:
120
- print(f"gpt-image-1 test skipped: {str(e)}")
121
-
122
- # Test xAI models
123
- try:
124
- generate_and_save_image("xai", "grok-2-image", prompts["space"])
125
- except Exception as e:
126
- print(f"xAI test skipped: {str(e)}")
127
-
128
- # Test Google models
129
- try:
130
- generate_and_save_image(
131
- "google", "imagen-3.0-generate-002", prompts["abstract"]
132
- )
133
- except Exception as e:
134
- print(f"Google test skipped: {str(e)}")
135
-
136
- # Close the client
137
- client.close()
138
-
139
-
140
- if __name__ == "__main__":
141
- main()
@@ -1,163 +0,0 @@
1
- """
2
- Example script demonstrating image generation with different providers through indoxRouter.
3
-
4
- This script shows how to generate images using different providers (OpenAI, Google, xAI)
5
- with their provider-specific parameters and handling.
6
-
7
- Requirements:
8
- - Install indoxRouter: pip install indoxrouter
9
- - Set INDOX_ROUTER_API_KEY environment variable with your API key
10
- """
11
-
12
- import os
13
- import base64
14
- from io import BytesIO
15
- import requests
16
- from datetime import datetime
17
-
18
- from indoxrouter import Client
19
-
20
- # For displaying images in notebooks
21
- try:
22
- from IPython.display import Image, display
23
-
24
- in_notebook = True
25
- except ImportError:
26
- in_notebook = False
27
-
28
- # Initialize client with API key from environment variable
29
- api_key = os.environ.get("INDOX_ROUTER_API_KEY")
30
- if not api_key:
31
- print("Please set the INDOX_ROUTER_API_KEY environment variable")
32
- exit(1)
33
-
34
- client = Client(api_key=api_key)
35
-
36
-
37
- def save_image_from_url(url, filename):
38
- """Download and save an image from a URL."""
39
- response = requests.get(url)
40
- if response.status_code == 200:
41
- with open(filename, "wb") as f:
42
- f.write(response.content)
43
- print(f"Image saved to {filename}")
44
- else:
45
- print(f"Failed to download image: {response.status_code}")
46
-
47
-
48
- def save_image_from_b64(b64_data, filename):
49
- """Save an image from base64 data."""
50
- image_data = base64.b64decode(b64_data)
51
- with open(filename, "wb") as f:
52
- f.write(image_data)
53
- print(f"Image saved to {filename}")
54
-
55
-
56
- def display_response_image(response, provider, model):
57
- """Display image from response and save it."""
58
- try:
59
- if "data" in response and response["data"]:
60
- image_data = response["data"][0]
61
-
62
- # Create a timestamp for unique filenames
63
- timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
64
-
65
- if "url" in image_data and image_data["url"]:
66
- filename = f"{provider}_{model}_{timestamp}.png"
67
- save_image_from_url(image_data["url"], filename)
68
-
69
- # Display in notebook if possible
70
- if in_notebook:
71
- display(Image(url=image_data["url"]))
72
-
73
- elif "b64_json" in image_data and image_data["b64_json"]:
74
- filename = f"{provider}_{model}_{timestamp}.png"
75
- save_image_from_b64(image_data["b64_json"], filename)
76
-
77
- # Display in notebook if possible
78
- if in_notebook:
79
- display(Image(data=base64.b64decode(image_data["b64_json"])))
80
-
81
- # Check for revised prompt (DALL-E 3 often revises prompts)
82
- if "revised_prompt" in image_data and image_data["revised_prompt"]:
83
- print(f"Revised prompt: {image_data['revised_prompt']}")
84
- else:
85
- print("No image data found in response")
86
- except Exception as e:
87
- print(f"Error displaying/saving image: {str(e)}")
88
-
89
-
90
- def main():
91
- """Main function demonstrating image generation with different providers."""
92
-
93
- # Example prompt for all providers
94
- prompt = "A tranquil zen garden with cherry blossoms and a small pond"
95
-
96
- print("\n=== OpenAI (DALL-E 2) ===")
97
- print("Uses pixel dimensions (e.g., '1024x1024')")
98
- try:
99
- openai_response = client.images(
100
- prompt=prompt,
101
- model="openai/dall-e-2",
102
- size="1024x1024", # OpenAI uses pixel dimensions
103
- )
104
- print(f"Response received - Success: {openai_response.get('success', False)}")
105
- print(f"Cost: ${openai_response.get('usage', {}).get('cost', 0):.4f}")
106
- display_response_image(openai_response, "openai", "dall-e-2")
107
- except Exception as e:
108
- print(f"Error with OpenAI: {str(e)}")
109
-
110
- print("\n=== Google (Imagen) ===")
111
- print("Uses aspect ratios (e.g., '1:1', '16:9') instead of pixel dimensions")
112
- try:
113
- google_response = client.images(
114
- prompt=prompt,
115
- model="google/imagen-3.0-generate-002",
116
- # Note: Use 'aspect_ratio' instead of 'size' for Google
117
- aspect_ratio="1:1", # Google uses aspect ratios
118
- negative_prompt="cartoon, illustration, drawing, painting",
119
- )
120
- print(f"Response received - Success: {google_response.get('success', False)}")
121
- print(f"Cost: ${google_response.get('usage', {}).get('cost', 0):.4f}")
122
- display_response_image(google_response, "google", "imagen")
123
- except Exception as e:
124
- print(f"Error with Google: {str(e)}")
125
-
126
- print("\n=== xAI (Grok) ===")
127
- print("Does not use size parameter, only supports specific parameters")
128
- try:
129
- xai_response = client.images(
130
- prompt=prompt,
131
- model="xai/grok-2-image",
132
- # Note: xAI doesn't support size parameter, so we don't include it
133
- response_format="url", # xAI supports response_format
134
- )
135
- print(f"Response received - Success: {xai_response.get('success', False)}")
136
- print(f"Cost: ${xai_response.get('usage', {}).get('cost', 0):.4f}")
137
- display_response_image(xai_response, "xai", "grok-2-image")
138
- except Exception as e:
139
- print(f"Error with xAI: {str(e)}")
140
-
141
- # Advanced example with DALL-E 3
142
- print("\n=== OpenAI (DALL-E 3) with Advanced Parameters ===")
143
- try:
144
- dalle3_response = client.images(
145
- prompt="A beautiful underwater scene with coral reef and tropical fish",
146
- model="openai/dall-e-3",
147
- size="1024x1024",
148
- quality="standard", # 'standard' or 'hd'
149
- style="vivid", # 'vivid' or 'natural'
150
- response_format="url",
151
- )
152
- print(f"Response received - Success: {dalle3_response.get('success', False)}")
153
- print(f"Cost: ${dalle3_response.get('usage', {}).get('cost', 0):.4f}")
154
- display_response_image(dalle3_response, "openai", "dall-e-3")
155
- except Exception as e:
156
- print(f"Error with DALL-E 3: {str(e)}")
157
-
158
- # Close the client when done
159
- client.close()
160
-
161
-
162
- if __name__ == "__main__":
163
- main()
File without changes
File without changes
File without changes