Docfile commited on
Commit
57b6ed4
·
verified ·
1 Parent(s): 39ea9c3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +74 -126
app.py CHANGED
@@ -1,171 +1,119 @@
 
1
  import os
2
  import json
3
  from textwrap import dedent
4
- from flask import Flask, render_template, request, jsonify
5
  from crewai import Agent, Crew, Process, Task
6
  from crewai_tools import SerperDevTool
7
- from langchain_google_genai import ChatGoogleGenerativeAI
8
- from typing import List, Dict, Any
9
 
10
- # Configuration (use .env in production)
 
 
11
  os.environ["GEMINI_API_KEY"] = "AIzaSyCQpoVCdk7h7MvAQKZOUfcnkQYVkHmAKwI"
12
  os.environ["SERPER_API_KEY"] = "9b90a274d9e704ff5b21c0367f9ae1161779b573"
13
- gemini_api_key = os.environ.get("GEMINI_API_KEY")
14
- serper_api_key = os.environ.get("SERPER_API_KEY")
15
-
16
- if not gemini_api_key:
17
- raise ValueError("Gemini API key missing.")
18
- if not serper_api_key:
19
- raise ValueError("Serper API key missing.")
20
-
21
- llm = ChatGoogleGenerativeAI(
22
- model="gemini-2.0-flash",
23
- temperature=0.7,
24
- google_api_key=gemini_api_key,
25
- max_output_tokens=8000,
26
- convert_system_message_to_human=True
27
  )
28
 
 
29
  search_tool = SerperDevTool()
30
 
 
31
  researcher = Agent(
32
- role='Chercheur de Sujets Académiques',
33
- goal=dedent("""Find factual, precise information on {topic} using the web search tool.
34
- Focus on key concepts, definitions, dates, and notable facts."""),
35
- backstory=dedent("""A meticulous researcher with a developed critical mind.
36
- Synthesizes information from multiple sources to extract the factual essence."""),
37
  tools=[search_tool],
38
  llm=llm,
39
  verbose=True,
40
- allow_delegation=False,
41
- max_iter=5
42
  )
43
 
44
- quiz_creator = Agent(
45
- role='Concepteur Pédagogique de Quiz',
46
- goal=dedent("""Create an engaging multiple-choice quiz based on the factual information
47
- provided by the Researcher on {topic}.
48
- Formulate clear questions, plausible options, and identify the correct answer.
49
- Include a concise explanation for each question."""),
50
- backstory=dedent("""A specialist in pedagogical design who excels at transforming
51
- raw information into effective evaluation tools."""),
52
  llm=llm,
53
  verbose=True,
54
- allow_delegation=False,
55
- max_iter=3
56
  )
57
 
58
- def extract_json_from_result(result_text: str) -> List[Dict[str, Any]]:
 
59
  try:
60
  json_start = result_text.find('[')
61
  json_end = result_text.rfind(']') + 1
62
-
63
- if json_start != -1 and json_end != 0 and json_end > json_start:
64
- json_str = result_text[json_start:json_end]
65
- parsed_json = json.loads(json_str)
66
- if isinstance(parsed_json, list):
67
- for item in parsed_json:
68
- if not all(k in item for k in ('question', 'options', 'correct_answer')):
69
- raise ValueError("Invalid quiz element structure in JSON.")
70
- return parsed_json
71
- else:
72
- raise ValueError("The extracted JSON is not a list.")
73
- else:
74
- try:
75
- parsed_json = json.loads(result_text)
76
- if isinstance(parsed_json, list):
77
- for item in parsed_json:
78
- if not all(k in item for k in ('question', 'options', 'correct_answer')):
79
- raise ValueError("Invalid quiz element structure in JSON.")
80
- return parsed_json
81
- else:
82
- raise ValueError("The JSON found is not a list.")
83
- except json.JSONDecodeError:
84
- raise ValueError("No valid JSON block (list of objects) found in the result.")
85
-
86
- except json.JSONDecodeError as e:
87
- raise ValueError(f"JSON decoding error: {str(e)}. Contenu reçu : '{result_text[:200]}...'")
88
- except ValueError as e:
89
- raise e
90
-
91
- def research_task(topic: str, agent: Agent) -> Task:
92
  return Task(
93
- description=dedent(f"""Thorough research on '{topic}'.
94
- Identify and compile key factual information: definitions, dates,
95
- important figures, fundamental concepts, and significant events.
96
- Structure the information clearly and concisely."""),
97
- expected_output=dedent(f"""A synthetic report containing the most relevant information
98
- on '{topic}', ready to be used to create a quiz.
99
- Must include precise and verifiable facts."""),
100
- agent=agent,
101
  )
102
 
103
- def quiz_creation_task(topic: str, agent: Agent, context_task: Task) -> Task:
104
  return Task(
105
- description=dedent(f"""Based STRICTLY on the information provided in the context
106
- of the research on '{topic}', create a multiple-choice quiz.
107
- Generate between 8 and 12 pertinent questions.
108
- For each question, provide: 'question', 'options', 'correct_answer', and 'explanation'.
109
- The output format MUST be a valid JSON list and NOTHING ELSE."""),
110
- expected_output=dedent("""A valid JSON list, where each element is a quiz question
111
- with the keys 'question', 'options', 'correct_answer', and 'explanation'."""),
112
- agent=agent,
113
- context=[context_task]
114
  )
115
 
116
- app = Flask(__name__)
117
- app.secret_key = os.urandom(24)
118
-
119
  @app.route('/')
120
  def index():
121
  return render_template('index.html')
122
 
123
  @app.route('/generate', methods=['POST'])
124
- def generate_quiz_endpoint():
125
- if not request.is_json:
126
- return jsonify({'error': 'Invalid request, JSON expected.'}), 400
127
-
128
- data = request.get_json()
129
- topic = data.get('topic')
130
-
131
- if not topic or not isinstance(topic, str) or len(topic.strip()) == 0:
132
- return jsonify({'error': 'The "topic" field is missing or invalid.'}), 400
133
-
134
- topic = topic.strip()
135
 
136
  try:
137
- task_research = research_task(topic=topic, agent=researcher)
138
- task_quiz = quiz_creation_task(topic=topic, agent=quiz_creator, context_task=task_research)
139
-
140
- quiz_crew = Crew(
141
- agents=[researcher, quiz_creator],
142
- tasks=[task_research, task_quiz],
 
 
143
  process=Process.sequential,
144
- verbose=2
145
  )
146
 
147
- crew_result = quiz_crew.kickoff(inputs={'topic': topic})
148
-
149
- if not crew_result or not hasattr(quiz_crew, 'tasks_output') or not quiz_crew.tasks_output:
150
- return jsonify({'error': 'Quiz generation failed (no crew output).'}), 500
151
-
152
- last_task_output = quiz_crew.tasks_output[-1]
153
- raw_output = last_task_output.raw
154
-
155
- if not raw_output:
156
- return jsonify({'error': 'Quiz generation failed (empty task output).'}), 500
157
-
158
- try:
159
- quiz_data = extract_json_from_result(raw_output)
160
- return jsonify({'success': True, 'quiz': quiz_data})
161
-
162
- except ValueError as json_error:
163
- return jsonify({'error': f'Error during quiz finalization: {json_error}'}), 500
164
 
165
  except Exception as e:
166
- import traceback
167
- traceback.print_exc()
168
- return jsonify({'error': f'A server error occurred: {str(e)}'}), 500
169
 
170
  if __name__ == '__main__':
171
- app.run(host='0.0.0.0', port=5000, debug=True)
 
1
+ from flask import Flask, render_template, request, jsonify
2
  import os
3
  import json
4
  from textwrap import dedent
 
5
  from crewai import Agent, Crew, Process, Task
6
  from crewai_tools import SerperDevTool
7
+ from crewai import LLM
8
+ from typing import List
9
 
10
+ app = Flask(__name__)
11
+
12
+ # Configuration des clés API
13
  os.environ["GEMINI_API_KEY"] = "AIzaSyCQpoVCdk7h7MvAQKZOUfcnkQYVkHmAKwI"
14
  os.environ["SERPER_API_KEY"] = "9b90a274d9e704ff5b21c0367f9ae1161779b573"
15
+
16
+ llm = LLM(
17
+ model="gemini/gemini-2.0-flash",
18
+ temperature=1,
19
+ timeout=120,
20
+ max_tokens=8000,
 
 
 
 
 
 
 
 
21
  )
22
 
23
+ # Initialisation de l'outil de recherche
24
  search_tool = SerperDevTool()
25
 
26
+ # Définition des agents
27
  researcher = Agent(
28
+ role='Chercheur de Sujets',
29
+ goal=dedent("""Trouver les informations les plus pertinentes et précises sur {topic}
30
+ en utilisant l'API SerpApi."""),
31
+ backstory=dedent("""Un chercheur expert spécialisé dans la collecte d'informations sur divers sujets.
32
+ Capable d'utiliser l'API SerpApi pour des recherches précises et efficaces."""),
33
  tools=[search_tool],
34
  llm=llm,
35
  verbose=True,
36
+ allow_delegation=False
 
37
  )
38
 
39
+ writer = Agent(
40
+ role='Rédacteur de Flashcards',
41
+ goal=dedent("""Créer des flashcards claires et concises en format question-réponse
42
+ basées sur les informations fournies par le Chercheur."""),
43
+ backstory=dedent("""Un expert en pédagogie et en création de matériel d'apprentissage.
44
+ Capable de transformer des informations complexes en flashcards simples et mémorisables."""),
 
 
45
  llm=llm,
46
  verbose=True,
47
+ allow_delegation=False
 
48
  )
49
 
50
+ def extract_json_from_result(result_text: str) -> list:
51
+ """Extrait le JSON des résultats de la crew."""
52
  try:
53
  json_start = result_text.find('[')
54
  json_end = result_text.rfind(']') + 1
55
+ if json_start == -1 or json_end == 0:
56
+ raise ValueError("JSON non trouvé dans le résultat")
57
+
58
+ json_str = result_text[json_start:json_end]
59
+ return json.loads(json_str)
60
+ except (json.JSONDecodeError, ValueError) as e:
61
+ raise ValueError(f"Erreur lors de l'extraction du JSON : {str(e)}")
62
+
63
+ def research_task(topic: str) -> Task:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
64
  return Task(
65
+ description=dedent(f"""Effectuer une recherche approfondie sur le sujet '{topic}'.
66
+ Compiler les informations les plus pertinentes et les plus récentes."""),
67
+ expected_output="Une liste d'informations pertinentes sur le sujet.",
68
+ agent=researcher
 
 
 
 
69
  )
70
 
71
+ def flashcard_creation_task(research_task: Task) -> Task:
72
  return Task(
73
+ description=dedent("""Transformer les informations fournies par le Chercheur
74
+ en une série de flashcards au format JSON. Je veux une vingtaine de flashcard robuste et complet avec des questions et des réponses détailler. Chaque flashcard doit avoir une question
75
+ d'un côté et une réponse concise de l'autre."""),
76
+ expected_output="Une liste de flashcards au format JSON.",
77
+ agent=writer,
78
+ context=[research_task]
 
 
 
79
  )
80
 
 
 
 
81
  @app.route('/')
82
  def index():
83
  return render_template('index.html')
84
 
85
  @app.route('/generate', methods=['POST'])
86
+ def generate_flashcards():
87
+ topic = request.json.get('topic')
88
+ if not topic:
89
+ return jsonify({'error': 'Veuillez entrer un sujet.'}), 400
 
 
 
 
 
 
 
90
 
91
  try:
92
+ # Création des tâches
93
+ research = research_task(topic)
94
+ flashcard_creation = flashcard_creation_task(research)
95
+
96
+ # Création de la crew
97
+ crew = Crew(
98
+ agents=[researcher, writer],
99
+ tasks=[research, flashcard_creation],
100
  process=Process.sequential,
101
+ verbose=True
102
  )
103
 
104
+ # Exécution de la crew
105
+ result = crew.kickoff()
106
+
107
+ # Extraction du JSON depuis le dernier résultat de tâche
108
+ if result.tasks_output and len(result.tasks_output) > 0:
109
+ last_task_output = result.tasks_output[-1].raw
110
+ flashcards = extract_json_from_result(last_task_output)
111
+ return jsonify({'success': True, 'flashcards': flashcards})
112
+ else:
113
+ return jsonify({'error': 'Aucun résultat généré par la crew.'}), 500
 
 
 
 
 
 
 
114
 
115
  except Exception as e:
116
+ return jsonify({'error': 'error'}), 500
 
 
117
 
118
  if __name__ == '__main__':
119
+ app.run(debug=True)