dav74 commited on
Commit
f073e54
·
verified ·
1 Parent(s): 2227115

Upload 4 files

Browse files
Files changed (4) hide show
  1. code.db +3 -0
  2. code.txt +258 -0
  3. database.py +36 -0
  4. main.py +104 -0
code.db ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:763a8e11dffaafff83b8e0bfd22707c0e3042b56c27988259186e6ecca00fcdf
3
+ size 126976
code.txt ADDED
@@ -0,0 +1,258 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 1_16
2
+ ;;;
3
+ On désire programmer une fonction qui prend en paramètre le rayon d'un cercle et renvoie son aire
4
+
5
+ Exemple :
6
+ ```
7
+ >>> aire_cercle(2)
8
+ 28.274
9
+ ```
10
+ Complétez la fonction aire_cercle dans l'éditeur de code (remplacez les ...)
11
+ ;;;
12
+ import math
13
+
14
+ def aire_cercle(...):
15
+ aire = math.pi*rayon**2
16
+ return ...
17
+ ;;;
18
+ c=""
19
+ if round(aire_cercle(3)) == 28:
20
+ c+="1"
21
+ else :
22
+ c+="0"
23
+ ;;;
24
+ 1_17
25
+ ;;;
26
+ On désire programmer une fonction qui prend en paramètre un nombre et qui renvoie la chaîne de caractères "pair" si le nombre est pair et "impair" dans le cas contraire
27
+
28
+ Exemples :
29
+ ```
30
+ >>> pair_impair(4)
31
+ "pair"
32
+ >>> pair_impair(3)
33
+ "impair"
34
+ ```
35
+ Complétez la fonction `pair_impair` dans l'éditeur de code (remplacez les ...)
36
+ ;;;
37
+ import math
38
+
39
+ def pair_impair(n):
40
+ if ... % 2 == 0:
41
+ return ...
42
+ else :
43
+ return "impair"
44
+ ;;;
45
+ c=""
46
+ if pair_impair(4) == "pair":
47
+ c+="1"
48
+ else :
49
+ c+="0"
50
+ if pair_impair(3) == "impair":
51
+ c+="1"
52
+ else :
53
+ c+="0"
54
+ ;;;
55
+ 1_19
56
+ ;;;
57
+ Vous êtes gérant d'un magasin et vous désirez écrire un programme Python qui calculera automatiquement le montant de la facture des clients.
58
+
59
+ Tout client qui achète au moins 5 fois le même article se voit octroyer une remise de 5 % (uniquement sur le montant de l'achat de cet article).
60
+
61
+ Afin de simplifier le problème, on considère qu'un client n'achète qu'un seul type d'article.
62
+
63
+ Écrivez une fonction `facture` qui prend en paramètre le prix unitaire de l'article `p` et le nombre d'articles achetés `n`. Cette fonction doit renvoyer le montant de la facture.
64
+
65
+ Exemples :
66
+ ```
67
+ >>> facture(3,4)
68
+ 12
69
+ >>> facture(3,5)
70
+ 14.25
71
+ ;;;
72
+ ;;;
73
+ c=""
74
+ if facture(3,4) == 12:
75
+ c+="1"
76
+ else :
77
+ c+="0"
78
+ if facture(3,5) == 14.25:
79
+ c+="1"
80
+ else :
81
+ c+="0"
82
+ ;;;
83
+ 2_12
84
+ ;;;
85
+ La fonction recherche_max prend en paramètre un tableau et renvoie la plus grande valeur présente dans le tableau (le tableau est constitué d'entiers positifs ou nuls).
86
+
87
+ Exemples :
88
+ ```
89
+ >>> recherche_max([4, 3, 0, 5])
90
+ 5
91
+ >>> recherche_max([-3, -2, -12, -22])
92
+ -2
93
+ ```
94
+ Compétez la fonction dans l'éditeur de code.
95
+ ;;;
96
+ def recherche_max(tab):
97
+ maxi = ...
98
+ for t in tab :
99
+ if ... > maxi :
100
+ maxi = ...
101
+ return ...
102
+ ;;;
103
+ c=""
104
+ if recherche_max([4, 3, 0, 5]) == 5:
105
+ c+="1"
106
+ else :
107
+ c+="0"
108
+ if recherche_max([-3, -2, -12, -22]) == -2:
109
+ c+="1"
110
+ else :
111
+ c+="0"
112
+ ;;;
113
+ 2_13
114
+ ;;;
115
+ La fonction somme prend en paramètres un tableau tab contenant des entiers. Cette fonction renvoie la somme des entiers présents dans le tableau tab.
116
+
117
+ Exemple :
118
+ ```
119
+ >>> somme([3,5,8,4])
120
+ 20
121
+ ```
122
+ Complétez la fonction `somme` dans l'éditeur de code.
123
+ ;;;
124
+ def somme(tab):
125
+ s = ...
126
+ for t in ... :
127
+ s = s + ...
128
+ return ...
129
+ ;;;
130
+ c=""
131
+ if somme([3,5,8,4]) == 20:
132
+ c+="1"
133
+ else :
134
+ c+="0"
135
+ ;;;
136
+ 2_14
137
+ ;;;
138
+ La fonction recherche prend en paramètres un tableau tab contenant des entiers et un entier n. Cette fonction renvoie l'indice de position de l'entier n s'il est présent dans le tableau tab ou -1 dans le cas contraire (on partira du principe que le tableau ne peut pas contenir 2 fois le même entier).
139
+
140
+ Exemples :
141
+ ```
142
+ >>> recherche([3,5,8,34], 8)
143
+ 2
144
+ >>> recherche([3,5,8,34], 42)
145
+ -1
146
+ ```
147
+ Complétez la fonction `recherche` dans l'éditeur de code
148
+ ;;;
149
+ def recherche(tab, n):
150
+ for i in ... :
151
+ if n == ... :
152
+ return ...
153
+ return ...
154
+ ;;;
155
+ c=""
156
+ if recherche([3,5,8,34], 8) == 2:
157
+ c+="1"
158
+ else :
159
+ c+="0"
160
+ if recherche([3,5,8,34],42) == -1:
161
+ c+="1"
162
+ else :
163
+ c+="0"
164
+ ;;;
165
+ 2_15
166
+ ;;;
167
+ Écrire une fonction moyenne qui prend en paramètre un tableau d'entiers non vide `tab` et qui renvoie la moyenne de ces entiers.
168
+
169
+ Exemple :
170
+ ```
171
+ >>> moyenne([12,15,17,0])
172
+ 11
173
+ ```
174
+ ;;;
175
+ ;;;
176
+ c=""
177
+ if moyenne([12,15,17,0]) == 11:
178
+ c+="1"
179
+ else :
180
+ c+="0"
181
+ ;;;
182
+ 3_6
183
+ ;;;
184
+ On utilise un tableau contenant des dictionnaires afin de stocker les notes des élèves Titi, Toto et Tutu :
185
+ ```
186
+ [{'nom':'Titi', 'note':12}, {'nom':'Tutu', 'note':11}, {'nom':'Toto', 'note':17}]
187
+ ```
188
+ La fonction `plusHaute` prend en paramètre un tableau contenant des dictionnaires (comme celui ci-dessus) et renvoie le nom de l'élève ayant obtenu la meilleure note (on partira du principe que les élèves ont tous des notes différentes).
189
+
190
+ Complétez la fonction `plusHaute` dans l'éditeur de code.
191
+ ;;;
192
+ def plusHaute(tab):
193
+ nom = ""
194
+ max_note = ...
195
+ for t in ...:
196
+ if t['note'] > ...:
197
+ max_note = t[...]
198
+ nom = t[...]
199
+ return ...
200
+ ;;;
201
+ c=""
202
+ if plusHaute([{'nom':'Titi', 'note':12}, {'nom':'Tutu', 'note':11}, {'nom':'Toto', 'note':17}]) == "Toto":
203
+ c+="1"
204
+ else :
205
+ c+="0"
206
+ ;;;
207
+ 3_7
208
+ ;;;
209
+ On utilise un tableau et des dictionnaires pour stocker des noms et des numéros de téléphone :
210
+ ```
211
+ [{'nom':'Titi', 'num':987675643}, {'nom':'Tutu', 'num':424224}, {'nom':'Toto', 'num':343235365}]
212
+ ```
213
+ La fonction numTel prend 2 paramètres : un tableau de dictionnaires `tab_tel` contenant les noms et les numéros de téléphone (comme celui ci-dessus) et un nom `n`
214
+
215
+ La fonction `numTel` doit renvoyer le numéro de téléphone de `n` si ce dernier existe. Dans le cas où `n` n'existe pas, la fonction `numTel` doit renvoyer -1
216
+
217
+ Exemples :
218
+ ```
219
+ >>> numTel([{'nom':'Titi', 'num':987675643}, {'nom':'Tutu', 'num':424224}, {'nom':'Toto', 'num':343235365}], 'Tutu')
220
+ 424224
221
+ >>> numTel([{'nom':'Titi', 'num':987675643}, {'nom':'Tutu', 'num':424224}, {'nom':'Toto', 'num':343235365}], 'Tata')
222
+ -1
223
+ ```
224
+ Complétez la fonction `numTel` dans l'éditeur de code.
225
+ ;;;
226
+ def numTel(..., n):
227
+ for ... in tab_tel:
228
+ if ... == t['nom']:
229
+ return ...
230
+ return ...
231
+ ;;;
232
+ c=""
233
+ if numTel([{'nom':'Titi', 'num':987675643}, {'nom':'Tutu', 'num':424224}, {'nom':'Toto', 'num':343235365}], 'Tutu') == 424224:
234
+ c+="1"
235
+ else :
236
+ c+="0"
237
+ if numTel([{'nom':'Titi', 'num':987675643}, {'nom':'Tutu', 'num':424224}, {'nom':'Toto', 'num':343235365}], 'Tata') == -1:
238
+ c+="1"
239
+ else :
240
+ c+="0"
241
+ ;;;
242
+ 3_8
243
+ ;;;
244
+ On utilise un tableau contenant des dictionnaires afin de stocker les notes des élèves Titi, Toto et Tutu :
245
+ ```
246
+ [{'nom':'Titi', 'note':12}, {'nom':'Tutu', 'note':11}, {'nom':'Toto', 'note':17}]
247
+ ```
248
+ La fonction `moyenne` prend en paramètre un tableau contenant des dictionnaires (comme celui ci-dessus) et renvoie la moyenne des notes.
249
+
250
+ Écrivez la fonction `moyenne`
251
+ ;;;
252
+ ;;;
253
+ c=""
254
+ if moyenne([{'nom':'Titi', 'note':13}, {'nom':'Tutu', 'note':14}, {'nom':'Toto', 'note':18}]) == 15:
255
+ c+="1"
256
+ else :
257
+ c+="0"
258
+ ;;;
database.py ADDED
@@ -0,0 +1,36 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import sqlite3
2
+
3
+ def create_table():
4
+ conn = sqlite3.connect("code.db")
5
+ cursor = conn.cursor()
6
+ cursor.execute("DELETE FROM code;")
7
+ with open('code.txt', 'r') as f:
8
+ c = 0
9
+ txt = ""
10
+ id = 1
11
+ for l in f :
12
+ txt += l
13
+ if l == ";;;\n":
14
+ c += 1
15
+ if c == 4 :
16
+ tab = txt.split(";;;\n")
17
+ txt = ""
18
+ c = 0
19
+ cursor.execute("INSERT INTO code (id, titre, enonce, code_trous, test) VALUES (?, ?, ?, ?, ?)", (id, tab[0].replace("\n",""), tab[1], tab[2], tab[3]))
20
+ id += 1
21
+ conn.commit()
22
+ conn.close()
23
+
24
+ def return_exercise(titre):
25
+ conn = sqlite3.connect("code.db")
26
+ cursor = conn.cursor()
27
+ cursor.execute("SELECT * FROM code WHERE titre = ?", (titre,))
28
+ rows = cursor.fetchall()
29
+ conn.close()
30
+ return rows[0]
31
+
32
+
33
+
34
+
35
+
36
+
main.py ADDED
@@ -0,0 +1,104 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from langchain_core.output_parsers import StrOutputParser
3
+ from langchain_core.prompts import PromptTemplate
4
+ from langgraph.checkpoint.memory import MemorySaver
5
+ from typing import List
6
+ from typing_extensions import TypedDict
7
+ from typing import Annotated
8
+ from langgraph.graph.message import AnyMessage, add_messages
9
+ from langchain_core.messages import HumanMessage, AIMessage
10
+ from langgraph.graph import END, StateGraph, START
11
+ from fastapi import FastAPI
12
+ from fastapi.middleware.cors import CORSMiddleware
13
+ from pydantic import BaseModel
14
+ from database import create_table, return_exercise
15
+ import logging
16
+ from langchain_google_genai import ChatGoogleGenerativeAI
17
+
18
+ create_table()
19
+
20
+ GOOGLE_API_KEY = 'AIzaSyDUtmNWKzd93_yLs2Ihi7K0nYwclZESmbE'
21
+
22
+ llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash", temperature=0.7, api_key=GOOGLE_API_KEY)
23
+
24
+
25
+ prompt_aide = PromptTemplate.from_template(
26
+ """
27
+ Tu es un expert en pédagogie de l'apprentissage de la programmation
28
+ Le langage utilisé pour l'apprentissage de la programmation est Python.
29
+ Tu dois aider un élève à résoudre une activité de programmation Python.
30
+ Il existe 2 types d'activités :
31
+ - les activités qui demandent à l'élève d'écrire un programme Python complet
32
+ - les activités qui demandent à l'élève de compléter un programme Python à trous (les trous sont indiqués par 3 points : ...)
33
+ Si l'activité est de type "à trous" et que l'élève à laissé des trous, tu dois lui proposer de compléter les trous.
34
+ Tu ne dois jamais donner la solution de l'activité (même partiellement) à l'élève, juste lui donner des inddications lui permettant de résoudre lui même l'activité
35
+ Tu dois t'adresser directement à l'élève.
36
+ L'élève ne peut pas te poser des questions, il peut juste te proposer son code.
37
+ Tu ne dois pas proposer à l'élève de te poser des questions
38
+ Il est inutile de proposer à l'élève de tester son code avec les exemples proposés.
39
+ Tu ne dois pas proposer aux élèves des modifications du programme qui sorte du cadre de l'activité. Par exemple, pour l'activité qui demande d'écrire une fonction moyenne, si dans l'énoncé il est précisé que l'on a un tableau non vide d'entier en paramètre, il est inutile de dire à l'élève que son programme doit gérer les tableaux vides.
40
+ Tu dois t'exprimer en français
41
+ Voici l'énoncé de l'activité :
42
+ {enonce}
43
+ Voici le programme proposé par l'élève pour résoudre l'activité :
44
+ {code}
45
+ Pour améliorer ta réponse, tu as aussi à ta disposition l'historique des différents programme proposés par l'élève et les différents conseils que tu lui a déjà donné :
46
+ {historique}
47
+ """)
48
+
49
+ def history(hist):
50
+ historical = ""
51
+ for i in range(len(hist)):
52
+ if i%2 == 0:
53
+ historical += "code de l'éléve : \n"+hist[i].content+"\n"
54
+ else :
55
+ historical += "aide de l'expert : \n"+hist[i].content+"\n"
56
+ return historical
57
+
58
+ memory = MemorySaver()
59
+ app = FastAPI()
60
+
61
+ app.add_middleware(
62
+ CORSMiddleware,
63
+ allow_origins=["*"],
64
+ allow_credentials=True,
65
+ allow_methods=["*"],
66
+ allow_headers=["*"],
67
+ )
68
+
69
+ class Request(BaseModel):
70
+ id : str
71
+ enonce : str
72
+ code : str
73
+ res_test : str
74
+
75
+ class AgentState(TypedDict):
76
+ enonce : str
77
+ messages: Annotated[list[AnyMessage], add_messages]
78
+ res_test : str
79
+
80
+ def aide(state : AgentState):
81
+ llm_aide = prompt_aide | llm | StrOutputParser()
82
+ response = llm_aide.invoke({'enonce': state['enonce'], 'code' : state['messages'][-1].content, 'historique' : history(state['messages'])})
83
+ return {"messages": [AIMessage(content=response)]}
84
+
85
+ workflow = StateGraph(AgentState)
86
+
87
+ workflow.add_node("aide", aide)
88
+
89
+ workflow.add_edge(START, "aide")
90
+ workflow.add_edge( "aide", END)
91
+
92
+ graph = workflow.compile(checkpointer=memory)
93
+
94
+ @app.post('/request')
95
+ def request(req: Request):
96
+ config = {"configurable": {"thread_id": req.id}}
97
+ rep = graph.invoke({"enonce" : req.enonce,"messages": req.code, "res_test" : req.res_test},config , stream_mode="values")
98
+ return {"response":rep['messages'][-1].content}
99
+
100
+
101
+ @app.get('/exercise/{titre}')
102
+ def get_exercise(titre : str):
103
+ ex = return_exercise(titre)
104
+ return {"title" : ex[1], "enonce" : ex[2], "code_trous":ex[3], "test": ex[4]}