lucas-wa commited on
Commit
71d17e3
·
2 Parent(s): a6fb9f9 8c93fc6

Merge branch 'main' of github.com:workshop-question-generator/perguntai-app

Browse files
server/app.py CHANGED
@@ -3,6 +3,9 @@ from fastapi.middleware.cors import CORSMiddleware
3
  from pydantic import BaseModel
4
  from fastapi.staticfiles import StaticFiles
5
  from services.generate_questions_service import GenerateQuestionsService
 
 
 
6
 
7
  generate_questions_service = GenerateQuestionsService()
8
 
@@ -10,6 +13,8 @@ class Body(BaseModel):
10
  matter: str
11
  subject: str
12
  difficultie: str
 
 
13
 
14
  app = FastAPI()
15
 
@@ -26,7 +31,10 @@ async def generate_questions(body: Body):
26
  matter = body.matter
27
  subject = body.subject
28
  difficultie = body.difficultie
29
- query = f"Quero que você gere questões de {matter}, sendo do assunto: {subject} e sendo da dificuldade: {difficultie}."
 
 
 
30
  res = generate_questions_service.handle(f"""{query}""")
31
  return res
32
 
 
3
  from pydantic import BaseModel
4
  from fastapi.staticfiles import StaticFiles
5
  from services.generate_questions_service import GenerateQuestionsService
6
+ from typing import Optional
7
+
8
+ # from data.load_data import retriever_pre
9
 
10
  generate_questions_service = GenerateQuestionsService()
11
 
 
13
  matter: str
14
  subject: str
15
  difficultie: str
16
+ promptValue: Optional[str] = None
17
+
18
 
19
  app = FastAPI()
20
 
 
31
  matter = body.matter
32
  subject = body.subject
33
  difficultie = body.difficultie
34
+ if body.promptValue:
35
+ query = body.promptValue
36
+ else:
37
+ query = f"Quero que você gere questões de {school_subject}, sendo do assunto: {subject} e sendo da dificuldade: {difficultie}."
38
  res = generate_questions_service.handle(f"""{query}""")
39
  return res
40
 
web/package-lock.json CHANGED
@@ -8,8 +8,10 @@
8
  "name": "question-generator",
9
  "version": "0.0.0",
10
  "dependencies": {
 
11
  "@radix-ui/react-select": "^2.0.0",
12
  "@radix-ui/react-separator": "^1.0.3",
 
13
  "class-variance-authority": "^0.7.0",
14
  "clsx": "^2.1.1",
15
  "lucide-react": "^0.377.0",
@@ -1230,6 +1232,29 @@
1230
  }
1231
  }
1232
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1233
  "node_modules/@radix-ui/react-popper": {
1234
  "version": "1.1.3",
1235
  "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz",
@@ -1392,6 +1417,35 @@
1392
  }
1393
  }
1394
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1395
  "node_modules/@radix-ui/react-use-callback-ref": {
1396
  "version": "1.0.1",
1397
  "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
 
8
  "name": "question-generator",
9
  "version": "0.0.0",
10
  "dependencies": {
11
+ "@radix-ui/react-label": "^2.0.2",
12
  "@radix-ui/react-select": "^2.0.0",
13
  "@radix-ui/react-separator": "^1.0.3",
14
+ "@radix-ui/react-switch": "^1.0.3",
15
  "class-variance-authority": "^0.7.0",
16
  "clsx": "^2.1.1",
17
  "lucide-react": "^0.377.0",
 
1232
  }
1233
  }
1234
  },
1235
+ "node_modules/@radix-ui/react-label": {
1236
+ "version": "2.0.2",
1237
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-label/-/react-label-2.0.2.tgz",
1238
+ "integrity": "sha512-N5ehvlM7qoTLx7nWPodsPYPgMzA5WM8zZChQg8nyFJKnDO5WHdba1vv5/H6IO5LtJMfD2Q3wh1qHFGNtK0w3bQ==",
1239
+ "dependencies": {
1240
+ "@babel/runtime": "^7.13.10",
1241
+ "@radix-ui/react-primitive": "1.0.3"
1242
+ },
1243
+ "peerDependencies": {
1244
+ "@types/react": "*",
1245
+ "@types/react-dom": "*",
1246
+ "react": "^16.8 || ^17.0 || ^18.0",
1247
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
1248
+ },
1249
+ "peerDependenciesMeta": {
1250
+ "@types/react": {
1251
+ "optional": true
1252
+ },
1253
+ "@types/react-dom": {
1254
+ "optional": true
1255
+ }
1256
+ }
1257
+ },
1258
  "node_modules/@radix-ui/react-popper": {
1259
  "version": "1.1.3",
1260
  "resolved": "https://registry.npmjs.org/@radix-ui/react-popper/-/react-popper-1.1.3.tgz",
 
1417
  }
1418
  }
1419
  },
1420
+ "node_modules/@radix-ui/react-switch": {
1421
+ "version": "1.0.3",
1422
+ "resolved": "https://registry.npmjs.org/@radix-ui/react-switch/-/react-switch-1.0.3.tgz",
1423
+ "integrity": "sha512-mxm87F88HyHztsI7N+ZUmEoARGkC22YVW5CaC+Byc+HRpuvCrOBPTAnXgf+tZ/7i0Sg/eOePGdMhUKhPaQEqow==",
1424
+ "dependencies": {
1425
+ "@babel/runtime": "^7.13.10",
1426
+ "@radix-ui/primitive": "1.0.1",
1427
+ "@radix-ui/react-compose-refs": "1.0.1",
1428
+ "@radix-ui/react-context": "1.0.1",
1429
+ "@radix-ui/react-primitive": "1.0.3",
1430
+ "@radix-ui/react-use-controllable-state": "1.0.1",
1431
+ "@radix-ui/react-use-previous": "1.0.1",
1432
+ "@radix-ui/react-use-size": "1.0.1"
1433
+ },
1434
+ "peerDependencies": {
1435
+ "@types/react": "*",
1436
+ "@types/react-dom": "*",
1437
+ "react": "^16.8 || ^17.0 || ^18.0",
1438
+ "react-dom": "^16.8 || ^17.0 || ^18.0"
1439
+ },
1440
+ "peerDependenciesMeta": {
1441
+ "@types/react": {
1442
+ "optional": true
1443
+ },
1444
+ "@types/react-dom": {
1445
+ "optional": true
1446
+ }
1447
+ }
1448
+ },
1449
  "node_modules/@radix-ui/react-use-callback-ref": {
1450
  "version": "1.0.1",
1451
  "resolved": "https://registry.npmjs.org/@radix-ui/react-use-callback-ref/-/react-use-callback-ref-1.0.1.tgz",
web/package.json CHANGED
@@ -10,8 +10,10 @@
10
  "preview": "vite preview"
11
  },
12
  "dependencies": {
 
13
  "@radix-ui/react-select": "^2.0.0",
14
  "@radix-ui/react-separator": "^1.0.3",
 
15
  "class-variance-authority": "^0.7.0",
16
  "clsx": "^2.1.1",
17
  "lucide-react": "^0.377.0",
 
10
  "preview": "vite preview"
11
  },
12
  "dependencies": {
13
+ "@radix-ui/react-label": "^2.0.2",
14
  "@radix-ui/react-select": "^2.0.0",
15
  "@radix-ui/react-separator": "^1.0.3",
16
+ "@radix-ui/react-switch": "^1.0.3",
17
  "class-variance-authority": "^0.7.0",
18
  "clsx": "^2.1.1",
19
  "lucide-react": "^0.377.0",
web/src/App.jsx CHANGED
@@ -9,6 +9,9 @@ import { ChevronLeft, Menu } from "lucide-react"
9
  import { useEffect, useState } from "react";
10
  import { ToastContainer, toast } from "react-toastify"
11
  import 'react-toastify/dist/ReactToastify.css';
 
 
 
12
 
13
  function App() {
14
 
@@ -18,15 +21,11 @@ function App() {
18
  const [menuState, setMenuState] = useState(true);
19
  const [isLoading, setIsLoading] = useState(false);
20
  const [questions, setQuestions] = useState(null);
21
- const [selectedMatter, setSelectedMatter] = useState("biologia");
22
 
 
23
 
24
- const matter = [
25
- { label: "Biologia", value: "biologia" },
26
- { label: "História", value: "historia" },
27
- ];
28
-
29
- const biologySubjects = [
30
  { label: "Fisiologia", value: "fisiologia" },
31
  { label: "Embriologia", value: "embriologia" },
32
  { label: "Citologia", value: "citologia" },
@@ -38,15 +37,6 @@ function App() {
38
  { label: "Biofísica", value: "biofisica" },
39
  ]
40
 
41
- const historySubjects = [
42
- { label: "Revoluções", value: "revoluções" },
43
- { label: "Grécia", value: "grécia" },
44
- { label: "Roma", value: "roma" },
45
- { label: "Primeira Guerra Mundial", value: "primeira guerra mundial" },
46
- { label: "Guerra Fria", value: "guerra fria" },
47
- { label: "Feudalismo", value: "feudalismo" },
48
- ]
49
-
50
  const difficulties = [
51
  { label: "Fácil", value: "facil" },
52
  { label: "Intermediária", value: "intermediaria" },
@@ -62,13 +52,14 @@ function App() {
62
  "Content-Type": "application/json"
63
  },
64
  body: JSON.stringify({
65
- matter: selectedMatter,
66
  subject, difficultie
67
  })
68
  });
 
69
  if (res.ok) {
70
  const data = await res.json();
71
- setQuestions(data.rag_result.questions);
 
72
  } else {
73
  toast.error("Erro ao gerar questões", {
74
  position: "top-right",
@@ -120,87 +111,99 @@ function App() {
120
  </h1>
121
  </header>
122
  <main className="flex-1 flex overflow-hidden">
123
- {
124
- menuState &&
125
- <form
126
- onSubmit={handleSubmit}
127
- className="p-10 flex flex-col gap-2.5 absolute top-0 bg-black/95 h-full z-10 md:static md:h-full md:bg-transparent">
128
- <div className="md:sr-only">
129
- <ChevronLeft className="w-10 h-10" onClick={e => setMenuState(prev => !prev)} />
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
130
  </div>
131
- <h2>Selecione uma matéria:</h2>
132
- <Select defaultValue="biologia" onValueChange={value => setSelectedMatter(value)}>
133
- <SelectTrigger className="w-[180px]">
134
- <SelectValue placeholder="Matéria" />
135
- </SelectTrigger>
136
- <SelectContent >
137
- {
138
- matter.map(({ label, value }) => (
139
- <SelectItem key={value} value={value}>{label}</SelectItem>
140
- ))
141
- }
142
- </SelectContent>
143
- </Select>
144
- <h2>Selecione um conteúdo:</h2>
145
- <Select onValueChange={value => setSubject(value)}>
146
- <SelectTrigger className="w-[180px]">
147
- <SelectValue placeholder="Conteúdo" />
148
- </SelectTrigger>
149
- <SelectContent onChange={e => console.log(e)}>
150
- {
151
- selectedMatter === "biologia" ?
152
- biologySubjects.map(({ label, value }) => (
153
- <SelectItem key={value} value={value}>{label}</SelectItem>
154
- ))
155
- :
156
- historySubjects.map(({ label, value }) => (
157
- <SelectItem key={value} value={value}>{label}</SelectItem>
158
- ))
159
- }
160
- </SelectContent>
161
- </Select>
162
- <h2>Selecione uma dificuldade:</h2>
163
- <Select onValueChange={value => setDifficultie(value)}>
164
- <SelectTrigger className="w-[180px]">
165
- <SelectValue placeholder="Dificuldade" />
166
- </SelectTrigger>
167
- <SelectContent onChange={e => console.log(e)}>
168
- {difficulties && difficulties.map(({ label, value }) => (
169
- <SelectItem key={value} value={value}>{label}</SelectItem>
170
- ))}
171
- </SelectContent>
172
- </Select>
173
- <button className="h-10 bg-purple-500 rounded px-2.5 py-1 mt-5 hover:brightness-110 transition-all flex items-center justify-center disabled:hover:brightness-75 disabled:brightness-75"
174
- disabled={isLoading || !subject || !difficultie}>
175
- {
176
- isLoading ?
177
- <div className="animate-spin h-5 w-5 border-2 border-white border-r-purple-500 rounded-full"></div>
178
- :
179
- "Enviar"
180
- }
181
- </button>
182
- </form>
183
  }
184
- <section className="p-10 flex-1 md:border-l-2 md:border-l-white flex flex-col gap-2.5 ">
185
- <h2 className="text-2xl font-bold">Questões</h2>
186
- <div className="w-full h-full flex flex-col gap-5 rounded p-2.5 overflow-y-scroll">
187
- {questions ?
188
- questions.map(({ question, options, answer }, index) => (
189
- <div key={index} className="bg-slate-950 ring-2 ring-white p-2.5 rounded">
190
- {question}<br /><br />
191
- {options.map((option, i) => (
192
- <div key={i}>
193
- {option}
194
- </div>
195
- ))}<br />
196
- Resposta correta: {answer}
197
- </div>
198
- ))
199
- : <div className="p-2.5 bg-slate-950 ring-2 ring-white rounded">{"Ainda sem questões"}</div>}
200
- </div>
201
- </section>
202
  <ToastContainer />
203
  </main>
 
204
  </div>
205
  )
206
  }
 
9
  import { useEffect, useState } from "react";
10
  import { ToastContainer, toast } from "react-toastify"
11
  import 'react-toastify/dist/ReactToastify.css';
12
+ import { Switch } from "@/components/ui/switch"
13
+ import { Label } from "@/components/ui/label"
14
+ import { Input } from "@/components/ui/input"
15
 
16
  function App() {
17
 
 
21
  const [menuState, setMenuState] = useState(true);
22
  const [isLoading, setIsLoading] = useState(false);
23
  const [questions, setQuestions] = useState(null);
24
+ const [promptMode, setPromptMode] = useState(false);
25
 
26
+ const [promptValue, setPromptValue] = useState('');
27
 
28
+ const subjects = [
 
 
 
 
 
29
  { label: "Fisiologia", value: "fisiologia" },
30
  { label: "Embriologia", value: "embriologia" },
31
  { label: "Citologia", value: "citologia" },
 
37
  { label: "Biofísica", value: "biofisica" },
38
  ]
39
 
 
 
 
 
 
 
 
 
 
40
  const difficulties = [
41
  { label: "Fácil", value: "facil" },
42
  { label: "Intermediária", value: "intermediaria" },
 
52
  "Content-Type": "application/json"
53
  },
54
  body: JSON.stringify({
 
55
  subject, difficultie
56
  })
57
  });
58
+ console.log(res)
59
  if (res.ok) {
60
  const data = await res.json();
61
+ console.log(data)
62
+ setQuestions(data.questions);
63
  } else {
64
  toast.error("Erro ao gerar questões", {
65
  position: "top-right",
 
111
  </h1>
112
  </header>
113
  <main className="flex-1 flex overflow-hidden">
114
+ {menuState &&
115
+ <>
116
+ <div className="p-10 flex flex-col gap-5">
117
+ <div className="flex items-center space-x-2 w-56">
118
+ <Switch id="prompt-mode" checked={promptMode} onCheckedChange={setPromptMode} />
119
+ <Label htmlFor="prompt-mode">Prompt Mode</Label>
120
+ </div>
121
+ {!promptMode && (
122
+ <form
123
+ onSubmit={handleSubmit}
124
+ className="flex flex-col gap-2.5 absolute top-0 bg-black/95 h-full md:h-fit z-10 md:static md:bg-transparent">
125
+ <div className="md:sr-only">
126
+ <ChevronLeft className="w-10 h-10" onClick={e => setMenuState(prev => !prev)} />
127
+ </div>
128
+ <fieldset>
129
+ <h2>Selecione uma matéria:</h2>
130
+ <Select defaultValue="biologia">
131
+ <SelectTrigger className="w-[180px]">
132
+ <SelectValue placeholder="Matéria" />
133
+ </SelectTrigger>
134
+ <SelectContent>
135
+ <SelectItem value="biologia">Biologia</SelectItem>
136
+ </SelectContent>
137
+ </Select>
138
+ <h2>Selecione um conteúdo:</h2>
139
+ <Select onValueChange={value => setSubject(value)}>
140
+ <SelectTrigger className="w-[180px]">
141
+ <SelectValue placeholder="Conteúdo" />
142
+ </SelectTrigger>
143
+ <SelectContent onChange={e => console.log(e)}>
144
+ {subjects && subjects.map(({ label, value }) => (
145
+ <SelectItem key={value} value={value}>{label}</SelectItem>
146
+ ))}
147
+ </SelectContent>
148
+ </Select>
149
+ <h2>Selecione uma dificuldade:</h2>
150
+ <Select onValueChange={value => setDifficultie(value)}>
151
+ <SelectTrigger className="w-[180px]">
152
+ <SelectValue placeholder="Dificuldade" />
153
+ </SelectTrigger>
154
+ <SelectContent onChange={e => console.log(e)}>
155
+ {difficulties && difficulties.map(({ label, value }) => (
156
+ <SelectItem key={value} value={value}>{label}</SelectItem>
157
+ ))}
158
+ </SelectContent>
159
+ </Select>
160
+ </fieldset>
161
+ <button className="h-10 bg-purple-500 rounded px-2.5 py-1 mt-5 hover:brightness-110 transition-all flex items-center justify-center disabled:hover:brightness-75 disabled:brightness-75"
162
+ disabled={isLoading || !subject || !difficultie}>
163
+ {isLoading ?
164
+ <div className="animate-spin h-5 w-5 border-2 border-white border-r-purple-500 rounded-full"></div>
165
+ :
166
+ "Enviar"
167
+ }
168
+ </button>
169
+ </form>
170
+ )}
171
+
172
+
173
  </div>
174
+ <section className="p-10 flex-1 md:border-l-2 md:border-l-white flex flex-col gap-2.5 ">
175
+ {promptMode ? (
176
+ <>
177
+ <h2 className="text-2xl font-bold mb-5">Digite seu prompt para gerarmos as questões!</h2>
178
+ <Input placeholder="Digite seu prompt:" value={promptValue} onChange={(e) => setPromptValue(e.target.value)}/>
179
+ </>
180
+ ) : (
181
+ <>
182
+ <h2 className="text-2xl font-bold">Questões</h2>
183
+ <div className="w-full h-full flex flex-col gap-5 rounded p-2.5 overflow-y-scroll">
184
+ {questions ?
185
+ questions.map(({ question, options, answer }, index) => (
186
+ <div key={index} className="bg-slate-950 ring-2 ring-white p-2.5 rounded">
187
+ {question}<br /><br />
188
+ {options.map((option, i) => (
189
+ <div key={i}>
190
+ {option}
191
+ </div>
192
+ ))}<br />
193
+ Resposta correta: {answer}
194
+ </div>
195
+ ))
196
+ : <div className="p-2.5 bg-slate-950 ring-2 ring-white rounded">Escolha os filtros para criar as questões</div>
197
+ }
198
+ </div>
199
+ </>
200
+ )}
201
+ </section>
202
+ </>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
203
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
204
  <ToastContainer />
205
  </main>
206
+
207
  </div>
208
  )
209
  }
web/src/components/ui/input.jsx ADDED
@@ -0,0 +1,19 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import * as React from "react"
2
+
3
+ import { cn } from "@/lib/utils"
4
+
5
+ const Input = React.forwardRef(({ className, type, ...props }, ref) => {
6
+ return (
7
+ (<input
8
+ type={type}
9
+ className={cn(
10
+ "flex h-10 w-full rounded-md border border-input bg-background px-3 py-2 text-sm ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50",
11
+ className
12
+ )}
13
+ ref={ref}
14
+ {...props} />)
15
+ );
16
+ })
17
+ Input.displayName = "Input"
18
+
19
+ export { Input }
web/src/components/ui/label.jsx ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as LabelPrimitive from "@radix-ui/react-label"
5
+ import { cva } from "class-variance-authority";
6
+
7
+ import { cn } from "@/lib/utils"
8
+
9
+ const labelVariants = cva(
10
+ "text-sm font-medium leading-none peer-disabled:cursor-not-allowed peer-disabled:opacity-70"
11
+ )
12
+
13
+ const Label = React.forwardRef(({ className, ...props }, ref) => (
14
+ <LabelPrimitive.Root ref={ref} className={cn(labelVariants(), className)} {...props} />
15
+ ))
16
+ Label.displayName = LabelPrimitive.Root.displayName
17
+
18
+ export { Label }
web/src/components/ui/switch.jsx ADDED
@@ -0,0 +1,24 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ "use client"
2
+
3
+ import * as React from "react"
4
+ import * as SwitchPrimitives from "@radix-ui/react-switch"
5
+
6
+ import { cn } from "@/lib/utils"
7
+
8
+ const Switch = React.forwardRef(({ className, ...props }, ref) => (
9
+ <SwitchPrimitives.Root
10
+ className={cn(
11
+ "peer inline-flex h-6 w-11 shrink-0 cursor-pointer items-center rounded-full border-2 border-transparent transition-colors focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 focus-visible:ring-offset-background disabled:cursor-not-allowed disabled:opacity-50 data-[state=checked]:bg-primary data-[state=unchecked]:bg-input",
12
+ className
13
+ )}
14
+ {...props}
15
+ ref={ref}>
16
+ <SwitchPrimitives.Thumb
17
+ className={cn(
18
+ "pointer-events-none block h-5 w-5 rounded-full bg-background shadow-lg ring-0 transition-transform data-[state=checked]:translate-x-5 data-[state=unchecked]:translate-x-0"
19
+ )} />
20
+ </SwitchPrimitives.Root>
21
+ ))
22
+ Switch.displayName = SwitchPrimitives.Root.displayName
23
+
24
+ export { Switch }