File size: 6,750 Bytes
b7844e1 b237e11 b7844e1 e1feafa b7844e1 e1feafa b7844e1 e1feafa b7844e1 e1feafa b7844e1 a415b40 b7844e1 a415b40 b7844e1 a415b40 b7844e1 687de48 b7844e1 e1feafa a415b40 b7844e1 a415b40 b7844e1 a415b40 b7844e1 a415b40 b7844e1 a415b40 b7844e1 a415b40 b7844e1 e1feafa b7844e1 a415b40 b7844e1 a415b40 b7844e1 b237e11 687de48 b7844e1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 |
import os
import json
from textwrap import dedent
from flask import Flask, render_template, request, jsonify
from crewai import Agent, Crew, Process, Task
from crewai_tools import SerperDevTool
from langchain_google_genai import ChatGoogleGenerativeAI
from typing import List, Dict, Any
# Configuration (use .env in production)
os.environ["GEMINI_API_KEY"] = "AIzaSyCQpoVCdk7h7MvAQKZOUfcnkQYVkHmAKwI"
os.environ["SERPER_API_KEY"] = "9b90a274d9e704ff5b21c0367f9ae1161779b573"
gemini_api_key = os.environ.get("GEMINI_API_KEY")
serper_api_key = os.environ.get("SERPER_API_KEY")
if not gemini_api_key:
raise ValueError("Gemini API key missing.")
if not serper_api_key:
raise ValueError("Serper API key missing.")
llm = ChatGoogleGenerativeAI(
model="gemini-2.0-flash",
temperature=0.7,
google_api_key=gemini_api_key,
max_output_tokens=8000,
convert_system_message_to_human=True
)
search_tool = SerperDevTool()
researcher = Agent(
role='Chercheur de Sujets Académiques',
goal=dedent("""Find factual, precise information on {topic} using the web search tool.
Focus on key concepts, definitions, dates, and notable facts."""),
backstory=dedent("""A meticulous researcher with a developed critical mind.
Synthesizes information from multiple sources to extract the factual essence."""),
tools=[search_tool],
llm=llm,
verbose=True,
allow_delegation=False,
max_iter=5
)
quiz_creator = Agent(
role='Concepteur Pédagogique de Quiz',
goal=dedent("""Create an engaging multiple-choice quiz based on the factual information
provided by the Researcher on {topic}.
Formulate clear questions, plausible options, and identify the correct answer.
Include a concise explanation for each question."""),
backstory=dedent("""A specialist in pedagogical design who excels at transforming
raw information into effective evaluation tools."""),
llm=llm,
verbose=True,
allow_delegation=False,
max_iter=3
)
def extract_json_from_result(result_text: str) -> List[Dict[str, Any]]:
try:
json_start = result_text.find('[')
json_end = result_text.rfind(']') + 1
if json_start != -1 and json_end != 0 and json_end > json_start:
json_str = result_text[json_start:json_end]
parsed_json = json.loads(json_str)
if isinstance(parsed_json, list):
for item in parsed_json:
if not all(k in item for k in ('question', 'options', 'correct_answer')):
raise ValueError("Invalid quiz element structure in JSON.")
return parsed_json
else:
raise ValueError("The extracted JSON is not a list.")
else:
try:
parsed_json = json.loads(result_text)
if isinstance(parsed_json, list):
for item in parsed_json:
if not all(k in item for k in ('question', 'options', 'correct_answer')):
raise ValueError("Invalid quiz element structure in JSON.")
return parsed_json
else:
raise ValueError("The JSON found is not a list.")
except json.JSONDecodeError:
raise ValueError("No valid JSON block (list of objects) found in the result.")
except json.JSONDecodeError as e:
raise ValueError(f"JSON decoding error: {str(e)}. Contenu reçu : '{result_text[:200]}...'")
except ValueError as e:
raise e
def research_task(topic: str, agent: Agent) -> Task:
return Task(
description=dedent(f"""Thorough research on '{topic}'.
Identify and compile key factual information: definitions, dates,
important figures, fundamental concepts, and significant events.
Structure the information clearly and concisely."""),
expected_output=dedent(f"""A synthetic report containing the most relevant information
on '{topic}', ready to be used to create a quiz.
Must include precise and verifiable facts."""),
agent=agent,
)
def quiz_creation_task(topic: str, agent: Agent, context_task: Task) -> Task:
return Task(
description=dedent(f"""Based STRICTLY on the information provided in the context
of the research on '{topic}', create a multiple-choice quiz.
Generate between 8 and 12 pertinent questions.
For each question, provide: 'question', 'options', 'correct_answer', and 'explanation'.
The output format MUST be a valid JSON list and NOTHING ELSE."""),
expected_output=dedent("""A valid JSON list, where each element is a quiz question
with the keys 'question', 'options', 'correct_answer', and 'explanation'."""),
agent=agent,
context=[context_task]
)
app = Flask(__name__)
app.secret_key = os.urandom(24)
@app.route('/')
def index():
return render_template('index.html')
@app.route('/generate', methods=['POST'])
def generate_quiz_endpoint():
if not request.is_json:
return jsonify({'error': 'Invalid request, JSON expected.'}), 400
data = request.get_json()
topic = data.get('topic')
if not topic or not isinstance(topic, str) or len(topic.strip()) == 0:
return jsonify({'error': 'The "topic" field is missing or invalid.'}), 400
topic = topic.strip()
try:
task_research = research_task(topic=topic, agent=researcher)
task_quiz = quiz_creation_task(topic=topic, agent=quiz_creator, context_task=task_research)
quiz_crew = Crew(
agents=[researcher, quiz_creator],
tasks=[task_research, task_quiz],
process=Process.sequential,
verbose=2
)
crew_result = quiz_crew.kickoff(inputs={'topic': topic})
if not crew_result or not hasattr(quiz_crew, 'tasks_output') or not quiz_crew.tasks_output:
return jsonify({'error': 'Quiz generation failed (no crew output).'}), 500
last_task_output = quiz_crew.tasks_output[-1]
raw_output = last_task_output.raw
if not raw_output:
return jsonify({'error': 'Quiz generation failed (empty task output).'}), 500
try:
quiz_data = extract_json_from_result(raw_output)
return jsonify({'success': True, 'quiz': quiz_data})
except ValueError as json_error:
return jsonify({'error': f'Error during quiz finalization: {json_error}'}), 500
except Exception as e:
import traceback
traceback.print_exc()
return jsonify({'error': f'A server error occurred: {str(e)}'}), 500
if __name__ == '__main__':
app.run(host='0.0.0.0', port=5000, debug=True) |