django-lucy-assist 0.1.0__py3-none-any.whl

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.
Files changed (44) hide show
  1. django_lucy_assist-0.1.0.dist-info/METADATA +206 -0
  2. django_lucy_assist-0.1.0.dist-info/RECORD +44 -0
  3. django_lucy_assist-0.1.0.dist-info/WHEEL +5 -0
  4. django_lucy_assist-0.1.0.dist-info/top_level.txt +1 -0
  5. lucy_assist/__init__.py +11 -0
  6. lucy_assist/admin.py +22 -0
  7. lucy_assist/apps.py +10 -0
  8. lucy_assist/conf.py +103 -0
  9. lucy_assist/constantes.py +120 -0
  10. lucy_assist/context_processors.py +65 -0
  11. lucy_assist/migrations/0001_initial.py +92 -0
  12. lucy_assist/migrations/__init__.py +0 -0
  13. lucy_assist/models/__init__.py +14 -0
  14. lucy_assist/models/base.py +54 -0
  15. lucy_assist/models/configuration.py +175 -0
  16. lucy_assist/models/conversation.py +54 -0
  17. lucy_assist/models/message.py +45 -0
  18. lucy_assist/models/project_context_cache.py +213 -0
  19. lucy_assist/services/__init__.py +21 -0
  20. lucy_assist/services/bug_notification_service.py +183 -0
  21. lucy_assist/services/claude_service.py +417 -0
  22. lucy_assist/services/context_service.py +350 -0
  23. lucy_assist/services/crud_service.py +364 -0
  24. lucy_assist/services/gitlab_service.py +248 -0
  25. lucy_assist/services/project_context_service.py +412 -0
  26. lucy_assist/services/tool_executor_service.py +343 -0
  27. lucy_assist/services/tools_definition.py +229 -0
  28. lucy_assist/signals.py +25 -0
  29. lucy_assist/static/lucy_assist/css/lucy-assist.css +160 -0
  30. lucy_assist/static/lucy_assist/image/icon-lucy.png +0 -0
  31. lucy_assist/static/lucy_assist/js/lucy-assist.js +824 -0
  32. lucy_assist/templates/lucy_assist/chatbot_sidebar.html +419 -0
  33. lucy_assist/templates/lucy_assist/partials/documentation_content.html +107 -0
  34. lucy_assist/tests/__init__.py +0 -0
  35. lucy_assist/tests/factories/__init__.py +15 -0
  36. lucy_assist/tests/factories/lucy_assist_factories.py +109 -0
  37. lucy_assist/tests/test_lucy_assist.py +186 -0
  38. lucy_assist/urls.py +36 -0
  39. lucy_assist/utils/__init__.py +7 -0
  40. lucy_assist/utils/log_utils.py +59 -0
  41. lucy_assist/utils/message_utils.py +130 -0
  42. lucy_assist/utils/token_utils.py +87 -0
  43. lucy_assist/views/__init__.py +13 -0
  44. lucy_assist/views/api_views.py +595 -0
@@ -0,0 +1,206 @@
1
+ Metadata-Version: 2.4
2
+ Name: django-lucy-assist
3
+ Version: 0.1.0
4
+ Summary: Assistant IA intelligent Revolucy pour outil métier
5
+ Author-email: Revolucy <hello@revolucy.fr>
6
+ Maintainer-email: Maxence <hello@revolucy.fr>
7
+ License: MIT
8
+ Project-URL: Homepage, https://github.com/revolucy/django-lucy-assist
9
+ Project-URL: Documentation, https://github.com/revolucy/django-lucy-assist#readme
10
+ Project-URL: Repository, https://github.com/revolucy/django-lucy-assist.git
11
+ Project-URL: Issues, https://github.com/revolucy/django-lucy-assist/issues
12
+ Keywords: django,chatbot,ai,claude,anthropic,assistant,crm
13
+ Classifier: Development Status :: 4 - Beta
14
+ Classifier: Environment :: Web Environment
15
+ Classifier: Framework :: Django
16
+ Classifier: Framework :: Django :: 4.2
17
+ Classifier: Framework :: Django :: 5.0
18
+ Classifier: Framework :: Django :: 5.1
19
+ Classifier: Intended Audience :: Developers
20
+ Classifier: License :: OSI Approved :: MIT License
21
+ Classifier: Operating System :: OS Independent
22
+ Classifier: Programming Language :: Python
23
+ Classifier: Programming Language :: Python :: 3
24
+ Classifier: Programming Language :: Python :: 3.10
25
+ Classifier: Programming Language :: Python :: 3.11
26
+ Classifier: Programming Language :: Python :: 3.12
27
+ Classifier: Topic :: Internet :: WWW/HTTP
28
+ Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
29
+ Requires-Python: >=3.10
30
+ Description-Content-Type: text/markdown
31
+ Requires-Dist: Django>=4.0
32
+ Requires-Dist: anthropic>=0.20.0
33
+ Requires-Dist: requests>=2.28.0
34
+ Provides-Extra: dev
35
+ Requires-Dist: pytest>=7.0.0; extra == "dev"
36
+ Requires-Dist: pytest-django>=4.5.0; extra == "dev"
37
+ Requires-Dist: factory-boy>=3.3.0; extra == "dev"
38
+ Requires-Dist: black>=23.0.0; extra == "dev"
39
+ Requires-Dist: isort>=5.12.0; extra == "dev"
40
+ Requires-Dist: flake8>=6.0.0; extra == "dev"
41
+ Provides-Extra: gitlab
42
+ Requires-Dist: python-gitlab>=3.15.0; extra == "gitlab"
43
+
44
+ # Django Lucy Assist
45
+
46
+ Assistant IA intelligent basé sur Claude d'Anthropic, intégrable dans n'importe quelle application Django.
47
+
48
+ ## Installation
49
+
50
+ ```bash
51
+ pip install django-lucy-assist
52
+ ```
53
+
54
+ ## Configuration
55
+
56
+ ### 1. Ajouter l'application à INSTALLED_APPS
57
+
58
+ ```python
59
+ INSTALLED_APPS = [
60
+ ...
61
+ 'lucy_assist',
62
+ ]
63
+ ```
64
+
65
+ ### 2. Configurer les variables d'environnement
66
+
67
+ Ajouter dans votre fichier `.env` :
68
+
69
+ ```bash
70
+ # ======================================== LUCY ASSIST ========================================
71
+ # Clé API Claude
72
+ ANTHROPIC_API_KEY=sk-ant-...
73
+
74
+ # Configuration GitLab pour l'analyse de bugs (optionnel)
75
+ GITLAB_URL=https://gitlab.example.com
76
+ GITLAB_TOKEN=glpat-...
77
+ GITLAB_PROJECT_ID=123
78
+
79
+ # SIREN client pour l'API Lucy CRM (Si non présent via le module de retour)
80
+ SIREN_CLIENT=123456789
81
+ ```
82
+
83
+ Puis dans votre `settings.py` :
84
+
85
+ ```python
86
+ import os
87
+
88
+ # Lucy Assist
89
+ ANTHROPIC_API_KEY = os.getenv('ANTHROPIC_API_KEY')
90
+ GITLAB_URL = os.getenv('GITLAB_URL')
91
+ GITLAB_TOKEN = os.getenv('GITLAB_TOKEN')
92
+ GITLAB_PROJECT_ID = os.getenv('GITLAB_PROJECT_ID')
93
+ SIREN_CLIENT = os.getenv('SIREN_CLIENT')
94
+
95
+ # Configuration avancée (optionnel)
96
+ LUCY_ASSIST = {
97
+ # Modèle de base personnalisé
98
+ 'BASE_MODEL': 'mon_app.models.MonModeleBase',
99
+ # Préfixe des apps du projet pour le mapping modèle -> app
100
+ 'PROJECT_APPS_PREFIX': 'apps.',
101
+ }
102
+ ```
103
+
104
+ ### 3. Ajouter les URLs
105
+
106
+ ```python
107
+ # urls.py
108
+ from django.urls import path, include
109
+
110
+ urlpatterns = [
111
+ ...
112
+ path('lucy-assist/', include('lucy_assist.urls')),
113
+ ]
114
+ ```
115
+
116
+ ### 4. Ajouter le context processor
117
+
118
+ ```python
119
+ # settings.py
120
+ TEMPLATES = [
121
+ {
122
+ ...
123
+ 'OPTIONS': {
124
+ 'context_processors': [
125
+ ...
126
+ 'lucy_assist.context_processors.lucy_assist_context',
127
+ ],
128
+ },
129
+ },
130
+ ]
131
+ ```
132
+
133
+ ### 5. Inclure le template dans votre base.html
134
+
135
+ ```html
136
+ <!-- templates/base.html -->
137
+ {% include 'lucy_assist/chatbot_sidebar.html' %}
138
+ ```
139
+
140
+ ### 6. Exécuter les migrations
141
+
142
+ ```bash
143
+ python manage.py migrate lucy_assist
144
+ ```
145
+
146
+ ## Utilisation
147
+
148
+ Une fois installé et configuré, Lucy Assist apparaîtra automatiquement sur toutes les pages de votre application avec un bouton flottant en bas à droite.
149
+
150
+ ### Fonctionnalités
151
+
152
+ - **Chat IA contextuel** : Lucy comprend le contexte de la page actuelle
153
+ - **Actions CRUD** : Lucy peut créer, modifier, rechercher et supprimer des objets
154
+ - **Analyse de bugs** : Connexion à GitLab pour analyser les problèmes signalés
155
+ - **Historique des conversations** : Sauvegarde automatique des conversations
156
+ - **Gestion des tokens** : Suivi de la consommation des tokens Claude
157
+
158
+ ## Configuration avancée
159
+
160
+ ### Modèle de base personnalisé
161
+
162
+ Si vous utilisez un modèle de base personnalisé avec des champs d'audit (created_date, updated_date, etc.), vous pouvez le configurer :
163
+
164
+ ```python
165
+ LUCY_ASSIST = {
166
+ 'BASE_MODEL': 'mon_app.models.MonModeleBase',
167
+ }
168
+ ```
169
+
170
+ ### Personnalisation des questions fréquentes
171
+
172
+ ```python
173
+ LUCY_ASSIST = {
174
+ 'QUESTIONS_FREQUENTES_DEFAULT': [
175
+ "Comment créer un nouveau membre ?",
176
+ "Comment effectuer un paiement ?",
177
+ "Comment exporter des données ?",
178
+ ],
179
+ }
180
+ ```
181
+
182
+ ## API
183
+
184
+ Lucy Assist expose plusieurs endpoints API :
185
+
186
+ - `GET /lucy-assist/api/conversations/` - Liste des conversations
187
+ - `POST /lucy-assist/api/conversations/` - Créer une conversation
188
+ - `GET /lucy-assist/api/conversations/<id>/` - Détail d'une conversation
189
+ - `POST /lucy-assist/api/conversations/<id>/messages/` - Ajouter un message
190
+ - `POST /lucy-assist/api/conversations/<id>/completion/` - Générer une réponse (streaming)
191
+ - `GET /lucy-assist/api/tokens/status/` - Statut des tokens
192
+
193
+ ## Licence
194
+
195
+ [Revolucy](https://www.revolucy.fr)
196
+
197
+ ## Versionning
198
+
199
+ - V1.0.0 | Création du module Lucy
200
+
201
+ ## Déploiement Pypi
202
+
203
+ 1. `pip install build twine`
204
+ 2. `python -m build`
205
+ 3. `python -m twine upload dist/*`
206
+ 4. Indiquer le token présent dans 1Password
@@ -0,0 +1,44 @@
1
+ lucy_assist/__init__.py,sha256=vTA2UPlEX6UiMaOIpDAPAKife5f2KyDOhxGiTQu5lio,335
2
+ lucy_assist/admin.py,sha256=-hNfuwuMfxgZVFQc_ODy6WcyZPxrM_8TfKsRMd0fj38,694
3
+ lucy_assist/apps.py,sha256=zHZtlBXs5ML4CKtGg7xDyptSWzLfB1ks2VvbXF50hdo,264
4
+ lucy_assist/conf.py,sha256=S24BxpkMrT54YfYgQcFjgNZY8y_wu8u7wfKcegUaH1Q,3535
5
+ lucy_assist/constantes.py,sha256=YppDWi1DQueMwJk3jmeGPDi-UTmSUUDSwR6sW7QzBn4,4083
6
+ lucy_assist/context_processors.py,sha256=mDrr9G5XztDfJLGq_75X1rkJbVI5De08ys_pW3y12Dw,2210
7
+ lucy_assist/signals.py,sha256=aQA84oe9JNL72eeV5kURTTV-9CcQpqakDle1Lv3dnFY,861
8
+ lucy_assist/urls.py,sha256=Qr8jJjEyC_EFGAeiZnjhgTc-9P4Y-TqKDaYicWRp_GQ,1451
9
+ lucy_assist/migrations/0001_initial.py,sha256=_3ARg4hFA76pfrJV7RI6nMNaygwcCL5JA_-21LGroWQ,5015
10
+ lucy_assist/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
+ lucy_assist/models/__init__.py,sha256=JQMr50P94sBrKwwcNArRE_qnk7dLnknMKCabeRLskJc,415
12
+ lucy_assist/models/base.py,sha256=Ql2AY7bzvcxZhxsPdCpbVEKvtWD-NBkHTLYZX4TjT3s,1532
13
+ lucy_assist/models/configuration.py,sha256=oFVIh2RYl1TmutXBmjH3xGg7TFw_EHeJ_C9qZdZopwg,6300
14
+ lucy_assist/models/conversation.py,sha256=psx2AQtQ5SFP-AJD7wbGabpXXLIGYngdVZfeoTlgKtQ,1849
15
+ lucy_assist/models/message.py,sha256=kf-ffMtLYNFhXYUrB3QSL97KKDJUOMrKaPjKeOcJa_o,1492
16
+ lucy_assist/models/project_context_cache.py,sha256=Bnb0VU7pv7QEvjOI6JSLEPvL4BxskCQ0ojWGxO7YDSM,6530
17
+ lucy_assist/services/__init__.py,sha256=I0brW674WNIKkGHj2lj4sGEDD7HUAr5Z254dsbirdLk,691
18
+ lucy_assist/services/bug_notification_service.py,sha256=BkY-xqeC153j6p5GWrc70W5jBKkBFD2Zx68qguNUOrU,6999
19
+ lucy_assist/services/claude_service.py,sha256=QJIo983cSQ0k_9IKxYB50DxlRDJGPuEbrFGdzs6hl2c,15873
20
+ lucy_assist/services/context_service.py,sha256=GaZzUHNlJf9-0Mas4_nfi2RgycNLoWjYHCJxCoiwUnA,11997
21
+ lucy_assist/services/crud_service.py,sha256=E8-xRxPXXbUuPakGXPsbZfImEJWZx4BZq5DhM5q2I08,11436
22
+ lucy_assist/services/gitlab_service.py,sha256=uH83fwRSCwiRItznENpYQG4aPckjafYIV9z6OChUrZg,8056
23
+ lucy_assist/services/project_context_service.py,sha256=bIuqTanc59gP_BLod3oQgWplxpiCgByg-kbUMe_57CQ,14053
24
+ lucy_assist/services/tool_executor_service.py,sha256=fXLH4Aaip-HPX1nNRs8UQ1N77rGloBahSwOR9gPmjfU,13583
25
+ lucy_assist/services/tools_definition.py,sha256=xUJCtFZ1uROxB7jNHY0X75fs5nzFAKr4VpSHtKgepxU,8974
26
+ lucy_assist/static/lucy_assist/css/lucy-assist.css,sha256=VLsebnECg36dOykBldJALBKHW3CZUfukz_nq94rKklI,3333
27
+ lucy_assist/static/lucy_assist/image/icon-lucy.png,sha256=FOYlwXAt40Gr9jsWFmhgPivYOBFWKeYW0lxJI5Up-GM,6710
28
+ lucy_assist/static/lucy_assist/js/lucy-assist.js,sha256=dmXtSPQ38LisoRWZd3R1Ms6OvVaEk3OrYKcVM0OMb_Q,28207
29
+ lucy_assist/templates/lucy_assist/chatbot_sidebar.html,sha256=ptShZL89SPH4xk0RvFJheoZLJ-kWDSiPMvEqpbvnQVI,19827
30
+ lucy_assist/templates/lucy_assist/partials/documentation_content.html,sha256=byA2EvQT1GaMB5yTQHNt5ZfJKEew9_LxutU8s5muM9s,4143
31
+ lucy_assist/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
32
+ lucy_assist/tests/test_lucy_assist.py,sha256=KBvuED10_gOJWdaRS2zMigM3W5Kp00KhMEwaR8tvhUc,6949
33
+ lucy_assist/tests/factories/__init__.py,sha256=cDkgr4aPFKwbPo6JLY2s22pHrGWPI_vqG4IafWAhSmE,376
34
+ lucy_assist/tests/factories/lucy_assist_factories.py,sha256=Mz1EN7xtMpIDJPNMledDbjR6X6dsBNv7JWczjD9-_MQ,3674
35
+ lucy_assist/utils/__init__.py,sha256=FnL0QF7pyhjHCOywVAkZq3dl4IEgT39prJk1FtXMBDc,129
36
+ lucy_assist/utils/log_utils.py,sha256=gdjaKg5PNUYlDVCQNFXQJG3vsLKay_aWX6AJxoHtiG4,1720
37
+ lucy_assist/utils/message_utils.py,sha256=kABNVlfJTzmbRTVdauKPN5HVRqyw352xu_rlQrb279Q,3323
38
+ lucy_assist/utils/token_utils.py,sha256=rxe9jHjcRJcaIlcw0QuVmYXOjscTsUsxnhhI6RMBzDM,2608
39
+ lucy_assist/views/__init__.py,sha256=uUPYpuHlBC8j7zKS_DDoWjwpCpRnOIXETY-S2-Ss0cY,288
40
+ lucy_assist/views/api_views.py,sha256=C8Ftut7qNSauzFNoZ4yPMhiADeEma7aiqrQrN9Gx9Yk,23281
41
+ django_lucy_assist-0.1.0.dist-info/METADATA,sha256=Otc1eK9jUnClf5Jy63wgJmAOcmjuMnfBpA20a3Totlw,5752
42
+ django_lucy_assist-0.1.0.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
43
+ django_lucy_assist-0.1.0.dist-info/top_level.txt,sha256=T-UCiwpn5yF3Oem3234TUpSVnEgbkrM2rGz9Tz5N-QA,12
44
+ django_lucy_assist-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.10.2)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ lucy_assist
@@ -0,0 +1,11 @@
1
+ """
2
+ Lucy Assist - Assistant IA intelligent pour applications Django.
3
+
4
+ Un chatbot IA basé sur Claude d'Anthropic, intégrable dans n'importe quelle
5
+ application Django pour fournir une assistance contextuelle aux utilisateurs.
6
+ """
7
+
8
+ __version__ = '0.1.0'
9
+ __author__ = 'Revolucy'
10
+
11
+ default_app_config = 'lucy_assist.apps.LucyAssistConfig'
lucy_assist/admin.py ADDED
@@ -0,0 +1,22 @@
1
+ from django.contrib import admin
2
+
3
+ from lucy_assist.models import Conversation, Message, ConfigurationLucyAssist
4
+
5
+
6
+ class BlockMessage(admin.StackedInline):
7
+ model = Message
8
+ extra = 1
9
+
10
+
11
+ @admin.register(Conversation)
12
+ class ConversationAdmin(admin.ModelAdmin):
13
+ list_display = ('id', 'utilisateur', 'titre', 'created_date', 'is_active')
14
+ list_filter = ('is_active', 'created_date')
15
+ search_fields = ('utilisateur__email', 'titre')
16
+ ordering = ('-created_date',)
17
+ inlines = [BlockMessage]
18
+
19
+
20
+ @admin.register(ConfigurationLucyAssist)
21
+ class ConfigurationLucyAssistAdmin(admin.ModelAdmin):
22
+ list_display = ('id', 'tokens_disponibles', 'prix_par_million_tokens', 'updated_date')
lucy_assist/apps.py ADDED
@@ -0,0 +1,10 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class LucyAssistConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "lucy_assist"
7
+ verbose_name = "Lucy Assist - Chatbot IA"
8
+
9
+ def ready(self):
10
+ import lucy_assist.signals # noqa
lucy_assist/conf.py ADDED
@@ -0,0 +1,103 @@
1
+ """
2
+ Configuration de Lucy Assist.
3
+ Permet de personnaliser le comportement via les settings Django.
4
+ """
5
+ from django.conf import settings
6
+
7
+
8
+ class LucyAssistSettings:
9
+ """
10
+ Classe de configuration pour Lucy Assist.
11
+ Lit les settings depuis LUCY_ASSIST dans settings.py.
12
+ """
13
+
14
+ # Valeurs par défaut
15
+ DEFAULTS = {
16
+ # Modèle de base pour les modèles Lucy Assist (None = utilise le modèle par défaut)
17
+ # Peut être une string "mon_app.models.MonModele" ou une classe directement
18
+ 'BASE_MODEL': None,
19
+
20
+ # Clé API Claude (peut aussi être définie via ANTHROPIC_API_KEY)
21
+ 'CLAUDE_API_KEY': None,
22
+
23
+ # Modèle Claude à utiliser
24
+ 'CLAUDE_MODEL': 'claude-sonnet-4-20250514',
25
+
26
+ # Configuration GitLab pour l'analyse de bugs
27
+ 'GITLAB_URL': None,
28
+ 'GITLAB_TOKEN': None,
29
+ 'GITLAB_PROJECT_ID': None,
30
+
31
+ # SIREN du client pour l'API Lucy CRM
32
+ 'SIREN_CLIENT': None,
33
+
34
+ # Email de fallback pour les feedbacks
35
+ 'FEEDBACK_EMAIL': 'support@revolucy.fr',
36
+
37
+ # Préfixe des apps du projet pour le mapping modèle -> app
38
+ # Ex: 'apps.' pour filtrer les apps commençant par 'apps.'
39
+ 'PROJECT_APPS_PREFIX': None,
40
+
41
+ # URL de base de l'API Lucy CRM
42
+ 'LUCY_CRM_API_URL': 'https://app.lucy-crm.fr',
43
+
44
+ # Prix par million de tokens (en euros)
45
+ 'PRIX_PAR_MILLION_TOKENS': 10.0,
46
+
47
+ # Nombre moyen de tokens par conversation
48
+ 'TOKENS_MOYENS_PAR_CONVERSATION': 2000,
49
+
50
+ # Questions fréquentes par défaut
51
+ 'QUESTIONS_FREQUENTES_DEFAULT': [
52
+ "Comment créer un nouveau membre ?",
53
+ "Comment effectuer un paiement ?",
54
+ "Comment exporter des données ?",
55
+ "Comment modifier mon profil ?",
56
+ "Où trouver la liste des adhésions ?",
57
+ ],
58
+ }
59
+
60
+ def __init__(self):
61
+ self._settings = getattr(settings, 'LUCY_ASSIST', {})
62
+
63
+ def __getattr__(self, name):
64
+ if name in self.DEFAULTS:
65
+ # Vérifier d'abord dans LUCY_ASSIST settings
66
+ if name in self._settings:
67
+ return self._settings[name]
68
+
69
+ # Cas spéciaux pour les settings qui peuvent être définis au niveau global
70
+ if name == 'CLAUDE_API_KEY':
71
+ # Chercher dans plusieurs variables possibles
72
+ return (
73
+ getattr(settings, 'CLAUDE_LUCY_ASSIST_API_KEY', None) or
74
+ getattr(settings, 'ANTHROPIC_API_KEY', None) or
75
+ self.DEFAULTS[name]
76
+ )
77
+
78
+ if name == 'SIREN_CLIENT':
79
+ return getattr(settings, 'SIREN_CLIENT', None) or self.DEFAULTS[name]
80
+
81
+ if name == 'GITLAB_URL':
82
+ return getattr(settings, 'GITLAB_URL', None) or self.DEFAULTS[name]
83
+
84
+ if name == 'GITLAB_TOKEN':
85
+ return getattr(settings, 'GITLAB_TOKEN', None) or self.DEFAULTS[name]
86
+
87
+ if name == 'GITLAB_PROJECT_ID':
88
+ return getattr(settings, 'GITLAB_PROJECT_ID', None) or self.DEFAULTS[name]
89
+
90
+ return self.DEFAULTS[name]
91
+
92
+ raise AttributeError(f"'{type(self).__name__}' object has no attribute '{name}'")
93
+
94
+ def get(self, name, default=None):
95
+ """Récupère une valeur de configuration avec une valeur par défaut."""
96
+ try:
97
+ return getattr(self, name)
98
+ except AttributeError:
99
+ return default
100
+
101
+
102
+ # Instance singleton des settings
103
+ lucy_assist_settings = LucyAssistSettings()
@@ -0,0 +1,120 @@
1
+ """
2
+ Constantes pour Lucy Assist
3
+ """
4
+
5
+
6
+ class LucyAssistConstantes:
7
+ """Constantes générales de Lucy Assist"""
8
+
9
+ # Prix par million de tokens (en euros)
10
+ PRIX_PAR_MILLION_TOKENS = 10.0
11
+
12
+ # Nombre moyen de tokens par conversation
13
+ TOKENS_MOYENS_PAR_CONVERSATION = 2000
14
+
15
+ # Nombre de conversations estimées pour 1 million de tokens
16
+ CONVERSATIONS_PAR_MILLION = 500 # 1_000_000 / 2000
17
+
18
+ class Repondant:
19
+ """Types de répondants dans une conversation"""
20
+ UTILISATEUR = 'UTILISATEUR'
21
+ CHATBOT = 'CHATBOT'
22
+
23
+ tuples = [
24
+ (UTILISATEUR, 'Utilisateur'),
25
+ (CHATBOT, 'Lucy Assist'),
26
+ ]
27
+
28
+ class TypeAction:
29
+ """Types d'actions que Lucy Assist peut effectuer"""
30
+ AIDE_NAVIGATION = 'AIDE_NAVIGATION'
31
+ RECHERCHE = 'RECHERCHE'
32
+ CRUD = 'CRUD'
33
+ ANALYSE_BUG = 'ANALYSE_BUG'
34
+ EXPLICATION = 'EXPLICATION'
35
+
36
+ tuples = [
37
+ (AIDE_NAVIGATION, 'Aide à la navigation'),
38
+ (RECHERCHE, 'Recherche d\'objets'),
39
+ (CRUD, 'Création/Modification/Suppresion d\'objets'),
40
+ (ANALYSE_BUG, 'Analyse de bug'),
41
+ (EXPLICATION, 'Explication de fonctionnalité'),
42
+ ]
43
+
44
+ class StatutConversation:
45
+ """Statuts possibles d'une conversation"""
46
+ ACTIVE = 'ACTIVE'
47
+ ARCHIVEE = 'ARCHIVEE'
48
+
49
+ tuples = [
50
+ (ACTIVE, 'Active'),
51
+ (ARCHIVEE, 'Archivée'),
52
+ ]
53
+
54
+ # Prompts système pour Claude
55
+ SYSTEM_PROMPTS = {
56
+ 'default': """Tu es Lucy, un assistant IA intégré dans un CRM métier (UNAF-CRM).
57
+ Tu as la capacité d'EXÉCUTER des actions directement dans l'application grâce aux tools disponibles.
58
+
59
+ ## COMPORTEMENT PRIORITAIRE - ACTION FIRST
60
+
61
+ RÈGLE FONDAMENTALE : Quand l'utilisateur te demande de faire quelque chose (créer, modifier, rechercher, supprimer),
62
+ tu dois EXÉCUTER L'ACTION IMMÉDIATEMENT en utilisant les tools disponibles.
63
+
64
+ ❌ NE FAIS PAS : Expliquer comment faire, rediriger vers une page, dire que tu ne peux pas
65
+ ✅ FAIS : Utiliser le tool approprié pour exécuter l'action demandée
66
+
67
+ ## Exemples de comportement attendu
68
+
69
+ Utilisateur : "Crée un membre Maxence Dupont"
70
+ → Tu utilises le tool create_object avec les données {{"nom": "Dupont", "prenom": "Maxence"}}
71
+
72
+ Utilisateur : "Cherche les membres de Paris"
73
+ → Tu utilises le tool search_objects avec query="Paris" et model_name="Membre"
74
+
75
+ Utilisateur : "Modifie l'adresse du membre 42"
76
+ → Tu utilises le tool update_object avec l'object_id et les nouvelles données
77
+
78
+ ## Quand NE PAS agir directement
79
+
80
+ - Si l'utilisateur demande explicitement "comment faire" ou "explique-moi"
81
+ - Si tu n'as pas assez d'informations (dans ce cas, demande les infos manquantes)
82
+ - Pour les suppressions : demande une confirmation avant d'exécuter
83
+
84
+ ## Contexte de la page actuelle
85
+ {page_context}
86
+
87
+ ## Permissions de l'utilisateur
88
+ {user_permissions}
89
+
90
+ ## Modèles principaux disponibles
91
+ - Membre (membre) : nom, prenom, email, telephone, adresse, structure
92
+ - Structure (structure) : nom, adresse, type, siret
93
+ - Adhesion (adhesion) : membre, structure, date_debut, date_fin, montant
94
+ - Paiement (paiement) : membre, montant, date, mode_paiement
95
+
96
+ ## Format de réponse après action
97
+
98
+ Après avoir exécuté une action, confirme brièvement :
99
+ "✅ [Action effectuée] - [Détail bref]"
100
+
101
+ Exemple : "✅ Membre créé - Maxence Dupont (ID: 123)"
102
+ """,
103
+ 'crud': """Tu dois aider l'utilisateur à créer ou modifier un objet.
104
+ Formulaire disponible : {form_info}
105
+ Champs requis : {required_fields}
106
+ """,
107
+ 'bug_analysis': """Analyse le problème signalé par l'utilisateur.
108
+ Code source pertinent : {code_context}
109
+ Erreur rapportée : {error_message}
110
+ """,
111
+ }
112
+
113
+ # Questions fréquentes par défaut (utilisées si non configurées dans le modèle)
114
+ QUESTIONS_FREQUENTES_DEFAULT = [
115
+ "Comment créer un nouveau membre ?",
116
+ "Comment effectuer un paiement ?",
117
+ "Comment exporter des données ?",
118
+ "Comment modifier mon profil ?",
119
+ "Où trouver la liste des adhésions ?",
120
+ ]
@@ -0,0 +1,65 @@
1
+ """
2
+ Context Processors pour Lucy Assist.
3
+
4
+ Ces fonctions injectent automatiquement les données Lucy Assist
5
+ dans le contexte de tous les templates Django.
6
+ """
7
+ from django.conf import settings
8
+
9
+ from lucy_assist.models import ConfigurationLucyAssist
10
+
11
+
12
+ def lucy_assist_context(request):
13
+ """
14
+ Context processor pour injecter Lucy Assist dans toutes les pages.
15
+
16
+ Ajoute au contexte:
17
+ - lucy_assist_enabled: bool indiquant si Lucy Assist est activé
18
+ - lucy_assist_config: configuration de Lucy Assist
19
+ - lucy_assist_user_has_conversations: bool si l'utilisateur a des conversations
20
+
21
+ Usage dans template:
22
+ {% if lucy_assist_enabled %}
23
+ {% include "chatbot_sidebar.html" %}
24
+ {% endif %}
25
+ """
26
+ context = {
27
+ 'lucy_assist_enabled': False,
28
+ 'lucy_assist_config': None,
29
+ 'lucy_assist_user_has_conversations': False,
30
+ }
31
+
32
+ # Vérifier si l'utilisateur est authentifié
33
+ if not request.user.is_authenticated:
34
+ return context
35
+
36
+ try:
37
+ # Récupérer la configuration
38
+ config = ConfigurationLucyAssist.get_config()
39
+
40
+ # Vérifier si Lucy Assist est configuré (clé API présente)
41
+ api_key_configured = bool(getattr(settings, 'CLAUDE_LUCY_ASSIST_API_KEY', ''))
42
+
43
+ if config and config.actif:
44
+ context['lucy_assist_enabled'] = True
45
+ context['lucy_assist_config'] = {
46
+ 'tokens_disponibles': config.tokens_disponibles,
47
+ 'tokens_en_euros': round(config.tokens_restants_en_euros, 2),
48
+ 'conversations_estimees': config.conversations_estimees,
49
+ 'actif': config.actif,
50
+ 'api_configured': api_key_configured,
51
+ 'avatar_url': config.avatar.url if config.avatar else None,
52
+ }
53
+
54
+ # Vérifier si l'utilisateur a des conversations
55
+ from lucy_assist.models import Conversation
56
+ context['lucy_assist_user_has_conversations'] = Conversation.objects.filter(
57
+ utilisateur=request.user,
58
+ is_active=True
59
+ ).exists()
60
+
61
+ except Exception:
62
+ # En cas d'erreur, Lucy Assist reste désactivé
63
+ pass
64
+
65
+ return context