mgbam commited on
Commit
ae9e00c
·
verified ·
1 Parent(s): fe7d37a

Update core/image_services.py

Browse files
Files changed (1) hide show
  1. core/image_services.py +107 -112
core/image_services.py CHANGED
@@ -1,132 +1,127 @@
1
  # storyverse_weaver/core/image_services.py
2
  import os
3
- import requests # For generic API calls
4
  import base64
5
  from io import BytesIO
6
  from PIL import Image
7
- # from dotenv import load_dotenv
8
- # load_dotenv()
9
 
10
- # --- API Key Configuration (Use specific names for StoryVerse) ---
11
  STABILITY_API_KEY = os.getenv("STORYVERSE_STABILITY_API_KEY")
12
- OPENAI_API_KEY = os.getenv("STORYVERSE_OPENAI_API_KEY") # For DALL-E
13
- # HUGGINGFACE_TOKEN also used by llm_services, can be reused if using HF image models
14
 
15
  STABILITY_API_CONFIGURED = bool(STABILITY_API_KEY and STABILITY_API_KEY.strip())
16
  OPENAI_DALLE_CONFIGURED = bool(OPENAI_API_KEY and OPENAI_API_KEY.strip())
17
- # HF_IMAGE_CONFIGURED = bool(HF_TOKEN and HF_TOKEN.strip()) # Assuming HF_TOKEN is also for image models
18
 
19
- class ImageGenResponse:
20
- def __init__(self, image: Image.Image = None, image_url: str = None, error: str = None, success: bool = True, provider: str = "unknown"):
21
- self.image = image # PIL Image object
22
- self.image_url = image_url # If API returns a URL
23
- self.error = error
24
- self.success = success
25
- self.provider = provider
26
 
27
- def initialize_image_llms(): # Simple function to print status
 
 
 
 
 
 
 
28
  print("INFO: image_services.py - Initializing Image Generation services...")
29
- if STABILITY_API_CONFIGURED: print("SUCCESS: image_services.py - Stability AI API Key detected.")
30
- else: print("WARNING: image_services.py - STORYVERSE_STABILITY_API_KEY not found. Stability AI disabled.")
31
- if OPENAI_DALLE_CONFIGURED: print("SUCCESS: image_services.py - OpenAI API Key detected (for DALL-E).")
32
- else: print("WARNING: image_services.py - STORYVERSE_OPENAI_API_KEY not found. DALL-E disabled.")
33
- # if HF_IMAGE_CONFIGURED: print("INFO: image_services.py - Hugging Face Token detected (can be used for HF image models).")
34
- print("INFO: image_services.py - Image LLM Init complete.")
35
-
36
-
37
- # --- Stability AI (Example) ---
38
- def generate_image_stabilityai(prompt: str, style_preset: str = None, negative_prompt: str = None,
39
- engine_id: str = "stable-diffusion-xl-1024-v1-0",
40
- steps: int = 30, cfg_scale: float = 7.0,
41
- width: int = 1024, height: int = 1024) -> ImageGenResponse:
42
- if not STABILITY_API_CONFIGURED:
43
- return ImageGenResponse(error="Stability AI API key not configured.", success=False, provider="StabilityAI")
44
-
45
- api_host = os.getenv('API_HOST', 'https://api.stability.ai')
46
- request_url = f"{api_host}/v1/generation/{engine_id}/text-to-image"
47
-
48
- payload = {
49
- "text_prompts": [{"text": prompt}],
50
- "cfg_scale": cfg_scale,
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
51
  "height": height,
52
  "width": width,
53
- "steps": steps,
54
- "samples": 1,
55
  }
56
- if style_preset: payload["style_preset"] = style_preset
57
- if negative_prompt: payload["text_prompts"].append({"text": negative_prompt, "weight": -1.0})
58
 
59
- headers = {
60
- "Accept": "application/json",
61
- "Content-Type": "application/json",
62
- "Authorization": f"Bearer {STABILITY_API_KEY}"
63
- }
64
- print(f"DEBUG: image_services.py - Calling Stability AI with prompt: {prompt[:50]}...")
65
  try:
66
- response = requests.post(request_url, headers=headers, json=payload, timeout=60) # Increased timeout
67
- response.raise_for_status() # Will raise an HTTPError if the HTTP request returned an unsuccessful status code
68
-
69
- artifacts = response.json().get("artifacts")
70
- if not artifacts:
71
- return ImageGenResponse(error="No image artifacts found in Stability AI response.", success=False, provider="StabilityAI", raw_response=response.text)
72
-
73
- image_data = base64.b64decode(artifacts[0]["base64"])
74
- image = Image.open(BytesIO(image_data))
75
- print("DEBUG: image_services.py - Stability AI image generated successfully.")
76
- return ImageGenResponse(image=image, provider="StabilityAI")
77
- except requests.exceptions.RequestException as e:
78
- error_msg = f"Stability AI API request failed: {type(e).__name__} - {str(e)}"
79
- if hasattr(e, 'response') and e.response is not None: error_msg += f" - Response: {e.response.text[:200]}"
80
- print(f"ERROR: image_services.py - {error_msg}")
81
- return ImageGenResponse(error=error_msg, success=False, provider="StabilityAI", raw_response=e)
82
- except Exception as e: # Catch other potential errors like JSON decoding
83
- error_msg = f"Error processing Stability AI response: {type(e).__name__} - {str(e)}"
84
- print(f"ERROR: image_services.py - {error_msg}")
85
- return ImageGenResponse(error=error_msg, success=False, provider="StabilityAI", raw_response=e)
86
 
 
 
87
 
88
- # --- DALL-E (Conceptual - you'd need 'openai' library and setup) ---
89
- def generate_image_dalle(prompt: str, size="1024x1024", quality="standard", n=1) -> ImageGenResponse:
90
- if not OPENAI_DALLE_CONFIGURED:
91
- return ImageGenResponse(error="OpenAI DALL-E API key not configured.", success=False, provider="DALL-E")
92
- try:
93
- # from openai import OpenAI # Would be imported at top level
94
- # client = OpenAI(api_key=OPENAI_API_KEY)
95
- # response = client.images.generate(
96
- # model="dall-e-3", # or "dall-e-2"
97
- # prompt=prompt,
98
- # size=size,
99
- # quality=quality,
100
- # n=n,
101
- # response_format="url" # or "b64_json"
102
- # )
103
- # image_url = response.data[0].url
104
- # image_content = requests.get(image_url).content
105
- # image = Image.open(BytesIO(image_content))
106
- # return ImageGenResponse(image=image, image_url=image_url, provider="DALL-E")
107
- print("DEBUG: image_services.py - DALL-E call placeholder.") # Placeholder
108
- # Simulate an image for now
109
- dummy_image = Image.new('RGB', (512, 512), color = 'skyblue')
110
- return ImageGenResponse(image=dummy_image, provider="DALL-E (Simulated)")
111
- except Exception as e:
112
- return ImageGenResponse(error=f"DALL-E API Error: {type(e).__name__} - {str(e)}", success=False, provider="DALL-E")
113
-
114
-
115
- # --- Hugging Face Image Model (Conceptual - via Inference API or local Diffusers) ---
116
- # def generate_image_hf_model(prompt: str, model_id="stabilityai/stable-diffusion-xl-base-1.0") -> ImageGenResponse:
117
- # if not HF_IMAGE_CONFIGURED:
118
- # return ImageGenResponse(error="HF Token not configured for image models.", success=False, provider="HF")
119
- # try:
120
- # You might use a client similar to hf_inference_text_client but for image generation task
121
- # Or if it's a diffusers pipeline, you'd load and run it.
122
- # This requires the `diffusers` library and often significant compute.
123
- # response_bytes = hf_some_image_client.text_to_image(prompt, model=model_id) # Hypothetical client method
124
- # image = Image.open(BytesIO(response_bytes))
125
- # return ImageGenResponse(image=image, provider=f"HF ({model_id})")
126
- # print("DEBUG: image_services.py - HF Image Model call placeholder.")
127
- # dummy_image = Image.new('RGB', (512, 512), color = 'lightgreen')
128
- # return ImageGenResponse(image=dummy_image, provider=f"HF ({model_id} - Simulated)")
129
- # except Exception as e:
130
- # return ImageGenResponse(error=f"HF Image Model Error: {type(e).__name__} - {str(e)}", success=False, provider=f"HF ({model_id})")
131
-
132
- print("DEBUG: core.image_services (for StoryVerseWeaver) - Module defined.")
 
1
  # storyverse_weaver/core/image_services.py
2
  import os
3
+ import requests
4
  import base64
5
  from io import BytesIO
6
  from PIL import Image
7
+ from huggingface_hub import InferenceClient # Ensure this is imported
 
8
 
9
+ # --- API Key Configuration ---
10
  STABILITY_API_KEY = os.getenv("STORYVERSE_STABILITY_API_KEY")
11
+ OPENAI_API_KEY = os.getenv("STORYVERSE_OPENAI_API_KEY")
12
+ HF_TOKEN = os.getenv("STORYVERSE_HF_TOKEN") # Reuse from llm_services or get it here
13
 
14
  STABILITY_API_CONFIGURED = bool(STABILITY_API_KEY and STABILITY_API_KEY.strip())
15
  OPENAI_DALLE_CONFIGURED = bool(OPENAI_API_KEY and OPENAI_API_KEY.strip())
16
+ HF_IMAGE_API_CONFIGURED = bool(HF_TOKEN and HF_TOKEN.strip()) # New flag
17
 
18
+ hf_inference_image_client = None # Separate client instance for image tasks if needed, or reuse
 
 
 
 
 
 
19
 
20
+ class ImageGenResponse: # Keep this class
21
+ def __init__(self, image: Image.Image = None, image_url: str = None, error: str = None, success: bool = True, provider: str = "unknown", model_id_used: str = None):
22
+ self.image, self.image_url, self.error, self.success, self.provider, self.model_id_used = \
23
+ image, image_url, error, success, provider, model_id_used
24
+
25
+ def initialize_image_llms():
26
+ global STABILITY_API_CONFIGURED, OPENAI_DALLE_CONFIGURED, HF_IMAGE_API_CONFIGURED, hf_inference_image_client
27
+
28
  print("INFO: image_services.py - Initializing Image Generation services...")
29
+ # Stability AI (as before)
30
+ if STABILITY_API_KEY and STABILITY_API_KEY.strip():
31
+ STABILITY_API_CONFIGURED = True
32
+ print("SUCCESS: image_services.py - Stability AI API Key detected.")
33
+ else:
34
+ STABILITY_API_CONFIGURED = False
35
+ print("WARNING: image_services.py - STORYVERSE_STABILITY_API_KEY not found. Stability AI disabled.")
36
+
37
+ # OpenAI DALL-E (as before)
38
+ if OPENAI_API_KEY and OPENAI_API_KEY.strip():
39
+ OPENAI_DALLE_CONFIGURED = True
40
+ print("SUCCESS: image_services.py - OpenAI API Key detected (for DALL-E).")
41
+ else:
42
+ OPENAI_DALLE_CONFIGURED = False
43
+ print("WARNING: image_services.py - STORYVERSE_OPENAI_API_KEY not found. DALL-E disabled.")
44
+
45
+ # Hugging Face Image Models
46
+ if HF_TOKEN and HF_TOKEN.strip():
47
+ try:
48
+ # You can use the same token for text and image clients if the permissions cover it
49
+ # Or, if you want a dedicated client for image tasks (maybe different default model types)
50
+ hf_inference_image_client = InferenceClient(token=HF_TOKEN) # Reusing the token
51
+ HF_IMAGE_API_CONFIGURED = True
52
+ print("SUCCESS: image_services.py - Hugging Face InferenceClient (for images) ready.")
53
+ except Exception as e:
54
+ HF_IMAGE_API_CONFIGURED = False
55
+ print(f"ERROR: image_services.py - Failed to initialize HF InferenceClient for images: {e}")
56
+ else:
57
+ HF_IMAGE_API_CONFIGURED = False
58
+ print("WARNING: image_services.py - STORYVERSE_HF_TOKEN not found. HF Image models disabled.")
59
+
60
+ print("INFO: image_services.py - Image Service Init complete.")
61
+
62
+
63
+ # --- Stability AI (Keep as is, it will just be disabled if no key) ---
64
+ def generate_image_stabilityai(prompt: str, ...) -> ImageGenResponse:
65
+ # ... (your existing generate_image_stabilityai function)
66
+ if not STABILITY_API_CONFIGURED: return ImageGenResponse(error="Stability AI API key not configured.", success=False, provider="StabilityAI")
67
+ # ... rest of the function
68
+ api_host = os.getenv('API_HOST', 'https://api.stability.ai'); request_url = f"{api_host}/v1/generation/{engine_id if 'engine_id' in locals() else 'stable-diffusion-xl-1024-v1-0'}/text-to-image"; payload = {"text_prompts": [{"text": prompt}], "steps": steps if 'steps' in locals() else 30}; headers = {"Authorization": f"Bearer {STABILITY_API_KEY}", "Accept":"application/json", "Content-Type":"application/json"}; try: response = requests.post(request_url, headers=headers, json=payload, timeout=60); response.raise_for_status(); artifacts = response.json().get("artifacts"); img_data = base64.b64decode(artifacts[0]["base64"]); img = Image.open(BytesIO(img_data)); return ImageGenResponse(image=img, provider="StabilityAI")
69
+ except Exception as e: return ImageGenResponse(error=f"Stability AI Error: {str(e)}", success=False, provider="StabilityAI", raw_response=e)
70
+
71
+
72
+ # --- DALL-E (Keep as is, conceptual) ---
73
+ def generate_image_dalle(prompt: str, ...) -> ImageGenResponse:
74
+ # ... (your existing generate_image_dalle function)
75
+ if not OPENAI_DALLE_CONFIGURED: return ImageGenResponse(error="OpenAI DALL-E API key not configured.", success=False, provider="DALL-E")
76
+ dummy_image = Image.new('RGB', (512, 512), color = 'skyblue'); return ImageGenResponse(image=dummy_image, provider="DALL-E (Simulated)")
77
+
78
+
79
+ # --- NEW: Hugging Face Image Model via Inference API ---
80
+ def generate_image_hf_model(prompt: str,
81
+ model_id: str = "stabilityai/stable-diffusion-xl-base-1.0", # A popular choice
82
+ # model_id: str = "runwayml/stable-diffusion-v1-5", # Another option
83
+ # model_id: str = "prompthero/openjourney", # Midjourney-like style
84
+ negative_prompt: str = None,
85
+ height: int = 768, # Adjust for different models
86
+ width: int = 768,
87
+ num_inference_steps: int = 25,
88
+ guidance_scale: float = 7.5
89
+ ) -> ImageGenResponse:
90
+ global hf_inference_image_client # Use the initialized client
91
+ if not HF_IMAGE_API_CONFIGURED or not hf_inference_image_client:
92
+ return ImageGenResponse(error="Hugging Face API (for images) not configured.", success=False, provider="HF Image API", model_id_used=model_id)
93
+
94
+ params = {
95
+ "negative_prompt": negative_prompt,
96
  "height": height,
97
  "width": width,
98
+ "num_inference_steps": num_inference_steps,
99
+ "guidance_scale": guidance_scale
100
  }
101
+ # Remove None params as some models might not like them
102
+ params = {k: v for k, v in params.items() if v is not None}
103
 
104
+ print(f"DEBUG: image_services.py - Calling HF Image API ({model_id}) with prompt: {prompt[:50]}...")
 
 
 
 
 
105
  try:
106
+ # The `text_to_image` method of InferenceClient returns a PIL Image directly
107
+ image_result: Image.Image = hf_inference_image_client.text_to_image(
108
+ prompt,
109
+ model=model_id,
110
+ **params
111
+ )
112
+ print(f"DEBUG: image_services.py - HF Image API ({model_id}) image generated successfully.")
113
+ return ImageGenResponse(image=image_result, provider="HF Image API", model_id_used=model_id)
114
+ except Exception as e:
115
+ error_msg = f"HF Image API Error ({model_id}): {type(e).__name__} - {str(e)}"
116
+ # Check for common HF API errors
117
+ if "Rate limit reached" in str(e):
118
+ error_msg += " You may have hit free tier limits."
119
+ elif "Model is currently loading" in str(e):
120
+ error_msg += " The model might be loading, please try again in a moment."
121
+ elif "Authorization header is correct" in str(e) or "401" in str(e):
122
+ error_msg += " Issue with your HF_TOKEN authentication."
 
 
 
123
 
124
+ print(f"ERROR: image_services.py - {error_msg}")
125
+ return ImageGenResponse(error=error_msg, success=False, provider="HF Image API", model_id_used=model_id, raw_response=e)
126
 
127
+ print("DEBUG: core.image_services (for StoryVerseWeaver) - Module defined with HF Image support.")