diff --git a/openai_product_images/README.rst b/openai_product_images/README.rst index 8680d1da7..23e88f424 100644 --- a/openai_product_images/README.rst +++ b/openai_product_images/README.rst @@ -23,6 +23,7 @@ Company Credits ------- * Developer: Rosmy John @ cybrosys +* Developer: Nisarudheen @ cybrosys Contacts -------- diff --git a/openai_product_images/wizard/image_suggestion.py b/openai_product_images/wizard/image_suggestion.py index 269f8b006..f1571e471 100644 --- a/openai_product_images/wizard/image_suggestion.py +++ b/openai_product_images/wizard/image_suggestion.py @@ -9,83 +9,90 @@ # You can modify it under the terms of the GNU AFFERO # GENERAL PUBLIC LICENSE (AGPL v3), Version 3. # -# This program is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU AFFERO GENERAL PUBLIC LICENSE (AGPL v3) for more details. -# -# You should have received a copy of the GNU AFFERO GENERAL PUBLIC LICENSE -# (AGPL v3) along with this program. -# If not, see . -# ################################################################################ -import requests -from requests.structures import CaseInsensitiveDict -import json -import base64 from odoo import fields, models, _ -from odoo.exceptions import ValidationError +from odoo.exceptions import UserError, ValidationError +from urllib.request import urlopen +from openai import OpenAI +import base64 class ImageSuggestion(models.TransientModel): - """image for product from dalle""" + """Image generator for product from OpenAI DALL·E 3""" _name = 'image.suggestion' _rec_name = 'product_tmpl_id' - _description = 'model for creation of dalle image ' + _description = 'Model for creation of product images using DALL·E' - image_prompt = fields.Char(string="Prompt for image", - help="field to fill prompt", required=True) - product_tmpl_id = fields.Many2one('product.template', string="Product", - help="field to store product", - required=True) - num_image = fields.Integer(string="Number of image needed", - help="field to store number of image", - required=True, - default=1) + image_prompt = fields.Char( + string="Prompt for Image", + help="Describe the image you want to generate", + required=True + ) + product_tmpl_id = fields.Many2one( + 'product.template', + string="Product", + help="Select the product for which image needs to be generated", + required=True + ) + num_image = fields.Integer( + string="Number of Images", + help="Number of images to generate", + required=True, + default=1 + ) size_image = fields.Selection( - [('256x256', '256x256'), ('512x512', '512x512')], string="Resolution", - help="field to store image size", required=True) + [ + ('1024x1024', '1024x1024'), + ('1024x1792', '1024x1792 (Portrait)'), + ('1792x1024', '1792x1024 (Landscape)') + ], + string="Resolution", + help="Resolution of generated images", + required=True, + default='1024x1024' + ) + quality = fields.Selection( + [ + ('standard', 'Standard'), + ('hd', 'High Definition') + ], + string="Quality", + help="Image quality setting for DALL·E 3", + required=True, + default='standard' + ) def action_search(self): - """Summary: - Function to search image suggestion from dalle - Returns: - returns the created media image of corresponding product - """ - api_key = self.env['ir.config_parameter'].sudo().get_param( - 'openai_api_key') - if not api_key: - raise ValidationError( - _("Invalid API key provided. Please ensure that you have " - "entered the correct API key. ")) - headers = CaseInsensitiveDict() - headers["Content-Type"] = "application/json" - headers["Authorization"] = f"Bearer {api_key}" - data = '{"model": "dall-e-2",' \ - ' "prompt": "' + self.image_prompt + '", "num_images": ' + \ - str(self.num_image) + ', "size": "' \ - + self.size_image + '", "response_format": "url"}' - resp = requests.post("https://api.openai.com/v1/images/generations", - headers=headers, data=data) - if resp.status_code != 200: - raise ValidationError("Failed to generate image") - response_text = json.loads(resp.text) - for url in response_text['data']: - image_url = url['url'] - # Get image data and encode it in base64 - image_resp = requests.get(image_url) - if image_resp.status_code != 200: - raise ValidationError("Failed to retrieve image") - image_b64 = base64.b64encode(image_resp.content) - # Store encoded image as binary field on model - self.env['dalle.image.suggestion'].create( - {'product_image': image_b64, - 'product_tmpl_id': self.product_tmpl_id.id, }) - return { - 'name': self.product_tmpl_id.name, - 'view_mode': 'tree,form', - 'res_model': 'dalle.image.suggestion', - 'type': 'ir.actions.act_window', - 'domain': [('product_tmpl_id', '=', self.product_tmpl_id.id)], - 'target': 'current', - } + """Generate product images from OpenAI DALL·E 3""" + # Hardcoded API key as requested + api_key = self.env['ir.config_parameter'].sudo().get_param('openai_api_key') + + client = OpenAI(api_key=api_key) + try: + response = client.images.generate( + model="dall-e-3", + prompt=self.image_prompt, # Use image_prompt field + size=self.size_image, + quality=self.quality, + n=self.num_image, + ) + # Process the first image (DALL-E 3 typically returns one image) + image_url = response.data[0].url + image_content = urlopen(image_url).read() + image_b64_encoded = base64.b64encode(image_content) + + # Update the product's image_1920 field + self.product_tmpl_id.write({'image_1920': image_b64_encoded}) + + # Optionally store in dalle.image.suggestion (if needed for history) + self.env['dalle.image.suggestion'].create({ + 'product_image': image_b64_encoded, + 'product_tmpl_id': self.product_tmpl_id.id, + }) + + # Return action to close wizard or refresh product form + return { + 'type': 'ir.actions.act_window_close', + } + except Exception as e: + raise UserError(f"Error generating image: {str(e)}") \ No newline at end of file diff --git a/openai_product_images/wizard/image_suggestion_views.xml b/openai_product_images/wizard/image_suggestion_views.xml index 37b0e4af6..91167b85e 100644 --- a/openai_product_images/wizard/image_suggestion_views.xml +++ b/openai_product_images/wizard/image_suggestion_views.xml @@ -13,6 +13,7 @@ +