Attaque2 / app.py
Docfile's picture
Upload app.py
b7844e1 verified
raw
history blame
6.75 kB
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)