django-lucy-assist 1.2.1__py3-none-any.whl → 1.2.3__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.
- {django_lucy_assist-1.2.1.dist-info → django_lucy_assist-1.2.3.dist-info}/METADATA +1 -1
- {django_lucy_assist-1.2.1.dist-info → django_lucy_assist-1.2.3.dist-info}/RECORD +11 -9
- lucy_assist/__init__.py +1 -1
- lucy_assist/admin.py +49 -11
- lucy_assist/constantes.py +7 -7
- lucy_assist/migrations/0005_configurationlucyassist_project_context.py +22 -0
- lucy_assist/migrations/0006_remove_configurationlucyassist_prompt_complementaire.py +17 -0
- lucy_assist/models/configuration.py +130 -14
- lucy_assist/signals.py +0 -15
- {django_lucy_assist-1.2.1.dist-info → django_lucy_assist-1.2.3.dist-info}/WHEEL +0 -0
- {django_lucy_assist-1.2.1.dist-info → django_lucy_assist-1.2.3.dist-info}/top_level.txt +0 -0
|
@@ -1,19 +1,21 @@
|
|
|
1
|
-
lucy_assist/__init__.py,sha256=
|
|
2
|
-
lucy_assist/admin.py,sha256=
|
|
1
|
+
lucy_assist/__init__.py,sha256=9NTQKOljcruDMZjj1WQhcSRRjLbrx61jyaTuhXpk9ds,325
|
|
2
|
+
lucy_assist/admin.py,sha256=CFVBPmuFRIJzxc2pZ9s3LK1kdxMhSbLVA022VgbH89Y,4734
|
|
3
3
|
lucy_assist/apps.py,sha256=zHZtlBXs5ML4CKtGg7xDyptSWzLfB1ks2VvbXF50hdo,264
|
|
4
4
|
lucy_assist/conf.py,sha256=RgtZSrUwHZjjbEGZqQvifvC4GNdICmhty2XetfvAbls,3992
|
|
5
|
-
lucy_assist/constantes.py,sha256=
|
|
5
|
+
lucy_assist/constantes.py,sha256=9L2VGBK0HorJoNDGdwQlhEfT75W-xNPAhtS0-qgawBs,3947
|
|
6
6
|
lucy_assist/context_processors.py,sha256=tnzil4CEJwtExuQGLyRzIEuwpQfnwJ-eMgkkR6zNgSg,2200
|
|
7
|
-
lucy_assist/signals.py,sha256=
|
|
7
|
+
lucy_assist/signals.py,sha256=i3Uj9v-0zyAIROFl86fLlwaqRqQizL9_CpWmVjJbk8g,863
|
|
8
8
|
lucy_assist/urls.py,sha256=Qr8jJjEyC_EFGAeiZnjhgTc-9P4Y-TqKDaYicWRp_GQ,1451
|
|
9
9
|
lucy_assist/migrations/0001_initial.py,sha256=quQUw6is5clu3Q4B3P_0mUZVE33lSvdimH_OTCY3ycE,4977
|
|
10
10
|
lucy_assist/migrations/0002_configurationlucyassist_prompt_complementaire.py,sha256=yWE4-RPHQtPAqYHlAhr4EsXgk35kI8zRQArlAP_JwDc,418
|
|
11
11
|
lucy_assist/migrations/0003_configurationlucyassist_crud_views_mapping.py,sha256=1vnu1VwVBouskhQBgLz-Lp71p4a9Cb9PjrT-RLVGY7s,429
|
|
12
12
|
lucy_assist/migrations/0004_configurationlucyassist_system_prompt.py,sha256=0a78xO15oiLcCSlO8BicMac_QE8IfiNSt9WlGptVNNo,568
|
|
13
|
+
lucy_assist/migrations/0005_configurationlucyassist_project_context.py,sha256=6eZCssiWylS_9pg9wDExbUZWEDwk2zaVu_f3pqMzuz8,564
|
|
14
|
+
lucy_assist/migrations/0006_remove_configurationlucyassist_prompt_complementaire.py,sha256=AwTzbmZWfWJ7Q_kcbSspSOiVJgHzGLLeMupeRSSVuI4,359
|
|
13
15
|
lucy_assist/migrations/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
14
16
|
lucy_assist/models/__init__.py,sha256=JQMr50P94sBrKwwcNArRE_qnk7dLnknMKCabeRLskJc,415
|
|
15
17
|
lucy_assist/models/base.py,sha256=Ql2AY7bzvcxZhxsPdCpbVEKvtWD-NBkHTLYZX4TjT3s,1532
|
|
16
|
-
lucy_assist/models/configuration.py,sha256=
|
|
18
|
+
lucy_assist/models/configuration.py,sha256=GHmgkVZk3m01vlDwT-YEn4UG4za8e3Qr7xK00vsd_Qc,17095
|
|
17
19
|
lucy_assist/models/conversation.py,sha256=psx2AQtQ5SFP-AJD7wbGabpXXLIGYngdVZfeoTlgKtQ,1849
|
|
18
20
|
lucy_assist/models/message.py,sha256=kf-ffMtLYNFhXYUrB3QSL97KKDJUOMrKaPjKeOcJa_o,1492
|
|
19
21
|
lucy_assist/models/project_context_cache.py,sha256=Bnb0VU7pv7QEvjOI6JSLEPvL4BxskCQ0ojWGxO7YDSM,6530
|
|
@@ -42,7 +44,7 @@ lucy_assist/utils/message_utils.py,sha256=YzcLHnl1ig4d5_utHCJwgxS7tKmd49Q-tuo78e
|
|
|
42
44
|
lucy_assist/utils/token_utils.py,sha256=aBzyKVqpU67rAetO_Ee3QIfPtbNyjyWSe6qPfzIRJF8,2608
|
|
43
45
|
lucy_assist/views/__init__.py,sha256=uUPYpuHlBC8j7zKS_DDoWjwpCpRnOIXETY-S2-Ss0cY,288
|
|
44
46
|
lucy_assist/views/api_views.py,sha256=sJwKNC9-mi1zMbgyKZTVvT3pz4hMmw4jR0rrS7iJR-g,23619
|
|
45
|
-
django_lucy_assist-1.2.
|
|
46
|
-
django_lucy_assist-1.2.
|
|
47
|
-
django_lucy_assist-1.2.
|
|
48
|
-
django_lucy_assist-1.2.
|
|
47
|
+
django_lucy_assist-1.2.3.dist-info/METADATA,sha256=JDd1H3wg2RpwLmeVdA-Ednz73-6-St1r3oSHWu3ztdQ,5899
|
|
48
|
+
django_lucy_assist-1.2.3.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
49
|
+
django_lucy_assist-1.2.3.dist-info/top_level.txt,sha256=T-UCiwpn5yF3Oem3234TUpSVnEgbkrM2rGz9Tz5N-QA,12
|
|
50
|
+
django_lucy_assist-1.2.3.dist-info/RECORD,,
|
lucy_assist/__init__.py
CHANGED
|
@@ -5,7 +5,7 @@ Un chatbot IA base sur Mistral AI, integrable dans n'importe quelle
|
|
|
5
5
|
application Django pour fournir une assistance contextuelle aux utilisateurs.
|
|
6
6
|
"""
|
|
7
7
|
|
|
8
|
-
__version__ = '1.2.
|
|
8
|
+
__version__ = '1.2.3'
|
|
9
9
|
__author__ = 'Revolucy'
|
|
10
10
|
|
|
11
11
|
default_app_config = 'lucy_assist.apps.LucyAssistConfig'
|
lucy_assist/admin.py
CHANGED
|
@@ -19,28 +19,44 @@ class ConversationAdmin(admin.ModelAdmin):
|
|
|
19
19
|
|
|
20
20
|
@admin.register(ConfigurationLucyAssist)
|
|
21
21
|
class ConfigurationLucyAssistAdmin(admin.ModelAdmin):
|
|
22
|
-
list_display = ('id', 'tokens_disponibles', 'prix_par_million_tokens', 'nb_vues_crud', 'updated_date')
|
|
23
|
-
readonly_fields = ('crud_views_mapping_display', 'model_app_mapping_display')
|
|
22
|
+
list_display = ('id', 'tokens_disponibles', 'prix_par_million_tokens', 'nb_vues_crud', 'has_project_context', 'updated_date')
|
|
23
|
+
readonly_fields = ('crud_views_mapping_display', 'model_app_mapping_display', 'project_context_display')
|
|
24
24
|
fieldsets = (
|
|
25
25
|
('Configuration Tokens', {
|
|
26
26
|
'fields': ('tokens_disponibles', 'prix_par_million_tokens', 'actif')
|
|
27
27
|
}),
|
|
28
28
|
('Personnalisation', {
|
|
29
|
-
'fields': ('avatar', 'questions_frequentes'
|
|
29
|
+
'fields': ('avatar', 'questions_frequentes')
|
|
30
|
+
}),
|
|
31
|
+
('Prompt Systeme', {
|
|
32
|
+
'fields': ('system_prompt',),
|
|
33
|
+
'classes': ('collapse',),
|
|
34
|
+
'description': 'Le prompt systeme est initialise automatiquement si vide.'
|
|
35
|
+
}),
|
|
36
|
+
('Contexte Projet GitLab', {
|
|
37
|
+
'fields': ('project_context_display',),
|
|
38
|
+
'classes': ('collapse',),
|
|
39
|
+
'description': 'Analyse du projet depuis GitLab. Utilisez l\'action "Rafraichir le contexte projet" pour mettre a jour.'
|
|
30
40
|
}),
|
|
31
41
|
('Mapping Automatique (lecture seule)', {
|
|
32
42
|
'fields': ('crud_views_mapping_display', 'model_app_mapping_display'),
|
|
33
43
|
'classes': ('collapse',)
|
|
34
44
|
}),
|
|
35
45
|
)
|
|
36
|
-
actions = ['refresh_crud_views']
|
|
46
|
+
actions = ['refresh_crud_views', 'refresh_project_context']
|
|
37
47
|
|
|
38
48
|
def nb_vues_crud(self, obj):
|
|
39
|
-
"""Affiche le nombre de
|
|
49
|
+
"""Affiche le nombre de modeles avec des vues CRUD decouvertes."""
|
|
40
50
|
if obj.crud_views_mapping:
|
|
41
51
|
return len(obj.crud_views_mapping)
|
|
42
52
|
return 0
|
|
43
|
-
nb_vues_crud.short_description = "
|
|
53
|
+
nb_vues_crud.short_description = "Modeles CRUD"
|
|
54
|
+
|
|
55
|
+
def has_project_context(self, obj):
|
|
56
|
+
"""Indique si le contexte projet est configure."""
|
|
57
|
+
return bool(obj.project_context)
|
|
58
|
+
has_project_context.short_description = "Contexte GitLab"
|
|
59
|
+
has_project_context.boolean = True
|
|
44
60
|
|
|
45
61
|
def crud_views_mapping_display(self, obj):
|
|
46
62
|
"""Affiche le mapping des vues CRUD de manière lisible."""
|
|
@@ -51,21 +67,43 @@ class ConfigurationLucyAssistAdmin(admin.ModelAdmin):
|
|
|
51
67
|
crud_views_mapping_display.short_description = "Vues CRUD découvertes"
|
|
52
68
|
|
|
53
69
|
def model_app_mapping_display(self, obj):
|
|
54
|
-
"""Affiche le mapping
|
|
70
|
+
"""Affiche le mapping modele -> app de maniere lisible."""
|
|
55
71
|
import json
|
|
56
72
|
if obj.model_app_mapping:
|
|
57
73
|
return json.dumps(obj.model_app_mapping, indent=2, ensure_ascii=False)
|
|
58
74
|
return "Aucun mapping. Sera construit automatiquement."
|
|
59
|
-
model_app_mapping_display.short_description = "Mapping
|
|
75
|
+
model_app_mapping_display.short_description = "Mapping Modele -> App"
|
|
60
76
|
|
|
61
|
-
|
|
77
|
+
def project_context_display(self, obj):
|
|
78
|
+
"""Affiche le contexte projet analyse depuis GitLab."""
|
|
79
|
+
if obj.project_context:
|
|
80
|
+
return obj.project_context
|
|
81
|
+
return "Aucun contexte. Utilisez l'action 'Rafraichir le contexte projet' ou configurez GitLab."
|
|
82
|
+
project_context_display.short_description = "Contexte Projet"
|
|
83
|
+
|
|
84
|
+
@admin.action(description="Rafraichir les vues CRUD decouvertes")
|
|
62
85
|
def refresh_crud_views(self, request, queryset):
|
|
63
|
-
"""Action admin pour
|
|
86
|
+
"""Action admin pour rafraichir le mapping des vues CRUD."""
|
|
64
87
|
for config in queryset:
|
|
65
88
|
mapping = config.refresh_crud_views_mapping()
|
|
66
89
|
nb_models = len(mapping)
|
|
67
90
|
nb_views = sum(len(actions) for actions in mapping.values())
|
|
68
91
|
self.message_user(
|
|
69
92
|
request,
|
|
70
|
-
f"Mapping
|
|
93
|
+
f"Mapping rafraichi: {nb_models} modeles, {nb_views} vues decouvertes."
|
|
71
94
|
)
|
|
95
|
+
|
|
96
|
+
@admin.action(description="Rafraichir le contexte projet (GitLab)")
|
|
97
|
+
def refresh_project_context(self, request, queryset):
|
|
98
|
+
"""Action admin pour analyser le projet depuis GitLab."""
|
|
99
|
+
for config in queryset:
|
|
100
|
+
result = config.refresh_project_context()
|
|
101
|
+
if "non configure" in result.lower():
|
|
102
|
+
self.message_user(request, result, level='warning')
|
|
103
|
+
else:
|
|
104
|
+
# Compter les lignes pour donner une idee de la taille
|
|
105
|
+
nb_lines = len(result.split('\n'))
|
|
106
|
+
self.message_user(
|
|
107
|
+
request,
|
|
108
|
+
f"Contexte projet rafraichi: {nb_lines} lignes d'analyse."
|
|
109
|
+
)
|
lucy_assist/constantes.py
CHANGED
|
@@ -58,11 +58,11 @@ Tu as la capacité d'EXÉCUTER des actions directement dans l'application grâce
|
|
|
58
58
|
|
|
59
59
|
## COMPORTEMENT PRIORITAIRE - ACTION FIRST
|
|
60
60
|
|
|
61
|
-
|
|
62
|
-
tu dois
|
|
61
|
+
REGLE FONDAMENTALE : Quand l'utilisateur te demande de faire quelque chose (creer, modifier, rechercher, supprimer),
|
|
62
|
+
tu dois EXECUTER L'ACTION IMMEDIATEMENT en utilisant les tools disponibles.
|
|
63
63
|
|
|
64
|
-
|
|
65
|
-
|
|
64
|
+
NE FAIS PAS : Expliquer comment faire, rediriger vers une page, dire que tu ne peux pas
|
|
65
|
+
FAIS : Utiliser le tool approprie pour executer l'action demandee
|
|
66
66
|
|
|
67
67
|
## Quand NE PAS agir directement
|
|
68
68
|
|
|
@@ -91,10 +91,10 @@ Pour TOUTE demande de suppression, tu DOIS suivre cette procédure :
|
|
|
91
91
|
## Modèles disponibles dans l'application
|
|
92
92
|
{available_models}
|
|
93
93
|
|
|
94
|
-
## Format de
|
|
94
|
+
## Format de reponse apres action
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
"
|
|
96
|
+
Apres avoir execute une action, confirme brievement :
|
|
97
|
+
"[OK] [Action effectuee] - [Detail bref]"
|
|
98
98
|
""",
|
|
99
99
|
'crud': """Tu dois aider l'utilisateur à créer ou modifier un objet.
|
|
100
100
|
Formulaire disponible : {form_info}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Generated by Django
|
|
2
|
+
|
|
3
|
+
from django.db import migrations, models
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('lucy_assist', '0004_configurationlucyassist_system_prompt'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.AddField(
|
|
14
|
+
model_name='configurationlucyassist',
|
|
15
|
+
name='project_context',
|
|
16
|
+
field=models.TextField(
|
|
17
|
+
blank=True,
|
|
18
|
+
default='',
|
|
19
|
+
help_text="Contexte du projet analyse depuis GitLab. Rafraichir via l'action admin."
|
|
20
|
+
),
|
|
21
|
+
),
|
|
22
|
+
]
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Generated by Django
|
|
2
|
+
|
|
3
|
+
from django.db import migrations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class Migration(migrations.Migration):
|
|
7
|
+
|
|
8
|
+
dependencies = [
|
|
9
|
+
('lucy_assist', '0005_configurationlucyassist_project_context'),
|
|
10
|
+
]
|
|
11
|
+
|
|
12
|
+
operations = [
|
|
13
|
+
migrations.RemoveField(
|
|
14
|
+
model_name='configurationlucyassist',
|
|
15
|
+
name='prompt_complementaire',
|
|
16
|
+
),
|
|
17
|
+
]
|
|
@@ -21,16 +21,12 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
21
21
|
avatar = models.ImageField(null=True, blank=True)
|
|
22
22
|
|
|
23
23
|
# Prompt système principal pour l'assistant
|
|
24
|
-
# Initialisé automatiquement
|
|
24
|
+
# Initialisé automatiquement si vide
|
|
25
25
|
system_prompt = models.TextField(
|
|
26
26
|
blank=True,
|
|
27
27
|
default='',
|
|
28
|
-
help_text="Prompt système pour l'assistant IA. Initialisé automatiquement si vide."
|
|
29
28
|
)
|
|
30
29
|
|
|
31
|
-
# Instructions complémentaires pour le prompt (ajoutées après le system_prompt)
|
|
32
|
-
prompt_complementaire = models.TextField(blank=True, default='')
|
|
33
|
-
|
|
34
30
|
# Mapping des modèles vers leurs applications Django
|
|
35
31
|
model_app_mapping = models.JSONField(blank=True, default=dict)
|
|
36
32
|
|
|
@@ -45,6 +41,13 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
45
41
|
# }
|
|
46
42
|
crud_views_mapping = models.JSONField(blank=True, default=dict)
|
|
47
43
|
|
|
44
|
+
# Contexte du projet analyse depuis GitLab
|
|
45
|
+
# Contient une description detaillee du projet, ses fonctionnalites, modeles, etc.
|
|
46
|
+
project_context = models.TextField(
|
|
47
|
+
blank=True,
|
|
48
|
+
default='',
|
|
49
|
+
)
|
|
50
|
+
|
|
48
51
|
class Meta:
|
|
49
52
|
verbose_name = "Configuration Lucy Assist"
|
|
50
53
|
verbose_name_plural = "Configuration Lucy Assist"
|
|
@@ -57,12 +60,20 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
57
60
|
"""
|
|
58
61
|
Retourne la configuration singleton.
|
|
59
62
|
Utilise le cache pour optimiser les performances.
|
|
63
|
+
Initialise le system_prompt si vide.
|
|
60
64
|
"""
|
|
61
65
|
cache_key = 'lucy_assist_config'
|
|
62
66
|
config = cache.get(cache_key)
|
|
63
67
|
|
|
64
68
|
if config is None:
|
|
65
|
-
config,
|
|
69
|
+
config, created = cls.objects.get_or_create(pk=1)
|
|
70
|
+
|
|
71
|
+
# Initialiser le system_prompt si vide (première utilisation ou reset)
|
|
72
|
+
if not config.system_prompt:
|
|
73
|
+
from lucy_assist.constantes import LucyAssistConstantes
|
|
74
|
+
config.system_prompt = LucyAssistConstantes.SYSTEM_PROMPTS['default']
|
|
75
|
+
config.save(update_fields=['system_prompt'])
|
|
76
|
+
|
|
66
77
|
cache.set(cache_key, config, timeout=300) # Cache 5 minutes
|
|
67
78
|
|
|
68
79
|
return config
|
|
@@ -237,15 +248,15 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
237
248
|
available_models: str = ""
|
|
238
249
|
) -> str:
|
|
239
250
|
"""
|
|
240
|
-
Retourne le prompt
|
|
251
|
+
Retourne le prompt systeme formate avec les variables de contexte.
|
|
241
252
|
|
|
242
253
|
Args:
|
|
243
254
|
page_context: Contexte JSON de la page actuelle
|
|
244
255
|
user_permissions: Liste des permissions de l'utilisateur
|
|
245
|
-
available_models: Liste des
|
|
256
|
+
available_models: Liste des modeles disponibles
|
|
246
257
|
|
|
247
258
|
Returns:
|
|
248
|
-
Prompt
|
|
259
|
+
Prompt systeme complet avec le project_context
|
|
249
260
|
"""
|
|
250
261
|
prompt = self.system_prompt
|
|
251
262
|
|
|
@@ -257,9 +268,9 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
257
268
|
available_models=available_models
|
|
258
269
|
)
|
|
259
270
|
|
|
260
|
-
# Ajouter
|
|
261
|
-
if self.
|
|
262
|
-
prompt += f"\n\n##
|
|
271
|
+
# Ajouter le contexte du projet (analyse GitLab) si disponible
|
|
272
|
+
if self.project_context:
|
|
273
|
+
prompt += f"\n\n## Contexte du projet (analyse du code source)\n{self.project_context}"
|
|
263
274
|
|
|
264
275
|
return prompt
|
|
265
276
|
|
|
@@ -267,7 +278,7 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
267
278
|
"""
|
|
268
279
|
Retourne le nom de l'application depuis les settings.
|
|
269
280
|
"""
|
|
270
|
-
return lucy_assist_settings
|
|
281
|
+
return getattr(lucy_assist_settings, 'APPLICATION_NAME', 'cette application')
|
|
271
282
|
|
|
272
283
|
def get_available_models_description(self) -> str:
|
|
273
284
|
"""
|
|
@@ -311,7 +322,112 @@ class ConfigurationLucyAssist(LucyAssistBaseModel):
|
|
|
311
322
|
fields_str += ", ..."
|
|
312
323
|
descriptions.append(f"- {model_name} ({model_name_lower}) : {fields_str}")
|
|
313
324
|
|
|
314
|
-
return "\n".join(descriptions) if descriptions else "Aucun
|
|
325
|
+
return "\n".join(descriptions) if descriptions else "Aucun modele configure"
|
|
326
|
+
|
|
327
|
+
def refresh_project_context(self) -> str:
|
|
328
|
+
"""
|
|
329
|
+
Analyse le projet GitLab et genere un contexte detaille.
|
|
330
|
+
Necessite GITLAB_TOKEN, GITLAB_URL et GITLAB_PROJECT_ID configures.
|
|
331
|
+
|
|
332
|
+
Returns:
|
|
333
|
+
Le contexte genere ou un message d'erreur
|
|
334
|
+
"""
|
|
335
|
+
from lucy_assist.services.gitlab_service import GitLabService
|
|
336
|
+
|
|
337
|
+
gitlab = GitLabService()
|
|
338
|
+
|
|
339
|
+
# Verifier que GitLab est configure
|
|
340
|
+
if not gitlab.token or not gitlab.project_id:
|
|
341
|
+
return "GitLab non configure. Definissez GITLAB_TOKEN, GITLAB_URL et GITLAB_PROJECT_ID."
|
|
342
|
+
|
|
343
|
+
context_parts = []
|
|
344
|
+
app_name = self._get_application_name()
|
|
345
|
+
context_parts.append(f"# Analyse du projet {app_name}\n")
|
|
346
|
+
|
|
347
|
+
# 1. Analyser la structure du projet (fichiers apps.py)
|
|
348
|
+
apps_search = gitlab.search_code("class.*Config.*AppConfig", per_page=20)
|
|
349
|
+
if apps_search:
|
|
350
|
+
context_parts.append("## Applications Django")
|
|
351
|
+
apps_found = []
|
|
352
|
+
for result in apps_search:
|
|
353
|
+
filename = result.get('filename', '')
|
|
354
|
+
if 'apps.py' in filename:
|
|
355
|
+
# Extraire le nom de l'app
|
|
356
|
+
parts = filename.split('/')
|
|
357
|
+
if len(parts) >= 2:
|
|
358
|
+
apps_found.append(parts[-2])
|
|
359
|
+
if apps_found:
|
|
360
|
+
context_parts.append(f"Applications trouvees: {', '.join(set(apps_found))}\n")
|
|
361
|
+
|
|
362
|
+
# 2. Analyser les modeles principaux
|
|
363
|
+
models_search = gitlab.search_code("class.*models.Model", per_page=30)
|
|
364
|
+
if models_search:
|
|
365
|
+
context_parts.append("## Modeles principaux")
|
|
366
|
+
models_info = {}
|
|
367
|
+
for result in models_search:
|
|
368
|
+
filename = result.get('filename', '')
|
|
369
|
+
data = result.get('data', '')
|
|
370
|
+
if 'models' in filename and 'class ' in data:
|
|
371
|
+
# Extraire le nom du modele
|
|
372
|
+
import re
|
|
373
|
+
match = re.search(r'class\s+(\w+)\s*\(', data)
|
|
374
|
+
if match:
|
|
375
|
+
model_name = match.group(1)
|
|
376
|
+
if model_name not in ('Meta', 'Manager'):
|
|
377
|
+
# Recuperer plus de details sur le modele
|
|
378
|
+
model_detail = gitlab.find_model_and_form(model_name)
|
|
379
|
+
if model_detail.get('model_code'):
|
|
380
|
+
# Extraire les champs
|
|
381
|
+
fields = re.findall(
|
|
382
|
+
r'(\w+)\s*=\s*models\.(\w+)',
|
|
383
|
+
model_detail['model_code']
|
|
384
|
+
)
|
|
385
|
+
if fields:
|
|
386
|
+
models_info[model_name] = [f[0] for f in fields[:10]]
|
|
387
|
+
|
|
388
|
+
for model_name, fields in list(models_info.items())[:15]:
|
|
389
|
+
context_parts.append(f"- {model_name}: {', '.join(fields)}")
|
|
390
|
+
context_parts.append("")
|
|
391
|
+
|
|
392
|
+
# 3. Analyser les vues principales
|
|
393
|
+
views_search = gitlab.search_code("class.*View.*", per_page=20)
|
|
394
|
+
if views_search:
|
|
395
|
+
context_parts.append("## Vues principales")
|
|
396
|
+
views_found = set()
|
|
397
|
+
for result in views_search:
|
|
398
|
+
filename = result.get('filename', '')
|
|
399
|
+
data = result.get('data', '')
|
|
400
|
+
if 'views' in filename and 'class ' in data:
|
|
401
|
+
import re
|
|
402
|
+
match = re.search(r'class\s+(\w+View)\s*\(', data)
|
|
403
|
+
if match:
|
|
404
|
+
views_found.add(match.group(1))
|
|
405
|
+
if views_found:
|
|
406
|
+
context_parts.append(f"Vues: {', '.join(list(views_found)[:20])}\n")
|
|
407
|
+
|
|
408
|
+
# 4. Analyser le README si present
|
|
409
|
+
readme_content = gitlab.get_file_content('README.md')
|
|
410
|
+
if readme_content:
|
|
411
|
+
context_parts.append("## Description du projet (README)")
|
|
412
|
+
# Garder les 500 premiers caracteres du README
|
|
413
|
+
context_parts.append(readme_content[:500])
|
|
414
|
+
if len(readme_content) > 500:
|
|
415
|
+
context_parts.append("...\n")
|
|
416
|
+
|
|
417
|
+
# 5. Recuperer les commits recents pour comprendre l'activite
|
|
418
|
+
commits = gitlab.get_recent_commits(per_page=5)
|
|
419
|
+
if commits:
|
|
420
|
+
context_parts.append("## Commits recents")
|
|
421
|
+
for commit in commits:
|
|
422
|
+
context_parts.append(f"- {commit['message']}")
|
|
423
|
+
context_parts.append("")
|
|
424
|
+
|
|
425
|
+
# Assembler le contexte
|
|
426
|
+
self.project_context = "\n".join(context_parts)
|
|
427
|
+
self.save(update_fields=['project_context'])
|
|
428
|
+
cache.delete('lucy_assist_config')
|
|
429
|
+
|
|
430
|
+
return self.project_context
|
|
315
431
|
|
|
316
432
|
|
|
317
433
|
def get_default_model_app_mapping() -> dict:
|
lucy_assist/signals.py
CHANGED
|
@@ -5,7 +5,6 @@ from django.db.models.signals import post_save, pre_delete
|
|
|
5
5
|
from django.dispatch import receiver
|
|
6
6
|
|
|
7
7
|
from lucy_assist.models import Message, ConfigurationLucyAssist
|
|
8
|
-
from lucy_assist.constantes import LucyAssistConstantes
|
|
9
8
|
|
|
10
9
|
|
|
11
10
|
@receiver(post_save, sender=Message)
|
|
@@ -26,17 +25,3 @@ def message_post_save(sender, instance, created, **kwargs):
|
|
|
26
25
|
config.save(update_fields=['tokens_disponibles'])
|
|
27
26
|
|
|
28
27
|
|
|
29
|
-
@receiver(post_save, sender=ConfigurationLucyAssist)
|
|
30
|
-
def config_post_save(sender, instance, created, **kwargs):
|
|
31
|
-
"""
|
|
32
|
-
Signal déclenché après sauvegarde de la configuration.
|
|
33
|
-
Initialise le system_prompt avec le prompt par défaut si vide.
|
|
34
|
-
"""
|
|
35
|
-
if getattr(instance, '_skip_signals', False):
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
if not instance.system_prompt:
|
|
39
|
-
# Initialiser avec le prompt par défaut
|
|
40
|
-
instance.system_prompt = LucyAssistConstantes.SYSTEM_PROMPTS['default']
|
|
41
|
-
instance._skip_signals = True
|
|
42
|
-
instance.save(update_fields=['system_prompt'])
|
|
File without changes
|
|
File without changes
|