Spaces:
Running
Running
Upload 4 files
Browse files
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]}
|