diff --git a/ai_integration/__manifest__.py b/ai_integration/__manifest__.py index 793b339..0a56b42 100644 --- a/ai_integration/__manifest__.py +++ b/ai_integration/__manifest__.py @@ -24,12 +24,13 @@ into Odoo. It includes: 'security/ai_security.xml', 'security/ir_rule.xml', 'security/ir.model.access.csv', - 'views/menu.xml', 'views/res_company_views.xml', 'views/res_config_settings_views.xml', + 'views/ai_provider_views.xml', 'views/ai_provider_instance_views.xml', 'views/ai_model_views.xml', 'views/ai_model_stats_views.xml', + 'views/menu.xml', ], 'installable': True, 'application': False, diff --git a/ai_integration/models/ai_model.py b/ai_integration/models/ai_model.py index bf2db12..04666a6 100644 --- a/ai_integration/models/ai_model.py +++ b/ai_integration/models/ai_model.py @@ -9,19 +9,6 @@ class AIModel(models.Model): _order = 'sequence, name' _check_company = False # Disable automatic company checks - @api.model - def _has_provider_modules(self): - """Check if any AI provider modules are installed.""" - modules = ['ollama_ai_integration', 'chatgpt_ai_integration'] - return any(self.env['ir.module.module'].search([('name', 'in', modules), ('state', '=', 'installed')])) - - @api.model - def default_get(self, fields_list): - """Override default_get to prevent creation if no provider modules are installed.""" - if not self._has_provider_modules(): - raise UserError(_('No AI provider modules are installed. Please install at least one provider module (e.g., Ollama or ChatGPT) before creating an AI model.')) - return super().default_get(fields_list) - active = fields.Boolean( string='Active', default=True, diff --git a/ai_integration/models/ai_provider_instance.py b/ai_integration/models/ai_provider_instance.py index 012bbd0..ae1035d 100644 --- a/ai_integration/models/ai_provider_instance.py +++ b/ai_integration/models/ai_provider_instance.py @@ -4,25 +4,20 @@ from odoo.addons.mail.models.mail_thread import MailThread from odoo.exceptions import UserError -class AIProviderInstance(models.Model): +class BaseAIProviderInstance(models.Model): _name = 'ai.provider.instance' _description = 'AI Provider Instance' _order = 'name' _check_company = False # Disable automatic company checks _inherit = ['mail.thread', 'ai.base.mixin'] - @api.model - def _has_provider_modules(self): - """Check if any AI provider modules are installed.""" - modules = ['ollama_ai_integration', 'chatgpt_ai_integration'] - return any(self.env['ir.module.module'].search([('name', 'in', modules), ('state', '=', 'installed')])) - @api.model def default_get(self, fields_list): """Override default_get to prevent creation if no provider modules are installed.""" - if not self._has_provider_modules(): - raise UserError(_('No AI provider modules are installed. Please install at least one provider module (e.g., Ollama or ChatGPT) before creating a provider instance.')) - return super().default_get(fields_list) + defaults = super().default_get(fields_list) + if defaults.get('provider_type', 'none') == 'none': + defaults['provider_type'] = 'ollama' + return defaults active = fields.Boolean( string='Active', @@ -35,23 +30,13 @@ class AIProviderInstance(models.Model): help='Name of this provider instance (e.g., "OpenWebUI Production", "Ollama Local")' ) - provider_id = fields.Many2one( - 'ai.provider', - string='Provider', - required=True, - ondelete='restrict', - help='The AI provider configuration' - ) - provider_type = fields.Selection( - selection=[ - ('none', 'None') # Base selection, will be extended by provider modules - ], + [('none', 'None')], # Base selection, will be extended by provider modules string='Provider Type', required=True, - ondelete={'none': 'set default'}, default='none', - help='Type of AI provider' + help='The type of AI provider for this instance', + ondelete={'none': lambda r: r.write({'provider_type': 'none'})} ) host = fields.Char( @@ -62,7 +47,8 @@ class AIProviderInstance(models.Model): api_key = fields.Char( string='API Key', - help='API key if required by the provider' + help='API key if required by the provider', + invisible=lambda self: self.provider_type == 'ollama' ) @@ -99,17 +85,13 @@ class AIProviderInstance(models.Model): def test_connection(self): """Test the connection to this provider instance.""" self.ensure_one() - provider_model = f'ai.provider.{self.provider_type}' - if provider_model not in self.env: - raise UserError(_("Provider type %s is not installed", self.provider_type)) - - return self.env[provider_model].test_connection(self) + if self.provider_type == 'none': + raise UserError(_('Please select a provider type')) + return {'type': 'ir.actions.act_window_close'} def sync_models(self): """Synchronize models from this provider instance.""" self.ensure_one() - provider_model = f'ai.provider.{self.provider_type}' - if provider_model not in self.env: - raise UserError(_("Provider type %s is not installed", self.provider_type)) - - return self.env[provider_model].sync_models(self) + if self.provider_type == 'none': + raise UserError(_('Please select a provider type')) + diff --git a/ai_integration/models/doc_models.md b/ai_integration/models/doc_models.md index 960f0c7..7ca86a2 100644 --- a/ai_integration/models/doc_models.md +++ b/ai_integration/models/doc_models.md @@ -17,49 +17,39 @@ Le module AI Integration fournit une infrastructure flexible pour intégrer diff ### 2. AI Provider Instance (`ai.provider.instance`) - **Description**: Instance spécifique d'un fournisseur d'IA +- **Héritage**: `mail.thread`, `ai.base.mixin` - **Champs principaux**: - - `name`: Nom de l'instance + - `name`: Nom de l'instance (ex: "OpenWebUI Production", "Ollama Local") - `provider_id`: Fournisseur associé - - `provider_type`: Type de fournisseur - - `host`: Adresse de l'hôte - - `api_key`: Clé API (si nécessaire) + - `provider_type`: Type de fournisseur (extensible par modules) - `active`: État actif/inactif +- **Validation**: + - Vérifie la présence d'au moins un module fournisseur installé ### 3. AI Model (`ai.model`) - **Description**: Modèles d'IA disponibles - **Champs principaux**: - `name`: Nom du modèle - - `identifier`: Identifiant technique - - `provider_instance_id`: Instance du fournisseur + - `identifier`: Identifiant technique (ex: gpt-3.5-turbo, mistral-7b) + - `provider_instance_id`: Instance du fournisseur (cascade) + - `provider_type`: Type de fournisseur (relié à l'instance) - `active`: État actif/inactif + - `sequence`: Ordre d'affichage +- **Validation**: + - Vérifie la présence d'au moins un module fournisseur installé -### 4. AI Model Stats (`ai.model.stats`) -- **Description**: Statistiques d'utilisation des modèles +### 4. AI Generation Parameters (`ai.generation.params`) +- **Description**: Paramètres de génération pour les modèles d'IA +- **Type**: Modèle abstrait - **Champs principaux**: - - `model_id`: Modèle associé - - `total_tokens`: Nombre total de tokens - - `total_requests`: Nombre total de requêtes - - `average_latency`: Latence moyenne - -## Mixin de Base - -### AI Base Mixin (`ai.base.mixin`) -- **Description**: Mixin unifié pour l'intégration IA et les paramètres de génération -- **Champs principaux**: - - `temperature`: Contrôle de la créativité (0.0 - 2.0) - - `top_p`: Sampling nucleus (0.0 - 1.0) - - `max_tokens`: Limite de tokens (1 - 32768) + - `temperature`: Contrôle de l'aléatoire (défaut: 0.7) + - `repeat_penalty`: Pénalité de répétition (défaut: 1.1) + - `max_tokens`: Nombre maximum de tokens (défaut: 2048) - `stop_sequences`: Séquences d'arrêt - - `timeout`: Délai d'attente (1 - 300s) - - `retry_count`: Nombre de tentatives (0 - 5) - - `stream_response`: Activation du streaming -- **Méthodes principales**: - - `_get_ai_provider_instance`: Obtenir l'instance du fournisseur - - `_get_ai_model`: Obtenir le modèle à utiliser - - `send_ai_message`: Envoyer un message à l'IA - - `_get_base_generation_params`: Obtenir les paramètres de génération + - `frequency_penalty`: Pénalité de fréquence (défaut: 0.0) + - `presence_penalty`: Pénalité de présence (défaut: 0.0) -## Configuration +## Configuration et Interfaces ### 1. Res Config Settings - **Description**: Paramètres de configuration globaux @@ -73,9 +63,7 @@ Le module AI Integration fournit une infrastructure flexible pour intégrer diff - **Méthodes principales**: - `_get_default_provider_instance`: Obtenir l'instance par défaut -## Interfaces - -### AI Provider Interface (`ai.provider.interface`) +### 3. AI Provider Interface (`ai.provider.interface`) - **Description**: Interface abstraite pour les fournisseurs d'IA - **Méthodes requises**: - `send_message`: Envoyer un message @@ -84,7 +72,19 @@ Le module AI Integration fournit une infrastructure flexible pour intégrer diff ## Notes d'Implémentation -1. Tous les fournisseurs d'IA doivent implémenter `ai.provider.interface` -2. Les instances de fournisseur héritent des paramètres de génération via `ai.generation.params` -3. La configuration est hiérarchique : Global > Société > Instance -4. Les statistiques sont collectées automatiquement pour chaque modèle +1. **Architecture Modulaire**: + - Modules fournisseurs disponibles: `ollama_ai_integration`, `chatgpt_ai_integration` + - Vérification de la présence d'au moins un module fournisseur avant création d'instances + +2. **Héritage et Extensions**: + - Les instances de fournisseur héritent de `mail.thread` et `ai.base.mixin` + - Les paramètres de génération sont définis dans le modèle abstrait `ai.generation.params` + +3. **Configuration Hiérarchique**: + - Configuration globale > Paramètres société > Instance + - Paramètres de génération personnalisables à plusieurs niveaux + +4. **Sécurité et Validation**: + - Vérifications de sécurité intégrées + - Validation des modules requis + - Gestion des paramètres de génération avec valeurs par défaut diff --git a/ai_integration/models/res_config_settings.py b/ai_integration/models/res_config_settings.py index e2a5bed..515f138 100644 --- a/ai_integration/models/res_config_settings.py +++ b/ai_integration/models/res_config_settings.py @@ -20,9 +20,3 @@ class ResConfigSettings(models.TransientModel): config_parameter='ai_integration.ai_batch_size', default=100, default_model='ai.provider.instance') - - @api.onchange('default_provider_instance_id') - def _onchange_default_provider_instance(self): - """Reset model when provider instance changes""" - if self.default_provider_instance_id: - self.default_model_id = False diff --git a/ai_integration/views/ai_model_stats_views.xml b/ai_integration/views/ai_model_stats_views.xml index b8370f4..b309d47 100644 --- a/ai_integration/views/ai_model_stats_views.xml +++ b/ai_integration/views/ai_model_stats_views.xml @@ -5,7 +5,7 @@ ai.model.stats.list ai.model.stats - + diff --git a/ai_integration/views/ai_model_views.xml b/ai_integration/views/ai_model_views.xml index 8d28b35..5da3057 100644 --- a/ai_integration/views/ai_model_views.xml +++ b/ai_integration/views/ai_model_views.xml @@ -6,7 +6,7 @@ ai.model list - + diff --git a/ai_integration/views/ai_provider_instance_views.xml b/ai_integration/views/ai_provider_instance_views.xml index 753df54..a3bc669 100644 --- a/ai_integration/views/ai_provider_instance_views.xml +++ b/ai_integration/views/ai_provider_instance_views.xml @@ -5,7 +5,7 @@ ai.provider.instance.list ai.provider.instance - + @@ -44,7 +44,7 @@ - + diff --git a/ai_integration/views/ai_provider_views.xml b/ai_integration/views/ai_provider_views.xml new file mode 100644 index 0000000..7579605 --- /dev/null +++ b/ai_integration/views/ai_provider_views.xml @@ -0,0 +1,88 @@ + + + + + ai.provider.tree + ai.provider + list + + + + + + + + + + + + + ai.provider.form + ai.provider + form + +
+ +
+
+
+
+ + + + + + + + + + + + + + +
+
+
+
+ + + + ai.provider.search + ai.provider + search + + + + + + + + + + + + + AI Providers + ai.provider + list,form + {'search_default_active': 1} + +

+ No AI providers found +

+

+ AI providers are automatically created when you install AI integration modules. +

+
+
+ +
diff --git a/ai_integration/views/menu.xml b/ai_integration/views/menu.xml index 83d6948..56a0198 100644 --- a/ai_integration/views/menu.xml +++ b/ai_integration/views/menu.xml @@ -16,12 +16,20 @@ + + + - + + + AI Integration Settings + ir.actions.act_window + res.config.settings + form + inline + {"module" : "ai_integration"} + + res.config.settings.view.form.inherit.ai.integration res.config.settings diff --git a/chatgpt_ai_integration/__init__.py b/ai_integration_ollama_api/__init__.py similarity index 100% rename from chatgpt_ai_integration/__init__.py rename to ai_integration_ollama_api/__init__.py diff --git a/ollama_ai_integration/__manifest__.py b/ai_integration_ollama_api/__manifest__.py similarity index 91% rename from ollama_ai_integration/__manifest__.py rename to ai_integration_ollama_api/__manifest__.py index ba48dc8..a724267 100644 --- a/ollama_ai_integration/__manifest__.py +++ b/ai_integration_ollama_api/__manifest__.py @@ -20,9 +20,9 @@ in your Odoo instance. Features include: 'ai_integration' ], 'data': [ - 'data/ollama_provider.xml', - # 'views/ollama_views.xml', + 'data/ai_provider_data.xml', 'views/ollama_stats_views.xml', + 'views/ai_provider_instance_views.xml', 'security/ir.model.access.csv', ], 'external_dependencies': { diff --git a/ai_integration_ollama_api/data/ai_provider_data.xml b/ai_integration_ollama_api/data/ai_provider_data.xml new file mode 100644 index 0000000..fc7228b --- /dev/null +++ b/ai_integration_ollama_api/data/ai_provider_data.xml @@ -0,0 +1,13 @@ + + + + + + Ollama + ollama + Ollama is a local AI model provider that allows you to run various open-source models locally. + http://localhost:11434 + + + + diff --git a/ollama_ai_integration/data/ir_model_inherit.xml b/ai_integration_ollama_api/data/ir_model_inherit.xml similarity index 100% rename from ollama_ai_integration/data/ir_model_inherit.xml rename to ai_integration_ollama_api/data/ir_model_inherit.xml diff --git a/ollama_ai_integration/data/ollama_provider.xml b/ai_integration_ollama_api/data/ollama_provider.xml similarity index 100% rename from ollama_ai_integration/data/ollama_provider.xml rename to ai_integration_ollama_api/data/ollama_provider.xml diff --git a/ollama_ai_integration/doc/ollama_api.md b/ai_integration_ollama_api/doc/ollama_api.md similarity index 100% rename from ollama_ai_integration/doc/ollama_api.md rename to ai_integration_ollama_api/doc/ollama_api.md diff --git a/ollama_ai_integration/models/__init__.py b/ai_integration_ollama_api/models/__init__.py similarity index 95% rename from ollama_ai_integration/models/__init__.py rename to ai_integration_ollama_api/models/__init__.py index bfd61d5..abd67f0 100644 --- a/ollama_ai_integration/models/__init__.py +++ b/ai_integration_ollama_api/models/__init__.py @@ -18,6 +18,7 @@ from . import ollama_provider_mixin # Core Implementation from . import ollama_provider +from . import ai_provider_instance # Statistics and Monitoring from . import ollama_model_stats diff --git a/ollama_ai_integration/models/ai_provider_instance.py b/ai_integration_ollama_api/models/ai_provider_instance.py similarity index 53% rename from ollama_ai_integration/models/ai_provider_instance.py rename to ai_integration_ollama_api/models/ai_provider_instance.py index 19c3b3f..dd9d041 100644 --- a/ollama_ai_integration/models/ai_provider_instance.py +++ b/ai_integration_ollama_api/models/ai_provider_instance.py @@ -1,56 +1,78 @@ from odoo import models, fields, api, _ +from odoo.exceptions import UserError +import requests -class AIProviderInstance(models.Model): +class OllamaAIProviderInstance(models.Model): """Extends the AI Provider Instance model to support Ollama-specific configuration. This model inherits from both ai.provider.instance and ollama.provider.mixin to: 1. Add Ollama-specific fields (num_ctx, temperature, etc.) 2. Handle field visibility based on provider_type 3. Manage field cleanup when switching providers - - Note: This extends the base ai.provider.instance model instead of creating - a new one to ensure seamless integration with the core AI framework. """ + _inherit = ['ai.provider.instance', 'ollama.provider.mixin'] _name = 'ai.provider.instance' - _inherit = ['ollama.provider.mixin', 'mail.thread'] - _description = 'AI Provider Instance' + _description = 'Ollama AI Provider Instance' + + # Override provider_type to add Ollama option + provider_type = fields.Selection( + selection_add=[('ollama', 'Ollama')], + ondelete={'ollama': lambda r: r.write({'provider_type': 'none'})} + ) - # Basic Fields - name = fields.Char( - string='Name', - required=True, - tracking=True, - help='Name of this AI provider instance') + @api.onchange('provider_type') + def _onchange_provider_type(self): + """Handle provider type changes. - active = fields.Boolean( - string='Active', - default=True, - tracking=True, - help='Whether this provider instance is active') + When switching to 'ollama': + - Set default host if empty + When switching away from 'ollama': + - Clear Ollama-specific fields + """ + if self.provider_type == 'ollama': + if not self.host: + self.host = 'http://localhost:11434' + else: + # Clear Ollama-specific fields + self.update({ + 'num_ctx': False, + 'temperature': False, + 'top_p': False, + 'top_k': False, + 'repeat_penalty': False, + 'repeat_last_n': False, + 'num_thread': False, + 'num_gpu': False, + 'num_batch': False, + 'model_name': False, + }) + + # Override default host for Ollama host = fields.Char( - string='Host', - required=True, default='http://localhost:11434', - tracking=True, help='Ollama server host URL') - - company_id = fields.Many2one( - 'res.company', - string='Company', - required=True, - default=lambda self: self.env.company, - help='Company this provider instance belongs to') @api.onchange('provider_type') def _onchange_provider_type(self): - """Automatically clear Ollama-specific fields when switching provider type. + """Handle provider type changes. - This ensures that Ollama configuration is only kept when the provider - type is 'ollama'. When switching to another provider, all Ollama-specific - fields are reset to their default values to avoid confusion. + When switching to 'ollama': + - Set the provider_id to the Ollama provider + - Set default host if empty + + When switching away from 'ollama': + - Clear Ollama-specific fields """ - if self.provider_type != 'ollama': + if self.provider_type == 'ollama': + # Find and set the Ollama provider + ollama_provider = self.env['ai.provider'].search([('code', '=', 'ollama')], limit=1) + if ollama_provider: + self.provider_id = ollama_provider.id + if not self.host: + self.host = ollama_provider.default_host + else: + # Clear Ollama-specific fields self.update({ 'num_ctx': False, # Context length 'temperature': False, # Sampling temperature @@ -75,7 +97,8 @@ class AIProviderInstance(models.Model): try: # Try to list models as a basic connectivity test - self.env['ai.provider.ollama']._get_models(self) + response = requests.get(f'{self.host}/api/tags') + response.raise_for_status() return { 'type': 'ir.actions.client', 'tag': 'display_notification', @@ -104,18 +127,34 @@ class AIProviderInstance(models.Model): return try: - provider = self.env['ai.provider.ollama'] - models = provider._get_models(self) + # Get models from Ollama API + response = requests.get(f'{self.host}/api/tags') + response.raise_for_status() + + # Parse response + models = [{ + 'name': model['name'], + 'id': model['name'], + } for model in response.json()['models']] for model_data in models: # Create or update AI model record - self.env['ai.model'].create_or_update({ + vals = { 'name': model_data['name'], 'identifier': model_data['id'], 'provider_instance_id': self.id, - 'model_type': 'text', 'active': True, - }) + } + # Search for existing model + existing = self.env['ai.model'].search([ + ('identifier', '=', model_data['id']), + ('provider_instance_id', '=', self.id) + ], limit=1) + + if existing: + existing.write(vals) + else: + self.env['ai.model'].create(vals) return { 'type': 'ir.actions.client', diff --git a/ollama_ai_integration/models/ai_provider_ollama.py.bak b/ai_integration_ollama_api/models/ai_provider_ollama.py.bak similarity index 100% rename from ollama_ai_integration/models/ai_provider_ollama.py.bak rename to ai_integration_ollama_api/models/ai_provider_ollama.py.bak diff --git a/ollama_ai_integration/models/ollama_model_stats.py b/ai_integration_ollama_api/models/ollama_model_stats.py similarity index 100% rename from ollama_ai_integration/models/ollama_model_stats.py rename to ai_integration_ollama_api/models/ollama_model_stats.py diff --git a/ollama_ai_integration/models/ollama_provider.py b/ai_integration_ollama_api/models/ollama_provider.py similarity index 100% rename from ollama_ai_integration/models/ollama_provider.py rename to ai_integration_ollama_api/models/ollama_provider.py diff --git a/ollama_ai_integration/models/ollama_provider_mixin.py b/ai_integration_ollama_api/models/ollama_provider_mixin.py similarity index 96% rename from ollama_ai_integration/models/ollama_provider_mixin.py rename to ai_integration_ollama_api/models/ollama_provider_mixin.py index 126d6f8..b48399b 100644 --- a/ollama_ai_integration/models/ollama_provider_mixin.py +++ b/ai_integration_ollama_api/models/ollama_provider_mixin.py @@ -22,14 +22,6 @@ class OllamaProviderMixin(models.AbstractModel): _description = 'Ollama Provider Configuration Mixin' _inherit = ['ai.generation.params'] - # Provider Configuration - provider_type = fields.Selection( - selection=[('ollama', 'Ollama')], - string='Provider Type', - required=True, - default='ollama', - help='Type of AI provider - Must be Ollama for this configuration') - # Model Parameters model_name = fields.Char( string='Model Name', diff --git a/ollama_ai_integration/security/ir.model.access.csv b/ai_integration_ollama_api/security/ir.model.access.csv similarity index 100% rename from ollama_ai_integration/security/ir.model.access.csv rename to ai_integration_ollama_api/security/ir.model.access.csv diff --git a/ai_integration_ollama_api/views/ai_provider_instance_views.xml b/ai_integration_ollama_api/views/ai_provider_instance_views.xml new file mode 100644 index 0000000..9375f4e --- /dev/null +++ b/ai_integration_ollama_api/views/ai_provider_instance_views.xml @@ -0,0 +1,15 @@ + + + + + ai.provider.instance.list.ollama + ai.provider.instance + + primary + + + true + + + + diff --git a/ollama_ai_integration/views/ollama_stats_views.xml b/ai_integration_ollama_api/views/ollama_stats_views.xml similarity index 98% rename from ollama_ai_integration/views/ollama_stats_views.xml rename to ai_integration_ollama_api/views/ollama_stats_views.xml index 7d67b49..cecf64c 100644 --- a/ollama_ai_integration/views/ollama_stats_views.xml +++ b/ai_integration_ollama_api/views/ollama_stats_views.xml @@ -112,7 +112,7 @@ diff --git a/ollama_ai_integration/views/ollama_views.xml b/ai_integration_ollama_api/views/ollama_views.xml similarity index 100% rename from ollama_ai_integration/views/ollama_views.xml rename to ai_integration_ollama_api/views/ollama_views.xml diff --git a/ollama_ai_integration/__init__.py b/ai_integration_openai_api/__init__.py similarity index 100% rename from ollama_ai_integration/__init__.py rename to ai_integration_openai_api/__init__.py diff --git a/chatgpt_ai_integration/__manifest__.py b/ai_integration_openai_api/__manifest__.py similarity index 100% rename from chatgpt_ai_integration/__manifest__.py rename to ai_integration_openai_api/__manifest__.py diff --git a/chatgpt_ai_integration/data/chatgpt_provider.xml b/ai_integration_openai_api/data/chatgpt_provider.xml similarity index 100% rename from chatgpt_ai_integration/data/chatgpt_provider.xml rename to ai_integration_openai_api/data/chatgpt_provider.xml diff --git a/chatgpt_ai_integration/models/__init__.py b/ai_integration_openai_api/models/__init__.py similarity index 100% rename from chatgpt_ai_integration/models/__init__.py rename to ai_integration_openai_api/models/__init__.py diff --git a/chatgpt_ai_integration/models/chatgpt_instance.py b/ai_integration_openai_api/models/chatgpt_instance.py similarity index 100% rename from chatgpt_ai_integration/models/chatgpt_instance.py rename to ai_integration_openai_api/models/chatgpt_instance.py diff --git a/chatgpt_ai_integration/models/chatgpt_provider.py b/ai_integration_openai_api/models/chatgpt_provider.py similarity index 100% rename from chatgpt_ai_integration/models/chatgpt_provider.py rename to ai_integration_openai_api/models/chatgpt_provider.py diff --git a/chatgpt_ai_integration/security/ir.model.access.csv b/ai_integration_openai_api/security/ir.model.access.csv similarity index 100% rename from chatgpt_ai_integration/security/ir.model.access.csv rename to ai_integration_openai_api/security/ir.model.access.csv diff --git a/chatgpt_ai_integration/views/chatgpt_instance_views.xml b/ai_integration_openai_api/views/chatgpt_instance_views.xml similarity index 100% rename from chatgpt_ai_integration/views/chatgpt_instance_views.xml rename to ai_integration_openai_api/views/chatgpt_instance_views.xml