Spaces:
Sleeping
Sleeping
Commit ·
24a01ba
0
Parent(s):
v3 initial
Browse files- .gitignore +6 -0
- Dockerfile +21 -0
- README.md +10 -0
- agents/analysis_phase/Introduction.py +111 -0
- agents/analysis_phase/__init__.py +10 -0
- agents/analysis_phase/analysis.py +99 -0
- agents/analysis_phase/analysis_report.py +61 -0
- agents/analysis_phase/objectives.py +287 -0
- agents/analysis_phase/outcomes.py +305 -0
- agents/analysis_phase/outliner.py +97 -0
- agents/design_phase/__init__.py +3 -0
- agents/design_phase/extractor.py +75 -0
- agents/design_phase/keywoard_researcher.py +50 -0
- agents/design_phase/source_finder.py +69 -0
- agents/final_outliners/__init__.py +4 -0
- agents/final_outliners/subtopics_generator.py +129 -0
- agents/final_outliners/units_langchain.py +67 -0
- agents/final_outliners/units_langchain_1v.py +58 -0
- agents/final_outliners/validator.py +139 -0
- agents/outliner_phase/Deep_Semantic_Topics_Generator_1.py +118 -0
- agents/outliner_phase/__init__.py +4 -0
- agents/outliner_phase/module_organizer_3.py +46 -0
- agents/outliner_phase/review_agent_4.py +35 -0
- agents/outliner_phase/topic_expander_2.py +43 -0
- app.py +60 -0
- modules/__init__.py +28 -0
- modules/directory.py +12 -0
- modules/env.py +73 -0
- modules/inputs.py +736 -0
- requirements.txt +15 -0
- routers/introduction_route.py +59 -0
- routers/objective_route.py +51 -0
- routers/outcome_route.py +50 -0
- routers/outliner_route.py +66 -0
- schemas/__init__.py +19 -0
- schemas/analysis_schema.py +32 -0
- schemas/dna_schema.py +82 -0
- schemas/extractor_schema.py +22 -0
- schemas/inputs_schema.py +29 -0
- schemas/introduction_schema.py +10 -0
- schemas/keywoard_schema.py +14 -0
- schemas/objectives_schema.py +65 -0
- schemas/outcomes_schema.py +28 -0
- schemas/outliner_schema.py +207 -0
- schemas/source_schema.py +13 -0
- tools/__init__.py +3 -0
- tools/chapter_division.py +46 -0
- tools/scraper.py +32 -0
- tools/tavily.py +64 -0
.gitignore
ADDED
|
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
.env
|
| 2 |
+
__pycache__/
|
| 3 |
+
*.pyc
|
| 4 |
+
*.pyo
|
| 5 |
+
modules\firebase_credentials.json
|
| 6 |
+
test*
|
Dockerfile
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# استخدم صورة أساسية خفيفة من Python
|
| 2 |
+
FROM python:3.10
|
| 3 |
+
|
| 4 |
+
# اضبط مجلد العمل داخل الحاوية
|
| 5 |
+
WORKDIR /app
|
| 6 |
+
|
| 7 |
+
# انسخ ملفات المشروع
|
| 8 |
+
COPY . /app
|
| 9 |
+
|
| 10 |
+
# انسخ ملف requirements لو عندك
|
| 11 |
+
COPY requirements.txt .
|
| 12 |
+
|
| 13 |
+
# نزّل المتطلبات
|
| 14 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
# عرّف البورت اللي البرنامج هيشتغل عليه
|
| 18 |
+
EXPOSE 7860
|
| 19 |
+
|
| 20 |
+
# لو بتستخدم FastAPI (مع uvicorn):
|
| 21 |
+
CMD ["uvicorn", "app:app", "--host", "0.0.0.0", "--port", "7860"]
|
README.md
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: ContiAI-v3
|
| 3 |
+
emoji: 🐨
|
| 4 |
+
colorFrom: blue
|
| 5 |
+
colorTo: green
|
| 6 |
+
sdk: docker
|
| 7 |
+
pinned: false
|
| 8 |
+
license: apache-2.0
|
| 9 |
+
app_port: 7860
|
| 10 |
+
---
|
agents/analysis_phase/Introduction.py
ADDED
|
@@ -0,0 +1,111 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm_g
|
| 5 |
+
from schemas import IntroductionOutput
|
| 6 |
+
|
| 7 |
+
intro_agent = Agent(
|
| 8 |
+
role="Human-Crafted Arabic Introduction Writer",
|
| 9 |
+
goal=(
|
| 10 |
+
"Create a deeply human, stylistically rich, emotionally resonant Arabic introduction "
|
| 11 |
+
"for a training program based on the provided topic ({topic}), outlines, units, and outcomes. "
|
| 12 |
+
"The introduction must feel alive, credible, realistic, and engaging—not artificial or generic."
|
| 13 |
+
),
|
| 14 |
+
backstory=(
|
| 15 |
+
"You are a master Arabic writer and educational content designer. "
|
| 16 |
+
"You craft introductions that carry a human breath—mixing scene, reflection, emotion, "
|
| 17 |
+
"and intellectual depth without artificial phrases. "
|
| 18 |
+
"Your style avoids AI clichés and empty rhetoric, relying instead on concrete imagery, "
|
| 19 |
+
"varied rhythm, personal tone, and subtle storytelling. "
|
| 20 |
+
"You write for {audience} with professionalism, depth, and authenticity."
|
| 21 |
+
),
|
| 22 |
+
system_template=(
|
| 23 |
+
"أنت كاتب عربي محترف تمتد خبرته إلى تصميم مقدمات تدريبية آسرة تعتمد على الصورة "
|
| 24 |
+
"الحسية، والتجربة الواقعية، والنبرة الشخصية الصادقة. كتابتك تشبه النصوص البشرية القوية "
|
| 25 |
+
"وليست مصطنعة أو آلية.\n\n"
|
| 26 |
+
"==============================\n"
|
| 27 |
+
"## قواعد الكتابة الإنسانية (ANTI-AI RULES)\n"
|
| 28 |
+
"==============================\n"
|
| 29 |
+
"يجب على المقدمة أن:\n"
|
| 30 |
+
"- تكون بين 250 و 320 كلمة.\n"
|
| 31 |
+
"- تتجنب تمامًا: هل تساءلت يومًا، ليس مجرد… بل…، في عالمنا المتسارع، رحلة متكاملة، إحداث فرق حقيقي.\n"
|
| 32 |
+
"- تتجنب الأسلوب الإنشائي الدعائي واللغة البراقة الفارغة.\n"
|
| 33 |
+
"- تحتوي على جُمل قصيرة وأخرى طويلة (تنويع الإيقاع).\n"
|
| 34 |
+
"- تتضمن لقطة أو مشهدًا واقعيًا مرتبطًا بالموضوع (مشهد صف، موقف واقعي، صورة حسيّة واضحة).\n"
|
| 35 |
+
"- تحمل لمسة شخصية: دهشة، ملاحظة، موقف شعوري، رأي بسيط.\n"
|
| 36 |
+
"- تستخدم انتقالات طبيعية نابعة من الفكرة نفسها، لا من الروابط الميكانيكية مثل: بعد ذلك، لن يكتمل، سننتقل.\n"
|
| 37 |
+
"- تستخدم لغة عربية قوية وواضحة، بلا مبالغة، بلا زخرفة، بلا تكرار.\n"
|
| 38 |
+
"- تعرض مشكلة حقيقية أو تحديًا واقعيًا يتعلق بالموضوع.\n"
|
| 39 |
+
"- تبتعد عن العموميات والعبارات المستهلكة.\n\n"
|
| 40 |
+
"==============================\n"
|
| 41 |
+
"## أساليب افتتاح مسموح بها\n"
|
| 42 |
+
"==============================\n"
|
| 43 |
+
"يمكنك البدء بـ:\n"
|
| 44 |
+
"- مشهد قصير واقعي.\n"
|
| 45 |
+
"- سطر من تجربة إنسانية.\n"
|
| 46 |
+
"- تساؤل تأملي صادق (غير إنشائي).\n"
|
| 47 |
+
"- حقيقة أو رقم لها علاقة مباشرة بالموضوع.\n"
|
| 48 |
+
"- حكمة أو قول مناسب لكن غير مستهلك.\n\n"
|
| 49 |
+
"==============================\n"
|
| 50 |
+
"## البنية المرنة للمقدمة\n"
|
| 51 |
+
"==============================\n"
|
| 52 |
+
"1. افتتاح مشهدي أو واقعي أو تأملي.\n"
|
| 53 |
+
"2. ربط المشهد بطبيعة موضوع التدريب.\n"
|
| 54 |
+
"3. عرض المشكلة أو التحدي الحقيقي الذي يعالجه البرنامج.\n"
|
| 55 |
+
"4. توضيح قيمة الموضوع والفائدة بأسلوب ملموس لا إنشائي.\n"
|
| 56 |
+
"5. وعد تعليمي مشتق من المخرجات لكن بلغة إنسانية طبيعية.\n\n"
|
| 57 |
+
"==============================\n"
|
| 58 |
+
"## تعليمات إضافية لضمان الأسلوب البشري\n"
|
| 59 |
+
"==============================\n"
|
| 60 |
+
"- استخدم صورًا حسية: صوت، ضوء، حركة، مشهد، شعور.\n"
|
| 61 |
+
"- لا تجعل الجمل كلها بنفس الإيقاع أو الطول.\n"
|
| 62 |
+
"- لا تبدأ بأسئلة رنانة بلا معنى.\n"
|
| 63 |
+
"- تجنب الترتيب النمطي للجمل الذي ينتجه الذكاء الاصطناعي.\n"
|
| 64 |
+
"- قدم فائدة أو ملاحظة شخصية حقيقية.\n"
|
| 65 |
+
"- اربط الكلمات بالموقف وليس بالقوالب.\n\n"
|
| 66 |
+
),
|
| 67 |
+
llm=llm_g,
|
| 68 |
+
memory=False,
|
| 69 |
+
allow_delegation=False,
|
| 70 |
+
verbose=True,
|
| 71 |
+
max_iter=50,
|
| 72 |
+
cache=False,
|
| 73 |
+
)
|
| 74 |
+
|
| 75 |
+
intro_task = Task(
|
| 76 |
+
description=(
|
| 77 |
+
"Write a human-like Arabic introduction (300–400 words) that reflects true human rhythm, "
|
| 78 |
+
"## INPUT\n"
|
| 79 |
+
"You have access to the program’s full context:\n"
|
| 80 |
+
"- Topic: {topic}\n"
|
| 81 |
+
"- Outline (units and subtopics): {outlines}\n"
|
| 82 |
+
"- Unit details: {units}\n"
|
| 83 |
+
"- Learning outcomes: {outcomes}\n\n"
|
| 84 |
+
"## OBJECTIVE\n"
|
| 85 |
+
"Write an Arabic introduction that connects the learner emotionally and intellectually to the training content. "
|
| 86 |
+
"The introduction must:\n"
|
| 87 |
+
"- Reflect the program’s educational goals and outcomes.\n"
|
| 88 |
+
"- Be motivational, concise, and linguistically natural for {audience}.\n"
|
| 89 |
+
"## MUST INCLUDE:\n"
|
| 90 |
+
"• نبرة شخصية.\n"
|
| 91 |
+
"• لغة خالية من الإنشاء المكرر والعبارات المستهلكة.\n"
|
| 92 |
+
"• تنويع طول الجمل.\n"
|
| 93 |
+
"• انتقالات طبيعية.\n\n"
|
| 94 |
+
"## MUST AVOID:\n"
|
| 95 |
+
"• الأسئلة الافتتاحية المعلبة.\n"
|
| 96 |
+
"• الإنشاء الفارغ.\n"
|
| 97 |
+
"• الإفراط في الجمل الطويلة.\n"
|
| 98 |
+
"• العبارات التسويقية.\n"
|
| 99 |
+
"• الكلمات اللامعة الخاوية.\n\n"
|
| 100 |
+
"### OUTPUT\n"
|
| 101 |
+
"Return the IntroductionOutput structure in valid JSON format.\n\n"
|
| 102 |
+
),
|
| 103 |
+
expected_output="""JSON object with this structure:
|
| 104 |
+
{
|
| 105 |
+
"introduction": "engaging introduction to the training program content, max 300 words."
|
| 106 |
+
}
|
| 107 |
+
""",
|
| 108 |
+
output_json=IntroductionOutput,
|
| 109 |
+
agent=intro_agent,
|
| 110 |
+
human_input=False,
|
| 111 |
+
)
|
agents/analysis_phase/__init__.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .analysis_report import report_agent, report_task
|
| 2 |
+
from .analysis import analysis_agent, analysis_task
|
| 3 |
+
from .objectives import (
|
| 4 |
+
objectives_generator,
|
| 5 |
+
objectives_task,
|
| 6 |
+
get_bloom_verb,
|
| 7 |
+
)
|
| 8 |
+
from .outcomes import outcomes_generator, outcomes_task
|
| 9 |
+
from .outliner import outline_agent, outline_task
|
| 10 |
+
from .Introduction import intro_agent, intro_task
|
agents/analysis_phase/analysis.py
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
from schemas import AnalysisOutput
|
| 6 |
+
|
| 7 |
+
analysis_agent = Agent(
|
| 8 |
+
role="Training Analysis Agent",
|
| 9 |
+
goal="\n".join(
|
| 10 |
+
[
|
| 11 |
+
"Generate the analysis phase for the training program in Arabic based on the topic, outline, and training outcomes.",
|
| 12 |
+
"Follow the DNA methodology defined in the Outline Agent.",
|
| 13 |
+
"and follow the DNA parameters ({domain}, {content_type}, {audience}, {material_type}).",
|
| 14 |
+
"The analysis must include the following elements (taken from the official analysis framework):",
|
| 15 |
+
"",
|
| 16 |
+
"1. Goal:",
|
| 17 |
+
"- Overall goal expected after the training program.",
|
| 18 |
+
"- Must start with: 'أن يتمكّن المتدرب من ...'.",
|
| 19 |
+
"- Should be a complete sentence covering all training topics.",
|
| 20 |
+
"- Must be comprehensive, not limited to one aspect.",
|
| 21 |
+
"",
|
| 22 |
+
"2. Target Audience:",
|
| 23 |
+
"- The group receiving the training.",
|
| 24 |
+
"- Include average age (e.g., شباب في العشرينات، موظفون في الثلاثينات).",
|
| 25 |
+
"",
|
| 26 |
+
"3. Previous Experiences:",
|
| 27 |
+
"- Short sentences written as noun-phrases (مصادر).",
|
| 28 |
+
"- Express prior practical or knowledge-based experiences.",
|
| 29 |
+
"- Examples: ممارسة أنشطة جماعية، مواجهة ضغوط العمل، استخدام أدوات تنظيم، الالتزام بجداول، إدارة مهام يومية.",
|
| 30 |
+
"",
|
| 31 |
+
"4. Learner Characteristics:",
|
| 32 |
+
"- Common traits considering age and developmental aspects:",
|
| 33 |
+
" * Linguistic development: improving oral expression and listening.",
|
| 34 |
+
" * Cognitive development: analyzing and linking concepts, applying analytical skills.",
|
| 35 |
+
" * Social development: tendency to interact and collaborate.",
|
| 36 |
+
" * Emotional development: reacting to emotional situations.",
|
| 37 |
+
" * Personality growth: building independent identity and attitudes.",
|
| 38 |
+
" * Learning styles: preference for practical, auditory, or visual learning.",
|
| 39 |
+
"",
|
| 40 |
+
"5. Training Needs:",
|
| 41 |
+
"- Represent what the learner needs in skills, knowledge, and behaviors.",
|
| 42 |
+
"- Must be extracted from the training topics.",
|
| 43 |
+
"- 6 sentences required, each a noun-phrase.",
|
| 44 |
+
"- Each starts with a مصدر (e.g., فهم، إدراك، توظيف، استيعاب).",
|
| 45 |
+
"- Must not be copied titles but rephrased needs.",
|
| 46 |
+
"",
|
| 47 |
+
"6. Constraints:",
|
| 48 |
+
"- Barriers that may negatively affect training.",
|
| 49 |
+
"- Two types:",
|
| 50 |
+
" * Trainer constraints (4 sentences):Examples: (e.g.,ضيق الوقت، محدودية الوسائل التعليمية، تباين مستويات المتدربين، قلة الدعم الإداري.).",
|
| 51 |
+
" * Trainee constraints (4 sentences): Examples:(e.g.,ضعف الالتزام، ضعف الحافز، انشغالات شخصية، قلة الخبرة التقنية.).",
|
| 52 |
+
"- All sentences must start with a مصدر (محدودية، ضعف، صعوبة، تباين).",
|
| 53 |
+
"- Written as complete noun-phrases only.",
|
| 54 |
+
"",
|
| 55 |
+
"7. Duration:",
|
| 56 |
+
"- Exact training duration (hours/days).",
|
| 57 |
+
"- Training day = 4 hours.",
|
| 58 |
+
"- Examples: دورة يوم واحد = 4 ساعات، دورتان = 8 ساعات.",
|
| 59 |
+
"",
|
| 60 |
+
"8. Sources of Analysis:",
|
| 61 |
+
"- Pre-training instructional design processes.",
|
| 62 |
+
"- Examples: البحث عن مصادر علمية، تحليل احتياجات المتدربين، دراسة محاور الدورة، تحديد الفجوات بين الواقع والمأمول، تجميع البيانات.",
|
| 63 |
+
"- Must be written as noun-phrases starting and ending with a مصدر (e.g., جمع البيانات وتحليلها).",
|
| 64 |
+
]
|
| 65 |
+
),
|
| 66 |
+
backstory="\n".join(
|
| 67 |
+
[
|
| 68 |
+
"This agent acts as an instructional designer responsible for producing the full analysis phase.",
|
| 69 |
+
"It ensures outputs are consistent with the Arabic training framework (مرحلة التحليل).",
|
| 70 |
+
"It builds on the Outline and Training Outcomes, while following DNA methodology and ollow the DNA parameters (domain, content_type, audience, material_type).",
|
| 71 |
+
]
|
| 72 |
+
),
|
| 73 |
+
llm=llm,
|
| 74 |
+
verbose=True,
|
| 75 |
+
)
|
| 76 |
+
|
| 77 |
+
# ====== Task ======
|
| 78 |
+
analysis_task = Task(
|
| 79 |
+
description="\n".join(
|
| 80 |
+
[
|
| 81 |
+
"Generate the complete analysis phase in Arabic for the training program.",
|
| 82 |
+
"Use the outline (main_headings + sub_headings + sub_sub_headings) and training outcomes as input.",
|
| 83 |
+
"Follow the analysis framework:",
|
| 84 |
+
"- Goal",
|
| 85 |
+
"- Target Audience",
|
| 86 |
+
"- Previous Experiences",
|
| 87 |
+
"- Learner Characteristics",
|
| 88 |
+
"- Training Needs",
|
| 89 |
+
"- Constraints",
|
| 90 |
+
"- Duration",
|
| 91 |
+
"- Sources of Analysis",
|
| 92 |
+
"Ensure all outputs are written in Arabic, concise, and aligned with DNA methodology.",
|
| 93 |
+
"Output must strictly match the Pydantic schema (AnalysisOutput) and be in JSON format.",
|
| 94 |
+
]
|
| 95 |
+
),
|
| 96 |
+
expected_output="A JSON object in Arabic with all required analysis fields.",
|
| 97 |
+
output_json=AnalysisOutput,
|
| 98 |
+
agent=analysis_agent,
|
| 99 |
+
)
|
agents/analysis_phase/analysis_report.py
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
|
| 6 |
+
# ====== Agent ======
|
| 7 |
+
report_agent = Agent(
|
| 8 |
+
role="Training Report Builder",
|
| 9 |
+
goal="\n".join(
|
| 10 |
+
[
|
| 11 |
+
"Take the outputs from title_agent, outline_agent, training_agent, and analysis_agent.",
|
| 12 |
+
"Generate a well-structured HTML report in Arabic.",
|
| 13 |
+
"",
|
| 14 |
+
"Rules:",
|
| 15 |
+
"- At the very top of the page, display the title from title_agent output as a main heading (<h1>).",
|
| 16 |
+
"- The training_agent introduction should appear under a section titled: 'المقدمة'.",
|
| 17 |
+
"- The outline_agent output should appear under a section titled: 'محتويات الحقيبة'.",
|
| 18 |
+
"- The training_agent learning outcomes should appear under a section titled: 'مخرجات البرنامج التدريبي'.",
|
| 19 |
+
"- The analysis_agent output should appear under a section titled: 'مرحلة التحليل'.",
|
| 20 |
+
"",
|
| 21 |
+
"For the 'مرحلة التحليل' section:",
|
| 22 |
+
"- Present it inside an HTML table.",
|
| 23 |
+
"- The table should have two columns: 'العنصر' and 'الوصف'.",
|
| 24 |
+
"- Each row corresponds to one analysis element (الهدف، الفئة المستهدفة، الخبرات السابقة، خصائص المتدربين، الاحتياجات التدريبية، القيود، المدة الزمنية، مصادر التحليل).",
|
| 25 |
+
"",
|
| 26 |
+
"The final HTML page should be clean and well-structured with Arabic titles and proper formatting.",
|
| 27 |
+
]
|
| 28 |
+
),
|
| 29 |
+
backstory="\n".join(
|
| 30 |
+
[
|
| 31 |
+
"This agent acts as a report generator.",
|
| 32 |
+
"It combines all outputs (title, outline, training outcomes, analysis) into one structured HTML training portfolio.",
|
| 33 |
+
]
|
| 34 |
+
),
|
| 35 |
+
llm=llm,
|
| 36 |
+
verbose=True,
|
| 37 |
+
)
|
| 38 |
+
|
| 39 |
+
# ====== Task ======
|
| 40 |
+
report_task = Task(
|
| 41 |
+
description="\n".join(
|
| 42 |
+
[
|
| 43 |
+
"Build an HTML page combining all outputs:",
|
| 44 |
+
"- At the top of the page, show the title (from title_agent output) as <h1>.",
|
| 45 |
+
"- Section 1: 'المقدمة' → from training_agent output (introduction).",
|
| 46 |
+
"- Section 2: 'محتويات الحقيبة' → from outline_agent output.",
|
| 47 |
+
"- Section 3: 'مخرجات البرنامج التدريبي' → from training_agent output (learning outcomes as a bulleted list).",
|
| 48 |
+
"- Section 4: 'مرحلة التحليل' → from analysis_agent output.",
|
| 49 |
+
" - The analysis section must be presented inside an HTML table same as this template {html_template}.",
|
| 50 |
+
"use css style to enhance the design more and the table responsive.",
|
| 51 |
+
"Care about colors, headers, and fonts.",
|
| 52 |
+
"don't change the style of analysis table",
|
| 53 |
+
" - The table should have two columns: 'العنصر' and 'الوصف'.",
|
| 54 |
+
" - Each row corresponds to one analysis element (goal, target audience, previous experiences, learner characteristics, training needs, constraints, duration, sources of analysis).",
|
| 55 |
+
"",
|
| 56 |
+
"Ensure the HTML page is clean, well-structured, and properly formatted in Arabic.",
|
| 57 |
+
]
|
| 58 |
+
),
|
| 59 |
+
expected_output="A single HTML string with a title, three sections, and a table for the analysis section. and don't put the code in html``` ```",
|
| 60 |
+
agent=report_agent,
|
| 61 |
+
)
|
agents/analysis_phase/objectives.py
ADDED
|
@@ -0,0 +1,287 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import bloom_taxonomy_2, objectives_dimensions, llm_g
|
| 5 |
+
from schemas import LearningObjectivesOutput
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
def get_bloom_verb(level: str) -> str:
|
| 9 |
+
"""Returns verbs from the given Bloom's taxonomy level."""
|
| 10 |
+
|
| 11 |
+
if level not in bloom_taxonomy_2:
|
| 12 |
+
raise ValueError(f"Invalid Bloom level: {level}")
|
| 13 |
+
verbs_key = [k for k in bloom_taxonomy_2[level].keys() if "_verbs_examples" in k][0]
|
| 14 |
+
return bloom_taxonomy_2[level][verbs_key]
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
def get_verbs_by_domain_and_level(domain, level_name):
|
| 18 |
+
"""
|
| 19 |
+
استخراج الأفعال المناسبة من قاموس الأبعاد التعليمية
|
| 20 |
+
|
| 21 |
+
Args:
|
| 22 |
+
domain: "Knowledge", "Ability", or "Skills"
|
| 23 |
+
level_name: اسم المستوى مثل "Remember", "Response", "Practice"
|
| 24 |
+
|
| 25 |
+
Returns:
|
| 26 |
+
قائمة بالأفعال المتاحة
|
| 27 |
+
"""
|
| 28 |
+
if domain not in objectives_dimensions:
|
| 29 |
+
return []
|
| 30 |
+
|
| 31 |
+
for level in objectives_dimensions[domain]["levels"]:
|
| 32 |
+
if level_name.lower() in level["level_name"].lower():
|
| 33 |
+
return level["verbs_examples"]
|
| 34 |
+
|
| 35 |
+
return []
|
| 36 |
+
|
| 37 |
+
|
| 38 |
+
objectives_generator = Agent(
|
| 39 |
+
role="Expert Learning Objectives Designer (Instructional Design Specialist)",
|
| 40 |
+
goal=(
|
| 41 |
+
"Design a comprehensive list of clear, measurable, and achievable learning objectives in Arabic "
|
| 42 |
+
"for each subtopic in the training curriculum. Your objectives must be based on {topic} and the "
|
| 43 |
+
"content provided in {outlines}. "
|
| 44 |
+
"You must carefully read and analyze every subtopic title, its purpose, and the unit description "
|
| 45 |
+
"before writing any objective. "
|
| 46 |
+
"Each objective must align with Bloom’s Taxonomy and the three learning domains "
|
| 47 |
+
"(cognitive, affective, psychomotor), accurately reflect the intended learning outcome, "
|
| 48 |
+
"and meet all 12 professional instructional design standards. "
|
| 49 |
+
"**Critical:** You must maximize verb diversity across all objectives — avoid repeating the same "
|
| 50 |
+
"verb whenever possible."
|
| 51 |
+
),
|
| 52 |
+
# system_template="",
|
| 53 |
+
backstory=(
|
| 54 |
+
"You are an expert instructional designer with deep experience in creating professional training programs. "
|
| 55 |
+
"You analyze each unit and subtopic to determine the type of knowledge, skill, or attitude learners "
|
| 56 |
+
"should achieve. "
|
| 57 |
+
"Then, you write one short, measurable, learner-centered objective for each subtopic following Bloom’s "
|
| 58 |
+
"Taxonomy sequence (Remember → Understand → Apply → Analyze → Evaluate → Create). "
|
| 59 |
+
"**You are exceptionally skilled at selecting diverse and non-repetitive verbs from Bloom’s Taxonomy "
|
| 60 |
+
"and the three learning domains.** "
|
| 61 |
+
"You maintain a mental tracker of all verbs used and actively avoid repetition across the entire curriculum. "
|
| 62 |
+
"You ensure maximum verb diversity, linguistic precision, and that every objective is "
|
| 63 |
+
"clear, measurable, realistic, achievable, and free from ambiguity or linguistic complexity. "
|
| 64 |
+
"Your objectives must reflect the parameters of {domain}, {content_type}, {audience}, and {material_type}, "
|
| 65 |
+
"while covering the cognitive, psychomotor, and affective domains."
|
| 66 |
+
),
|
| 67 |
+
llm=llm_g,
|
| 68 |
+
verbose=True,
|
| 69 |
+
max_iter=100,
|
| 70 |
+
)
|
| 71 |
+
|
| 72 |
+
|
| 73 |
+
objectives_task = Task(
|
| 74 |
+
description=(
|
| 75 |
+
"You have a complete and well-structured training curriculum provided in outlines: {outlines} and units details: {units}. "
|
| 76 |
+
"Your task is to create one detailed, measurable learning objective in Arabic for each subtopic, "
|
| 77 |
+
"aligned with Bloom’s Taxonomy and the three learning domains, and consistent with the purpose of each subtopic.\n\n"
|
| 78 |
+
"### Step-by-Step Process\n"
|
| 79 |
+
"1. Read the curriculum overview to understand the full learning journey.\n"
|
| 80 |
+
"2. **Before you begin, review the complete list of Bloom’s action verbs and the three domains for each level to plan maximum diversity.**\n"
|
| 81 |
+
"3. **Create a mental or written record of verbs as you use them to avoid repetition.**\n"
|
| 82 |
+
"4. For each unit:\n"
|
| 83 |
+
" a. Analyze the unit description to understand the learning scope and intended outcomes.\n"
|
| 84 |
+
" b. For each subtopic within that unit:\n"
|
| 85 |
+
" - Carefully read the subtopic title and its purpose.\n"
|
| 86 |
+
" - Identify the main learning outcome (Knowledge, Skill, or Attitude/Behavior).\n"
|
| 87 |
+
" - **First, determine the appropriate domain: Cognitive (Knowledge), Affective (Attitude), or Psychomotor (Skills).**\n"
|
| 88 |
+
" - Choose the most suitable Bloom’s level or the appropriate level of that domain.\n"
|
| 89 |
+
" - **From the available verbs at that level, select one that has not been used before (or only minimally used).**\n"
|
| 90 |
+
" - Choose three relevant Bloom’s verbs that suit the abilities of {audience}.\n"
|
| 91 |
+
" - Write one measurable learning objective in Arabic that accurately reflects the subtopic’s purpose.\n"
|
| 92 |
+
" - **Track the chosen verb to prevent reusing it in later objectives.**\n\n"
|
| 93 |
+
"### Requirements for the Three Learning Domains\n"
|
| 94 |
+
"**Objectives must cover the three domains in a balanced way:**\n\n"
|
| 95 |
+
f"**1. Cognitive Domain (Knowledge):**\n"
|
| 96 |
+
f"{objectives_dimensions['Knowledge']['description']}\n"
|
| 97 |
+
"**Levels:**\n"
|
| 98 |
+
+ "\n".join(
|
| 99 |
+
[
|
| 100 |
+
f" - {level['level_name']}: {level['description']}\n Verbs: {', '.join(level['verbs_examples'])}"
|
| 101 |
+
for level in objectives_dimensions["Knowledge"]["levels"]
|
| 102 |
+
]
|
| 103 |
+
)
|
| 104 |
+
+ "\n\n"
|
| 105 |
+
f"**2. Affective Domain (Attitude/Ability):**\n"
|
| 106 |
+
f"{objectives_dimensions['Ability']['description']}\n"
|
| 107 |
+
"**Levels:**\n"
|
| 108 |
+
+ "\n".join(
|
| 109 |
+
[
|
| 110 |
+
f" - {level['level_name']}: {level['description']}\n Verbs: {', '.join(level['verbs_examples'])}"
|
| 111 |
+
for level in objectives_dimensions["Ability"]["levels"]
|
| 112 |
+
]
|
| 113 |
+
)
|
| 114 |
+
+ "\n\n"
|
| 115 |
+
f"**3. Psychomotor Domain (Skills):**\n"
|
| 116 |
+
f"{objectives_dimensions['Skills']['description']}\n"
|
| 117 |
+
"**Levels:**\n"
|
| 118 |
+
+ "\n".join(
|
| 119 |
+
[
|
| 120 |
+
f" - {level['level_name']}: {level['description']}\n Verbs: {', '.join(level['verbs_examples'])}"
|
| 121 |
+
for level in objectives_dimensions["Skills"]["levels"]
|
| 122 |
+
]
|
| 123 |
+
)
|
| 124 |
+
+ "\n\n"
|
| 125 |
+
"### Critical Requirement: Verb Diversity \n"
|
| 126 |
+
"**This is a top-priority rule that must be followed precisely:**\n\n"
|
| 127 |
+
"**Verb Non-Repetition Rules:**\n"
|
| 128 |
+
"1. **Maximize verb diversity** — each objective should ideally use a different verb than all previous ones.\n"
|
| 129 |
+
"2. **Before selecting a verb, check:** Have I used this verb before? If yes, choose another.\n"
|
| 130 |
+
"3. **Repeat a verb only when:**\n"
|
| 131 |
+
" - All suitable alternative verbs in that Bloom level or domain are exhausted.\n"
|
| 132 |
+
" - The subtopic’s content explicitly requires that verb for accuracy.\n"
|
| 133 |
+
" - You can justify why no other verb fits.\n"
|
| 134 |
+
"4. **Prioritize diversity over perfect synonyms** — it’s better to use a slightly different but valid verb than to repeat.\n"
|
| 135 |
+
"5. **Use the full range of verbs from Bloom and the three domains** — avoid overusing common ones like 'define' or 'explain'.\n"
|
| 136 |
+
"6. **Track verb usage:** after writing each objective, note the verb and consciously avoid it in the next.\n"
|
| 137 |
+
"7. **If repetition is necessary:**\n"
|
| 138 |
+
" - Space it out by at least 3–5 objectives.\n"
|
| 139 |
+
" - Add a justification note in your internal reasoning.\n"
|
| 140 |
+
" - Try using it in a different context or content area.\n\n"
|
| 141 |
+
"### The 12 Mandatory Design Standards — Each Objective Must Meet All\n"
|
| 142 |
+
"**Based on the detailed objectives reference document:**\n\n"
|
| 143 |
+
"1. **Linked to the general goal:**\n"
|
| 144 |
+
" - Every objective must connect to the course’s overall goal.\n"
|
| 145 |
+
" - Example: If the general goal is 'Understand the concept of e-learning', "
|
| 146 |
+
"the specific objective could be 'The trainee accurately defines e-learning.'\n\n"
|
| 147 |
+
"2. **Measurable:**\n"
|
| 148 |
+
" - Objectives must be assessable using measurable performance indicators or outcomes.\n"
|
| 149 |
+
" - Correct: 'The trainee compares synchronous and asynchronous learning accurately.'\n"
|
| 150 |
+
" - Incorrect: 'The trainee understands e-learning.' (Not measurable)\n\n"
|
| 151 |
+
"3. **Achievable:**\n"
|
| 152 |
+
" - Realistic, suitable for learner ability and course duration.\n"
|
| 153 |
+
" - Correct: 'The trainee applies the steps to create a learning management account.'\n"
|
| 154 |
+
" - Incorrect: 'The trainee develops a full e-learning system in one hour.' (Unrealistic)\n\n"
|
| 155 |
+
"4. **Covers all three domains (Cognitive, Psychomotor, Affective):**\n"
|
| 156 |
+
" - Cognitive: 'The trainee defines e-learning accurately.'\n"
|
| 157 |
+
" - Psychomotor: 'The trainee practices using LMS assessment tools.'\n"
|
| 158 |
+
" - Affective: 'The trainee demonstrates interest in participating in e-learning activities.'\n\n"
|
| 159 |
+
"5. **Aligned with Bloom’s hierarchy:**\n"
|
| 160 |
+
" - Objectives must progress logically from lower to higher levels (Remember → Create).\n\n"
|
| 161 |
+
"6. **Clarity and precision:** Objective must be completely clear and specific.\n\n"
|
| 162 |
+
"7. **Free from ambiguity:** No vague or overly complex phrasing.\n\n"
|
| 163 |
+
"8. **Vocabulary clarity:** All terms must be understandable to {audience}.\n\n"
|
| 164 |
+
"9. **Single, focused goal:** Each objective expresses only one learning outcome.\n"
|
| 165 |
+
" - Correct: 'The trainee identifies the components of a virtual classroom.'\n"
|
| 166 |
+
" - Incorrect: 'The trainee identifies and applies virtual classroom components.'\n\n"
|
| 167 |
+
"10. **Realistic and feasible:** Achievable within program time and resources.\n\n"
|
| 168 |
+
"11. **Consistent with program outcomes:** Must align with the general and specific learning outcomes.\n\n"
|
| 169 |
+
"12. **Content-linked:** Directly related to the unit or module content.\n\n"
|
| 170 |
+
"### Objective Writing Rules\n"
|
| 171 |
+
"- One objective per subtopic — no more, no less.\n"
|
| 172 |
+
"- Each must directly and precisely reflect the subtopic’s purpose.\n"
|
| 173 |
+
"- Follow Bloom’s sequence within each unit (from lower to higher order thinking).\n"
|
| 174 |
+
"- If a level doesn’t logically fit, skip it but maintain general progression.\n"
|
| 175 |
+
"- You may combine two levels (e.g., Understand + Apply) if justified by subtopic purpose.\n"
|
| 176 |
+
"- Start each objective with '[verb in present]' and keep length between 6–10 words.\n"
|
| 177 |
+
"- Use verbs suitable for {audience} — e.g., children cannot 'evaluate' or 'analyze' like professionals.\n"
|
| 178 |
+
"- **Core rule: Avoid verb repetition — use the widest possible range from all three domains.**\n"
|
| 179 |
+
"- Ensure objectives are **measurable** and **achievable**.\n"
|
| 180 |
+
"- Maintain linguistic clarity — no vague or double meanings.\n"
|
| 181 |
+
"- Each objective must express only one precise learning outcome.\n\n"
|
| 182 |
+
"### Strategies for Verb Diversity\n"
|
| 183 |
+
"**Use these strategies to ensure maximum variety:**\n\n"
|
| 184 |
+
"- **Alternate synonyms:**\n"
|
| 185 |
+
" - Instead of always 'define', use: name, list, mention, identify, classify, select.\n"
|
| 186 |
+
"- **Use less common verbs:**\n"
|
| 187 |
+
" - Distinguish, infer, demonstrate, interpret, justify, summarize, illustrate.\n"
|
| 188 |
+
"- **Match verbs to content type:**\n"
|
| 189 |
+
" - Use verbs that capture the learning result precisely.\n"
|
| 190 |
+
"- **Consult the full domain verb lists** (above) with 5–7 verbs per level.\n"
|
| 191 |
+
"- **Distribute objectives across the three domains** — avoid focusing only on the cognitive domain.\n\n"
|
| 192 |
+
"### Examples of Correct and Incorrect Objectives\n\n"
|
| 193 |
+
"**Correct Examples (Good verb diversity and domain balance):**\n"
|
| 194 |
+
"1. (Cognitive - Remember): The trainee lists five types of e-learning platforms.\n"
|
| 195 |
+
"2. (Cognitive - Understand): The trainee distinguishes between various digital assessment tools.\n"
|
| 196 |
+
"3. (Cognitive - Apply): The trainee applies active learning strategies in the classroom.\n"
|
| 197 |
+
"4. (Cognitive - Understand): The trainee infers the main benefits of blended learning.\n"
|
| 198 |
+
"5. (Psychomotor - Practice): The trainee practices designing an interactive learning activity.\n"
|
| 199 |
+
"6. (Affective - Respond): The trainee actively participates in collaborative learning discussions.\n"
|
| 200 |
+
"7. (Cognitive - Analyze): The trainee compares different instructional design models.\n"
|
| 201 |
+
"8. (Psychomotor - Adapt): The trainee adjusts learning activities to meet learner needs.\n\n"
|
| 202 |
+
"**Incorrect Examples (Verb repetition — avoid this):**\n"
|
| 203 |
+
"1. The trainee defines the types of e-learning platforms.\n"
|
| 204 |
+
"2. The trainee defines digital assessment tools.\n"
|
| 205 |
+
"3. The trainee defines active learning strategies.\n"
|
| 206 |
+
"4. The trainee defines blended learning benefits.\n"
|
| 207 |
+
"5. The trainee defines steps of activity design.\n\n"
|
| 208 |
+
"**Unclear or Unmeasurable Objectives:**\n"
|
| 209 |
+
"- 'The trainee understands e-learning.' (Vague, not measurable)\n"
|
| 210 |
+
"- 'The trainee learns how to use tools.' (Unclear — which tools?)\n"
|
| 211 |
+
"- 'The trainee becomes an expert in instructional design.' (Unrealistic, not measurable)\n\n"
|
| 212 |
+
"**Improved Versions:**\n"
|
| 213 |
+
"- 'The trainee accurately defines e-learning.'\n"
|
| 214 |
+
"- 'The trainee effectively uses LMS tools.'\n"
|
| 215 |
+
"- 'The trainee applies instructional design principles to create a learning unit.'\n\n"
|
| 216 |
+
"### Critical Quality Checklist — Verify Before Finalizing Each Objective:\n"
|
| 217 |
+
"1. ✓ Is it clear and accurately expresses the intended outcome?\n"
|
| 218 |
+
"2. ✓ Does it align with a Bloom’s level or learning domain?\n"
|
| 219 |
+
"3. ✓ Is it free from ambiguity?\n"
|
| 220 |
+
"4. ✓ Is all vocabulary appropriate for {audience}?\n"
|
| 221 |
+
"5. ✓ Does it express only one learning outcome?\n"
|
| 222 |
+
"6. ✓ Is it measurable through observable performance?\n"
|
| 223 |
+
"7. ✓ Is it realistic and achievable?\n"
|
| 224 |
+
"8. ✓ Does it align with the overall outcomes?\n"
|
| 225 |
+
"9. ✓ Is it directly linked to the subtopic content?\n"
|
| 226 |
+
"10. ✓ Is it sequenced logically (simple → complex)?\n"
|
| 227 |
+
"11. ✓ Is it suitable for the learners’ level?\n"
|
| 228 |
+
"12. ✓ Do all objectives collectively cover knowledge, skills, and attitudes?\n"
|
| 229 |
+
"**13. Verb Check: Have you reused this verb? If yes, can you replace it?**\n"
|
| 230 |
+
"**14. Domain Check: Are the objectives balanced across all three domains?**\n\n"
|
| 231 |
+
"### Self-Reflection Requirement\n"
|
| 232 |
+
"After generating all objectives for a unit, pause and evaluate:\n"
|
| 233 |
+
"- Do objectives progress logically through Bloom’s levels?\n"
|
| 234 |
+
"- **How many unique verbs did you use? Any repetition?**\n"
|
| 235 |
+
"- **Can any repeated verbs be replaced with alternatives?**\n"
|
| 236 |
+
"- Are verbs diverse and contextually appropriate?\n"
|
| 237 |
+
"- **Do objectives cover all three domains evenly?**\n"
|
| 238 |
+
"- Can an external evaluator assess each objective clearly?\n"
|
| 239 |
+
"- Are all objectives realistic for {audience} and course duration?\n\n"
|
| 240 |
+
"### Final Verification: Verb Diversity & Domain Balance\n"
|
| 241 |
+
"**Before submitting your final output:**\n"
|
| 242 |
+
"1. Count how many times each verb appears.\n"
|
| 243 |
+
"2. If any verb appears more than 2–3 times, review and replace it where possible.\n"
|
| 244 |
+
"3. Aim for at least 70–80% unique verbs across the entire curriculum.\n"
|
| 245 |
+
"4. Keep a mental record of verb use for ongoing awareness.\n"
|
| 246 |
+
"5. **Check balanced distribution:**\n"
|
| 247 |
+
" - Cognitive (Knowledge): 50–60% of objectives\n"
|
| 248 |
+
" - Affective (Attitude): 20–30% of objectives\n"
|
| 249 |
+
" - Psychomotor (Skills): 20–30% of objectives\n"
|
| 250 |
+
"6. If imbalance occurs, revisit and adjust classifications.\n\n"
|
| 251 |
+
"### Domain-Specific Guidelines\n\n"
|
| 252 |
+
"**When writing Cognitive (Knowledge) objectives:**\n"
|
| 253 |
+
"- Use for topics focused on information, understanding, applying, analyzing, evaluating, or creating.\n"
|
| 254 |
+
"- Examples: 'The trainee defines...', 'The trainee compares...', 'The trainee designs...'.\n\n"
|
| 255 |
+
"**When writing Affective (Attitude) objectives:**\n"
|
| 256 |
+
"- Use for topics involving values, emotions, interests, or behaviors.\n"
|
| 257 |
+
"- Examples: 'The trainee demonstrates interest in...', 'The trainee participates actively...', 'The trainee commits to...'.\n\n"
|
| 258 |
+
"**When writing Psychomotor (Skills) objectives:**\n"
|
| 259 |
+
"- Use for topics requiring physical, technical, or procedural performance.\n"
|
| 260 |
+
"- Examples: 'The trainee practices...', 'The trainee performs...', 'The trainee innovates...'.\n\n"
|
| 261 |
+
"### Final Important Notes\n"
|
| 262 |
+
"- **Top Priority:** Verb diversity and balanced domain distribution.\n"
|
| 263 |
+
"- **Quality over quantity:** One well-crafted, diverse objective is better than several repetitive ones.\n"
|
| 264 |
+
"- **Flexibility with precision:** Be flexible in verb choice but never compromise on accuracy.\n"
|
| 265 |
+
"- **Continuous review:** Revisit objectives regularly for diversity and balance.\n"
|
| 266 |
+
"- **Context matters:** Always choose the verb that best reflects what the learner should achieve in that specific subtopic.\n"
|
| 267 |
+
"### OUTPUT\n"
|
| 268 |
+
"Return the LearningObjectivesOutput structure in valid JSON format.\n\n"
|
| 269 |
+
),
|
| 270 |
+
expected_output="""JSON object with this structure:
|
| 271 |
+
{
|
| 272 |
+
"objectives": [
|
| 273 |
+
{
|
| 274 |
+
"unit": "Unit title",
|
| 275 |
+
"unit_description": "Brief summary of the unit scope",
|
| 276 |
+
"subtopic": "subtopic title",
|
| 277 |
+
"module_description": "Brief summary of what this subtopic covers",
|
| 278 |
+
"level": "Bloom's level assigned based on subtopic analysis",
|
| 279 |
+
"verbs": ["verb1", "verb2", "verb3"],
|
| 280 |
+
"objective": "One measurable Arabic objective"
|
| 281 |
+
}
|
| 282 |
+
]
|
| 283 |
+
}""",
|
| 284 |
+
output_json=LearningObjectivesOutput,
|
| 285 |
+
agent=objectives_generator,
|
| 286 |
+
human_input=False,
|
| 287 |
+
)
|
agents/analysis_phase/outcomes.py
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm_g
|
| 5 |
+
from schemas import LearningOutcomesOutput
|
| 6 |
+
|
| 7 |
+
outcomes_generator = Agent(
|
| 8 |
+
role="Expert DNA-Based Learning Outcomes Designer",
|
| 9 |
+
goal="\n".join(
|
| 10 |
+
[
|
| 11 |
+
"Design a comprehensive list of high-quality Arabic learning outcomes for a training program based on the learning objectives provided.",
|
| 12 |
+
"Each outcome must be measurable, aligned with Bloom's taxonomy, and crafted using the DNA methodology.",
|
| 13 |
+
"",
|
| 14 |
+
"### CRITICAL RULES FOR OUTCOMES:",
|
| 15 |
+
"",
|
| 16 |
+
"**1. LINGUISTIC STRUCTURE:**",
|
| 17 |
+
" - Outcomes MUST be phrased as infinitive nouns (مصادر) such as: فهم، إدراك، تطبيق، تحليل، تقييم، تصميم.",
|
| 18 |
+
" - Use the verbal noun form (المصدر) not the verb itself.",
|
| 19 |
+
" - Structure: [مصدر] + [المحتوى/الموضوع] + [السياق إن وُجد]",
|
| 20 |
+
" - Example: 'فهم مبادئ التعليم الإلكتروني' NOT 'أن يفهم المتدرب...'",
|
| 21 |
+
"",
|
| 22 |
+
"**2. BLOOM'S TAXONOMY ALIGNMENT:**",
|
| 23 |
+
" - Outcomes MUST be strictly ordered according to Bloom's taxonomy hierarchy:",
|
| 24 |
+
" • Remember (التذكر) → Understand (الفهم) → Apply (التطبيق) → Analyze (التحليل) → Evaluate (التقييم) → Create (الإبداع)",
|
| 25 |
+
" - Start from lower cognitive levels and progress to higher levels.",
|
| 26 |
+
" - Each outcome must accurately reflect its assigned Bloom's level.",
|
| 27 |
+
" - Use appropriate verbal nouns (مصادر) that match the cognitive level.",
|
| 28 |
+
"",
|
| 29 |
+
"**3. VERB/NOUN DIVERSITY:**",
|
| 30 |
+
" - CRITICAL: Maximize diversity in verbal nouns (مصادر) across all outcomes.",
|
| 31 |
+
" - Avoid repeating the same مصدر unless absolutely necessary.",
|
| 32 |
+
" - Use synonyms and varied expressions within the same Bloom's level.",
|
| 33 |
+
" - Track usage to ensure maximum variety throughout the outcomes list.",
|
| 34 |
+
"",
|
| 35 |
+
"**4. CLARITY AND CONCISENESS:**",
|
| 36 |
+
" - Each outcome must be concise: 10-15 words maximum.",
|
| 37 |
+
" - Use clear, unambiguous language appropriate for {audience}.",
|
| 38 |
+
" - Avoid complex grammatical structures or nested phrases.",
|
| 39 |
+
" - Ensure smooth, natural Arabic flow.",
|
| 40 |
+
"",
|
| 41 |
+
"**5. MEASURABILITY:**",
|
| 42 |
+
" - Every outcome must be observable and measurable.",
|
| 43 |
+
" - The outcome should clearly indicate what success looks like.",
|
| 44 |
+
" - Avoid vague or abstract outcomes that cannot be assessed.",
|
| 45 |
+
"",
|
| 46 |
+
"**6. DNA METHODOLOGY INTEGRATION:**",
|
| 47 |
+
"Apply DNA principles to ensure comprehensive coverage:",
|
| 48 |
+
" - **Declarative (Conceptual)**: Theories, principles, abstract concepts, definitions",
|
| 49 |
+
" Examples: فهم المفاهيم، إدراك المبادئ، معرفة النظريات",
|
| 50 |
+
" - **Procedural**: Step-by-step methods, processes, how-to knowledge",
|
| 51 |
+
" Examples: تطبيق الخطوات، تنفيذ الإجراءات، ممارسة الأساليب",
|
| 52 |
+
" - **Structural**: Frameworks, models, system-level understanding, relationships",
|
| 53 |
+
" Examples: تحليل النماذج، فحص الأطر، استكشاف العلاقات",
|
| 54 |
+
" - **Personal/Metacognitive**: Self-reflection, personal development, awareness",
|
| 55 |
+
" Examples: تقييم الذات، تطوير المهارات الشخصية، إدراك القدرات",
|
| 56 |
+
" - **Realistic/Contextual**: Real-world application, case studies, practical scenarios",
|
| 57 |
+
" Examples: تطبيق في سياقات واقعية، حل مشكلات حقيقية، توظيف في الميدان",
|
| 58 |
+
"",
|
| 59 |
+
"Ensure outcomes collectively cover multiple DNA dimensions for holistic learning.",
|
| 60 |
+
]
|
| 61 |
+
),
|
| 62 |
+
backstory="\n".join(
|
| 63 |
+
[
|
| 64 |
+
"You are an elite instructional designer specializing in outcomes-based education and the DNA knowledge framework.",
|
| 65 |
+
"You have deep expertise in:",
|
| 66 |
+
" - Arabic linguistic structures, particularly verbal nouns (المصادر)",
|
| 67 |
+
" - Bloom's Taxonomy and its precise application to learning outcomes",
|
| 68 |
+
" - DNA methodology for comprehensive knowledge representation",
|
| 69 |
+
" - Measurable outcome design that can be clearly assessed",
|
| 70 |
+
"",
|
| 71 |
+
"You analyze learning objectives carefully to extract the core learning achievements,",
|
| 72 |
+
"then synthesize them into well-crafted outcomes that are:",
|
| 73 |
+
" • Linguistically precise and natural in Arabic",
|
| 74 |
+
" • Aligned with the appropriate Bloom's cognitive level",
|
| 75 |
+
" �� Diverse in vocabulary to avoid monotony",
|
| 76 |
+
" • Measurable and realistic for the {audience}",
|
| 77 |
+
" • Comprehensive in covering declarative, procedural, structural, personal, and realistic dimensions",
|
| 78 |
+
"",
|
| 79 |
+
"You consider the ({topic}, {domain}, {content_type}, {audience}, {material_type}) context",
|
| 80 |
+
"to ensure outcomes are appropriate, achievable, and relevant.",
|
| 81 |
+
"",
|
| 82 |
+
"You maintain a mental tracker of all verbal nouns (مصادر) used to maximize diversity across outcomes.",
|
| 83 |
+
]
|
| 84 |
+
),
|
| 85 |
+
llm=llm_g,
|
| 86 |
+
verbose=True,
|
| 87 |
+
max_iter=100,
|
| 88 |
+
)
|
| 89 |
+
|
| 90 |
+
outcomes_task = Task(
|
| 91 |
+
description="\n".join(
|
| 92 |
+
[
|
| 93 |
+
"You are given a set of learning objectives in: {objectives}.",
|
| 94 |
+
"",
|
| 95 |
+
"Your task is to analyze these objectives and generate high-quality Arabic learning outcomes",
|
| 96 |
+
"that are measurable, aligned with Bloom's taxonomy, and designed using DNA methodology.",
|
| 97 |
+
"",
|
| 98 |
+
"### STEP-BY-STEP PROCESS:",
|
| 99 |
+
"",
|
| 100 |
+
"**STEP 1: ANALYZE THE OBJECTIVES**",
|
| 101 |
+
" - Read all objectives carefully to understand the complete learning journey.",
|
| 102 |
+
" - Identify the main knowledge domains, skills, and behaviors covered.",
|
| 103 |
+
" - Group objectives by Bloom's taxonomy levels.",
|
| 104 |
+
" - Note the DNA dimensions present (declarative, procedural, structural, personal, realistic).",
|
| 105 |
+
"",
|
| 106 |
+
"**STEP 2: DETERMINE OUTCOME STRUCTURE**",
|
| 107 |
+
" - Decide how many outcomes are needed (typically one per Bloom's level that has objectives).",
|
| 108 |
+
" - If multiple objectives exist at one Bloom's level, synthesize them into ONE comprehensive outcome.",
|
| 109 |
+
" - Ensure outcomes progress logically from Remember → Create.",
|
| 110 |
+
"",
|
| 111 |
+
"**STEP 3: SELECT APPROPRIATE VERBAL NOUNS (مصادر)**",
|
| 112 |
+
" - For each Bloom's level, review the available verbal nouns (provided below).",
|
| 113 |
+
" - Select a مصدر that:",
|
| 114 |
+
" • Accurately represents the cognitive level",
|
| 115 |
+
" • Has NOT been used in previous outcomes (maximize diversity)",
|
| 116 |
+
" • Is appropriate for the {audience}",
|
| 117 |
+
" • Matches the DNA dimension of the content",
|
| 118 |
+
" - Maintain a mental list of used مصادر to avoid repetition.",
|
| 119 |
+
"",
|
| 120 |
+
"**STEP 4: CRAFT EACH OUTCOME**",
|
| 121 |
+
" - Structure: [مصدر] + [core content/concept] + [context if needed]",
|
| 122 |
+
" - Keep it concise: 6-10 words maximum.",
|
| 123 |
+
" - Ensure it's measurable and observable.",
|
| 124 |
+
" - Use natural, flowing Arabic.",
|
| 125 |
+
" - Verify it synthesizes all related objectives at that level.",
|
| 126 |
+
"",
|
| 127 |
+
"**STEP 5: QUALITY VERIFICATION**",
|
| 128 |
+
" - Check each outcome against the 12 quality criteria (see below).",
|
| 129 |
+
" - Ensure verb diversity across all outcomes.",
|
| 130 |
+
" - Verify Bloom's sequence is maintained.",
|
| 131 |
+
" - Confirm DNA dimensions are covered.",
|
| 132 |
+
"",
|
| 133 |
+
"### COMPREHENSIVE VERBAL NOUNS (مصادر) BY BLOOM'S LEVEL:",
|
| 134 |
+
"",
|
| 135 |
+
"Use these extensive lists to maximize diversity:",
|
| 136 |
+
"",
|
| 137 |
+
"**Remember (التذكر) - Declarative Focus:**",
|
| 138 |
+
"تعريف، تحديد، تسمية، ذكر، كتابة، عرض، سرد، تعداد، حفظ، استرجاع، تكرار، معرفة، إدراج، إشارة، اختيار",
|
| 139 |
+
"",
|
| 140 |
+
"**Understand (الفهم) - Conceptual Focus:**",
|
| 141 |
+
"فهم، إدراك، توضيح، شرح، تفسير، تلخيص، وصف، مناقشة، استنتاج، تمثيل، ترجمة، تعبير، صياغة، إعادة صياغة، استيعاب",
|
| 142 |
+
"",
|
| 143 |
+
"**Apply (التطبيق) - Procedural Focus:**",
|
| 144 |
+
"تطبيق، استخدام، توظيف، ممارسة، تنفيذ، إجراء، حل، تشغيل، إنجاز، ربط، تجريب، اختبار، عرض، إعداد، إظهار",
|
| 145 |
+
"",
|
| 146 |
+
"**Analyze (التحليل) - Structural Focus:**",
|
| 147 |
+
"تحليل، فحص، تمييز، مقارنة، تصنيف، فصل، تفريق، استقصاء، استكشاف، اكتشاف، ربط، تنظيم، تجزئة، دراسة، بحث",
|
| 148 |
+
"",
|
| 149 |
+
"**Evaluate (التقييم) - Metacognitive/Critical Focus:**",
|
| 150 |
+
"تقييم، حكم، نقد، تبرير، دعم، توصية، اختيار، مراجعة، دفاع، تقدير، فحص نقدي، موازنة، مفاضلة، ترجيح، إصدار حكم",
|
| 151 |
+
"",
|
| 152 |
+
"**Create (الإبداع) - Generative/Innovative Focus:**",
|
| 153 |
+
"تصميم، إنشاء، ابتكار، تطوير، بناء، تأليف، تخطيط، تركيب، صياغة، اقتراح، إعداد، إنت��ج، تكوين، توليد، ابتداع",
|
| 154 |
+
"",
|
| 155 |
+
"### DNA METHODOLOGY INTEGRATION GUIDE:",
|
| 156 |
+
"",
|
| 157 |
+
"Ensure your outcomes collectively address multiple DNA dimensions:",
|
| 158 |
+
"",
|
| 159 |
+
"**Declarative/Conceptual Outcomes (مصادر مناسبة):**",
|
| 160 |
+
" - Focus on: concepts, definitions, theories, principles",
|
| 161 |
+
" - Verbs: تعريف، فهم، إدراك، معرفة، استيعاب",
|
| 162 |
+
" - Example: فهم المبادئ الأساسية للتعلم الإلكتروني",
|
| 163 |
+
"",
|
| 164 |
+
"**Procedural Outcomes (مصادر مناسبة):**",
|
| 165 |
+
" - Focus on: methods, steps, processes, how-to",
|
| 166 |
+
" - Verbs: تطبيق، تنفيذ، ممارسة، استخدام، إجراء",
|
| 167 |
+
" - Example: تطبيق خطوات تصميم محتوى تعليمي رقمي",
|
| 168 |
+
"",
|
| 169 |
+
"**Structural Outcomes (مصادر مناسبة):**",
|
| 170 |
+
" - Focus on: frameworks, models, relationships, systems",
|
| 171 |
+
" - Verbs: تحليل، فحص، استكشاف، ربط، تنظيم",
|
| 172 |
+
" - Example: تحليل العلاقة بين استراتيجيات التعليم وأنواع المحتوى",
|
| 173 |
+
"",
|
| 174 |
+
"**Personal/Metacognitive Outcomes (مصادر مناسبة):**",
|
| 175 |
+
" - Focus on: self-awareness, reflection, personal development",
|
| 176 |
+
" - Verbs: تقييم الذات، تطوير، إدراك، تحسين، تنمية",
|
| 177 |
+
" - Example: تقييم المهارات الشخصية في إدارة الوقت",
|
| 178 |
+
"",
|
| 179 |
+
"**Realistic/Contextual Outcomes (مصادر مناسبة):**",
|
| 180 |
+
" - Focus on: real-world application, case studies, practical use",
|
| 181 |
+
" - Verbs: توظيف في سياق واقعي، حل مشكلات، تطبيق ميداني",
|
| 182 |
+
" - Example: حل مشكلات تعليمية واقعية باستخدام التقنيات الحديثة",
|
| 183 |
+
"",
|
| 184 |
+
"### QUALITY CRITERIA CHECKLIST (12+2 Criteria):",
|
| 185 |
+
"",
|
| 186 |
+
"Before finalizing each outcome, verify:",
|
| 187 |
+
"",
|
| 188 |
+
"✓ 1. **Correct linguistic form**: Uses مصدر (infinitive noun), not verb",
|
| 189 |
+
"✓ 2. **Bloom's alignment**: Accurately reflects the assigned cognitive level",
|
| 190 |
+
"✓ 3. **Clear and unambiguous**: No vague or confusing language",
|
| 191 |
+
"✓ 4. **Appropriate vocabulary**: Suitable for {audience} level",
|
| 192 |
+
"✓ 5. **Single focus**: Expresses ONE outcome, not multiple combined",
|
| 193 |
+
"✓ 6. **Measurable**: Can be observed or assessed",
|
| 194 |
+
"✓ 7. **Realistic**: Achievable within program scope and time",
|
| 195 |
+
"✓ 8. **Aligned with objectives**: Synthesizes related learning objectives",
|
| 196 |
+
"✓ 9. **Content-relevant**: Directly relates to {topic} and {domain}",
|
| 197 |
+
"✓ 10. **Logical sequence**: Follows Bloom's order (low to high)",
|
| 198 |
+
"✓ 11. **Audience-appropriate**: Matches {audience} capabilities",
|
| 199 |
+
"✓ 12. **Comprehensive**: Covers knowledge, skills, attitudes collectively",
|
| 200 |
+
"✓ 13. **DIVERSE VOCABULARY**: Avoids repetition of مصادر",
|
| 201 |
+
"✓ 14. **DNA-aligned**: Reflects appropriate DNA dimension(s)",
|
| 202 |
+
"",
|
| 203 |
+
"### EXAMPLES OF HIGH-QUALITY OUTCOMES:",
|
| 204 |
+
"",
|
| 205 |
+
"**✅ EXCELLENT EXAMPLES:**",
|
| 206 |
+
"",
|
| 207 |
+
"**Remember Level:**",
|
| 208 |
+
"تعريف المصطلحات الأساسية في التعلم الإلكتروني بدقة.",
|
| 209 |
+
"(Declarative, clear, measurable, concise, uses تعريف)",
|
| 210 |
+
"",
|
| 211 |
+
"**Understand Level:**",
|
| 212 |
+
"إدراك العلاقة بين أنماط التعلم واستراتيجيات التدريس.",
|
| 213 |
+
"(Structural understanding, uses إدراك, different from تعريف)",
|
| 214 |
+
"",
|
| 215 |
+
"**Apply Level:**",
|
| 216 |
+
"توظيف أدوات التقييم الرقمية في بيئة تعليمية فعلية.",
|
| 217 |
+
"(Procedural + Realistic, uses توظيف, context-specific)",
|
| 218 |
+
"",
|
| 219 |
+
"**Analyze Level:**",
|
| 220 |
+
"تمييز نقاط القوة والضعف في نماذج التصميم التعليمي.",
|
| 221 |
+
"(Structural analysis, uses تمييز, critical thinking)",
|
| 222 |
+
"",
|
| 223 |
+
"**Evaluate Level:**",
|
| 224 |
+
"مقارنة فعالية استراتيجيات التعليم المختلفة وفق معايير محددة.",
|
| 225 |
+
"(Evaluative, uses مقارنة, criteria-based)",
|
| 226 |
+
"",
|
| 227 |
+
"**Create Level:**",
|
| 228 |
+
"ابتكار حلول إبداعية لتحديات التعليم عن بُعد.",
|
| 229 |
+
"(Generative, uses ابتكار, innovative focus)",
|
| 230 |
+
"",
|
| 231 |
+
"**❌ POOR EXAMPLES (Avoid These):**",
|
| 232 |
+
"",
|
| 233 |
+
"❌ 'أن يفهم ا��متدرب مفهوم التعليم الإلكتروني'",
|
| 234 |
+
"(Wrong: uses verb form, not مصدر; includes 'أن يفهم المتدرب')",
|
| 235 |
+
"",
|
| 236 |
+
"❌ 'فهم التعليم الإلكتروني'",
|
| 237 |
+
"(Too vague, not measurable, lacks specificity)",
|
| 238 |
+
"",
|
| 239 |
+
"❌ 'فهم وتطبيق مبادئ التعليم الإلكتروني'",
|
| 240 |
+
"(Double outcome, combines two Bloom's levels)",
|
| 241 |
+
"",
|
| 242 |
+
"❌ 'تعريف أنواع التعليم الإلكتروني وتصنيف منصات التعلم'",
|
| 243 |
+
"(Multiple outcomes in one, too long)",
|
| 244 |
+
"",
|
| 245 |
+
"❌ Using 'تعريف' for all Remember-level outcomes",
|
| 246 |
+
"(Lacks diversity, repetitive)",
|
| 247 |
+
"",
|
| 248 |
+
"### CRITICAL VERB DIVERSITY REQUIREMENT:",
|
| 249 |
+
"",
|
| 250 |
+
"**🚨 PRIMARY INSTRUCTION: Maximize مصدر diversity across all outcomes**",
|
| 251 |
+
"",
|
| 252 |
+
"**Diversity Rules:**",
|
| 253 |
+
"1. Before selecting a مصدر, check: Have I used this before?",
|
| 254 |
+
"2. If yes, select an alternative unless no suitable synonym exists.",
|
| 255 |
+
"3. Use the full range of available مصادر at each Bloom's level.",
|
| 256 |
+
"4. Aim for 80-100% unique مصادر across all outcomes.",
|
| 257 |
+
"5. Track usage mentally as you craft each outcome.",
|
| 258 |
+
"",
|
| 259 |
+
"**Diversity Strategies:**",
|
| 260 |
+
"- Rotate through synonyms systematically",
|
| 261 |
+
"- Match مصدر to specific DNA dimension when possible",
|
| 262 |
+
"- Use more specific مصادر rather than generic ones",
|
| 263 |
+
"- Consider the nuance each مصدر brings to meaning",
|
| 264 |
+
"",
|
| 265 |
+
"### SELF-REFLECTION AFTER GENERATION:",
|
| 266 |
+
"",
|
| 267 |
+
"After creating all outcomes, review and ask:",
|
| 268 |
+
"- Do outcomes progress clearly from Remember to Create?",
|
| 269 |
+
"- Is there good diversity in مصادر (minimal repetition)?",
|
| 270 |
+
"- Do outcomes collectively cover DNA dimensions?",
|
| 271 |
+
"- Are all outcomes measurable and realistic for {audience}?",
|
| 272 |
+
"- Does each outcome synthesize its related objectives effectively?",
|
| 273 |
+
"- Is the Arabic natural, clear, and linguistically correct?",
|
| 274 |
+
"- Would an evaluator be able to assess achievement of each outcome?",
|
| 275 |
+
"",
|
| 276 |
+
"### FINAL QUALITY ASSURANCE:",
|
| 277 |
+
"",
|
| 278 |
+
"Before submitting, verify:",
|
| 279 |
+
"✓ All outcomes use مصدر form (not verbs)",
|
| 280 |
+
"✓ Bloom's sequence is maintained throughout",
|
| 281 |
+
"✓ Each outcome is 10-15 words maximum",
|
| 282 |
+
"✓ Vocabulary is appropriate for {audience}",
|
| 283 |
+
"✓ DNA methodology is applied",
|
| 284 |
+
"✓ Outcomes are measurable and realistic",
|
| 285 |
+
"✓ Minimal repetition of مصادر (high diversity)",
|
| 286 |
+
"✓ Each outcome synthesizes multiple related objectives where applicable",
|
| 287 |
+
"",
|
| 288 |
+
"### OUTPUT\n"
|
| 289 |
+
"Return the LearningObjectivesOutput structure in valid JSON format.\n\n",
|
| 290 |
+
]
|
| 291 |
+
),
|
| 292 |
+
expected_output="""JSON object with this structure:
|
| 293 |
+
{
|
| 294 |
+
"objectives": [
|
| 295 |
+
{
|
| 296 |
+
"unit": "Unit title",
|
| 297 |
+
"unit_description": "Brief summary of the unit scope",
|
| 298 |
+
"unit_outcome": "One measurable Arabic objective derived from the unit description and its subtopics and their purposes",
|
| 299 |
+
}
|
| 300 |
+
],
|
| 301 |
+
}""",
|
| 302 |
+
output_json=LearningOutcomesOutput,
|
| 303 |
+
agent=outcomes_generator,
|
| 304 |
+
human_input=False,
|
| 305 |
+
)
|
agents/analysis_phase/outliner.py
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
#from schemas import CurriculumOutline
|
| 6 |
+
|
| 7 |
+
# ========= 4. Outline Agent =========
|
| 8 |
+
outline_agent = Agent(
|
| 9 |
+
role="Scientific Outline Generator",
|
| 10 |
+
goal="\n".join(
|
| 11 |
+
[
|
| 12 |
+
"Generate a complete and scientifically accurate training curriculum for the topic: {topic}.",
|
| 13 |
+
"The curriculum must be structured, logically sequenced, and pedagogically useful.",
|
| 14 |
+
"Avoid vague, redundant, or repetitive points—each topic must be unique and non-overlapping.",
|
| 15 |
+
"Ensure strong logical flow: units must progress according to Bloom’s taxonomy principles—starting from simple recall/understanding, moving to deeper analysis, application, evaluation, and finally creation/innovation.",
|
| 16 |
+
"Important: Do NOT explicitly use Bloom verbs (e.g., analyze, evaluate, create). Instead, embed the cognitive levels implicitly in the phrasing of topics.",
|
| 17 |
+
"When generating topics, always use terms and concepts that are common, searchable, and can be easily found in Arabic or international online sources (articles, courses, books).",
|
| 18 |
+
"Avoid overly creative or abstract titles that are difficult to map to real content.",
|
| 19 |
+
"Follow this strict format:",
|
| 20 |
+
"- Output must be in JSON.",
|
| 21 |
+
"- Curriculum must include exactly 4 units.",
|
| 22 |
+
"- Each unit must have exactly 5 sub-topics.",
|
| 23 |
+
"- Units must be output with keys: unit_title, topics.",
|
| 24 |
+
"Each unit must reflect and cover one of the core concepts of the topic, so that together they encompass all aspects of the subject.",
|
| 25 |
+
"The 4 units must be interconnected, sequentially linked, and collectively ensure full coverage of all concepts of the topic, leaving no gaps.",
|
| 26 |
+
"Ensure all text is written in **Arabic language**.",
|
| 27 |
+
"Units should be connected and form a comprehensive training program that gradually increases in cognitive depth according to Bloom’s taxonomy.",
|
| 28 |
+
"Always adapt to metadata: domain ({domain}), content_type ({content_type}), audience ({audience}), material_type ({material_type}).",
|
| 29 |
+
"Apply DNA methodology explicitly in topic design:",
|
| 30 |
+
"- material_type:",
|
| 31 |
+
"-- Conceptual: theories, principles, abstract knowledge.",
|
| 32 |
+
"-- Procedural: step-by-step instructions or methods.",
|
| 33 |
+
"-- Structural: frameworks, models, or system views.",
|
| 34 |
+
"-- Personal: learner reflection, skills, or self-development aspects.",
|
| 35 |
+
"-- Realistic: real-world examples, applications, or case studies.",
|
| 36 |
+
"- content_type:",
|
| 37 |
+
"-- Educational → for structured learning (e.g., lessons, modules)",
|
| 38 |
+
"-- Awareness → for informative/raising awareness purposes (e.g., campaigns, workshops)",
|
| 39 |
+
"-- Training → for skill development with step-by-step practice (e.g., hands-on, exercises)",
|
| 40 |
+
"Important: The curriculum title must be identical to the input topic, and unit titles must reflect or embed the meaning of this title.",
|
| 41 |
+
]
|
| 42 |
+
),
|
| 43 |
+
backstory="\n".join(
|
| 44 |
+
[
|
| 45 |
+
"This agent acts as both a scientific researcher and curriculum designer.",
|
| 46 |
+
"It generates structured outlines in the form of 4 units × 5 topics, aligned with DNA methodology.",
|
| 47 |
+
"It ensures progression follows Bloom’s taxonomy: Unit 1 covers basic recall/understanding, Unit 2 focuses on application of methods/tools, Unit 3 emphasizes analysis and evaluation in real contexts, and Unit 4 explores integration, innovation, or advanced synthesis.",
|
| 48 |
+
"The topics must always be realistic, practical, and searchable in Arabic or global sources to ensure that real content can be gathered later.",
|
| 49 |
+
"The final output must always be in Arabic.",
|
| 50 |
+
"The curriculum should progress from simple to complex, reflecting Bloom’s cognitive hierarchy, but without explicitly naming Bloom’s verbs in the text.",
|
| 51 |
+
]
|
| 52 |
+
),
|
| 53 |
+
llm=llm,
|
| 54 |
+
verbose=True,
|
| 55 |
+
reasoning=True,
|
| 56 |
+
max_reasoning_attempts=3,
|
| 57 |
+
max_iter=100,
|
| 58 |
+
)
|
| 59 |
+
|
| 60 |
+
|
| 61 |
+
# ========= 5. Task =========
|
| 62 |
+
outline_task = Task(
|
| 63 |
+
description="\n".join(
|
| 64 |
+
[
|
| 65 |
+
"Generate a structured outline for the topic: {topic}.",
|
| 66 |
+
"The output must strictly follow this format:",
|
| 67 |
+
"- JSON object with keys: 'title' and 'units'.",
|
| 68 |
+
"- 'title': must be exactly the same as the input topic (in Arabic).",
|
| 69 |
+
"- 'units': exactly 4 items.",
|
| 70 |
+
"- Each unit must have:",
|
| 71 |
+
" - unit_title (string, Arabic, must reflect or embed the curriculum title meaning)",
|
| 72 |
+
" - topics (list of exactly 5 short topics, in Arabic).",
|
| 73 |
+
"Ensure the units flow logically, progressively, and cover the subject fully.",
|
| 74 |
+
"The units must align with Bloom’s taxonomy progression: Unit 1 = basic knowledge & understanding, Unit 2 = tools & applications, Unit 3 = analysis & evaluation, Unit 4 = synthesis & advanced innovation.",
|
| 75 |
+
"Do NOT explicitly use Bloom’s action verbs; express the cognitive levels implicitly in the phrasing of topics.",
|
| 76 |
+
"Each topic must embed one aspect of DNA methodology (Conceptual, Procedural, Structural, Personal, Realistic) and (content_type: Training, Awareness, Educational).",
|
| 77 |
+
"All topics must be formulated using widely recognized and searchable concepts (to allow collecting real content from online sources).",
|
| 78 |
+
"Avoid repetition—no two topics should overlap in meaning.",
|
| 79 |
+
"Do not add extra fields outside the schema.",
|
| 80 |
+
"The entire output must be in Arabic.",
|
| 81 |
+
]
|
| 82 |
+
),
|
| 83 |
+
expected_output=(
|
| 84 |
+
"A valid JSON object with this structure:\n"
|
| 85 |
+
"{\n"
|
| 86 |
+
' "title": "string (Arabic curriculum title)",\n'
|
| 87 |
+
' "units": [\n'
|
| 88 |
+
" {\n"
|
| 89 |
+
' "unit_title": "string (Arabic, must reflect the title)",\n'
|
| 90 |
+
' "topics": ["topic1", "topic2", "topic3", "topic4", "topic5"]\n'
|
| 91 |
+
" }, ... (4 units total)\n"
|
| 92 |
+
" ]\n"
|
| 93 |
+
"}"
|
| 94 |
+
),
|
| 95 |
+
#output_json=CurriculumOutline,
|
| 96 |
+
agent=outline_agent,
|
| 97 |
+
)
|
agents/design_phase/__init__.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .keywoard_researcher import keyword_researcher_agent, keyword_researcher_task
|
| 2 |
+
from .source_finder import search_engine_agent, search_engine_task
|
| 3 |
+
from .extractor import scraping_agent, scraping_task
|
agents/design_phase/extractor.py
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
from modules import llm
|
| 4 |
+
from tools import web_scraping_tool
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
scraping_agent = Agent(
|
| 8 |
+
role="Web Scraping & Content Extraction Agent",
|
| 9 |
+
goal="\n".join(
|
| 10 |
+
[
|
| 11 |
+
"To extract structured and valuable content details from multiple trusted web pages.",
|
| 12 |
+
"The agent should gather, analyze, and filter relevant information about {topic} from reliable Arabic and English sources.",
|
| 13 |
+
"It must focus on scholarly materials, books, research papers, and high-quality educational content that can inspire ideas for building the course and trusted websites.",
|
| 14 |
+
"Focus on extracting the COMPLETE content, capture every paragraph, section, example, and detail.",
|
| 15 |
+
"The agent should also identify and rank the usefulness of each source depending on its credibility and relevance to the course objectives.",
|
| 16 |
+
"The goal is not only to scrape raw text but also to provide clear notes and recommendations about the extracted content to help instructional designers, course creators, and content writers.",
|
| 17 |
+
]
|
| 18 |
+
),
|
| 19 |
+
backstory="\n".join(
|
| 20 |
+
[
|
| 21 |
+
"This agent acts like a scientific researcher and content curator for e-learning projects.",
|
| 22 |
+
"It specializes in exploring a wide range of Arabic and English references: books, articles, and academic research papers.",
|
| 23 |
+
"By analyzing the scraped content, it supports course designers in identifying diverse and meaningful ideas aligned with the main course theme and learning objectives.",
|
| 24 |
+
"It ensures that every extracted resource is reliable, and practical for developing educational materials, such as cultural intelligence courses.",
|
| 25 |
+
]
|
| 26 |
+
),
|
| 27 |
+
llm=llm,
|
| 28 |
+
tools=[web_scraping_tool],
|
| 29 |
+
verbose=True,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
scraping_task = Task(
|
| 33 |
+
description="\n".join(
|
| 34 |
+
[
|
| 35 |
+
"The task is to extract and organize content details from the most relevant and trusted web pages.",
|
| 36 |
+
"You should gather insights in both Arabic and English.",
|
| 37 |
+
"Here are the search results you have to extract content from:",
|
| 38 |
+
"{urls}",
|
| 39 |
+
"From each page, extract the title, main content, and any associated media (images, videos, audios, pdfs).",
|
| 40 |
+
"For every resource, provide an agent recommendation rank (0–5) along with notes explaining its relevance, credibility, and why it is or is not recommended.",
|
| 41 |
+
"For every resource select the heading and the subheading the content is belongs to from these outlines {outlines}",
|
| 42 |
+
]
|
| 43 |
+
),
|
| 44 |
+
expected_output=(
|
| 45 |
+
"Return ONLY a valid Python dictionary.\n"
|
| 46 |
+
"- Do not include explanations, markdown, or code fences.\n"
|
| 47 |
+
"- The dictionary must be UTF-8 safe and directly usable in Python with ast.literal_eval.\n"
|
| 48 |
+
"- Keys must be wrapped in double quotes.\n\n"
|
| 49 |
+
"Format example:\n"
|
| 50 |
+
"{\n"
|
| 51 |
+
' "parts": [\n'
|
| 52 |
+
" {\n"
|
| 53 |
+
' "page_url": "https://example.com/page1",\n'
|
| 54 |
+
' "title": "Understanding Time Management for Kids",\n'
|
| 55 |
+
' "content": "Detailed explanation of how children can learn time management.",\n'
|
| 56 |
+
' "img_url": ["https://example.com/image1.jpg"],\n'
|
| 57 |
+
' "video_url": ["https://example.com/video1.mp4"],\n'
|
| 58 |
+
' "audio_url": ["https://example.com/audio1.mp3"],\n'
|
| 59 |
+
' "pdf_url": ["https://example.com/file1.pdf"],\n'
|
| 60 |
+
' "agent_recommendation_rank": 4.7,\n'
|
| 61 |
+
' "agent_recommendation_notes": "This content provides clear strategies and visuals that are highly useful.",\n'
|
| 62 |
+
' "header": "Time Management",\n'
|
| 63 |
+
' "sub_header": "For Children"\n'
|
| 64 |
+
" }\n"
|
| 65 |
+
" ]\n"
|
| 66 |
+
"}\n\n"
|
| 67 |
+
"Make the output compatible with Python's ast library because I use:\n"
|
| 68 |
+
" r1 = result.dict()['raw']\n"
|
| 69 |
+
" f_result = ast.literal_eval(r1)\n"
|
| 70 |
+
"Make sure there are no unterminated string literals and no invalid syntax.\n"
|
| 71 |
+
"The output MUST match exactly the schema and format example above.\n"
|
| 72 |
+
"Do not include Thoughts, explanations, or anything else besides the dictionary."
|
| 73 |
+
),
|
| 74 |
+
agent=scraping_agent,
|
| 75 |
+
)
|
agents/design_phase/keywoard_researcher.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
from modules import llm
|
| 4 |
+
from schemas import SuggestedSearchQueries
|
| 5 |
+
|
| 6 |
+
no_keywords = 25
|
| 7 |
+
|
| 8 |
+
keyword_researcher_agent = Agent(
|
| 9 |
+
role="search queries recommendation agent",
|
| 10 |
+
goal="\n".join(
|
| 11 |
+
[
|
| 12 |
+
"To generate a set of structured and comprehensive search queries based on the topic {topic} "
|
| 13 |
+
"and the outline headings (main and sub-headings) provided from the outline task.",
|
| 14 |
+
"Queries should be varied, precise,relevant , and research-oriented.",
|
| 15 |
+
"For each heading and sub-heading, create multiple queries to help collect rich, relevant content from the web.",
|
| 16 |
+
"Queries must ensure coverage of the most important aspects of the topic, avoiding irrelevant or empty dimensions.",
|
| 17 |
+
"Avoid vague or overly generic queries.",
|
| 18 |
+
"Ensure queries reflect the scope of the outline, avoiding irrelevant or generic phrasing.",
|
| 19 |
+
"Strictly avoid generating queries related to religions, politics, or any biased/off-topic perspectives.",
|
| 20 |
+
]
|
| 21 |
+
),
|
| 22 |
+
backstory=(
|
| 23 |
+
"This agent acts as a scientific researcher and content strategist and instructional designer. "
|
| 24 |
+
"It takes the topic and its structured outline (headings + sub-headings) and expands them into precise, "
|
| 25 |
+
"targeted search queries. These queries are crafted to maximize coverage of the outline sections "
|
| 26 |
+
"and ensure the user can gather high-quality resources for each part."
|
| 27 |
+
),
|
| 28 |
+
llm=llm,
|
| 29 |
+
verbose=True,
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
keyword_researcher_task = Task(
|
| 33 |
+
name="search queries recommendation task",
|
| 34 |
+
description="\n".join(
|
| 35 |
+
[
|
| 36 |
+
"Using the outline headings and sub-headings {outlines} for the topic {topic},",
|
| 37 |
+
"generate up to {no_keywords_Researcher_For_Each_Heading} short and precise search queries for each heading.",
|
| 38 |
+
"Each query must be short, complete, and precise, directly reflecting the heading or sub-heading it belongs to.",
|
| 39 |
+
"The aim is to cover the full breadth of the outline so that no important section is left without queries.",
|
| 40 |
+
"Queries should be research-oriented, avoiding vague or overly generic terms.",
|
| 41 |
+
"Important: All queries for the same heading must be unique and non-repetitive.",
|
| 42 |
+
"Do NOT generate queries that only differ by synonyms like 'concept' vs. 'definition'.",
|
| 43 |
+
"Instead, vary the focus (e.g., concept, benefits, methods, challenges, applications).",
|
| 44 |
+
"Strictly exclude any queries related to religion, politics, or biased/off-topic perspectives.",
|
| 45 |
+
]
|
| 46 |
+
),
|
| 47 |
+
expected_output="A JSON object containing a list of suggested search queries.",
|
| 48 |
+
output_json=SuggestedSearchQueries,
|
| 49 |
+
agent=keyword_researcher_agent,
|
| 50 |
+
)
|
agents/design_phase/source_finder.py
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
from modules import llm
|
| 4 |
+
from tools import search_engine_tool
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
search_engine_agent = Agent(
|
| 8 |
+
role="search engine agent",
|
| 9 |
+
goal="\n".join(
|
| 10 |
+
[
|
| 11 |
+
"Search for diverse, high-quality, and reliable information related to {topic} using the suggested search queries.",
|
| 12 |
+
"Prioritize **scholarly and educational resources**: academic journals, books, research articles, and trusted institutional websites.",
|
| 13 |
+
"Include Arabic sources when contextually valuable, but prioritize English academic sources for broader coverage.",
|
| 14 |
+
"Ensure all results are concise, relevant, and aligned with the outline headings to directly support course design and educational content.",
|
| 15 |
+
"For each query, return at most 5 results with structured metadata (title, url, content summary, score, search_query).",
|
| 16 |
+
]
|
| 17 |
+
),
|
| 18 |
+
backstory=(
|
| 19 |
+
"This agent acts like a scientific researcher and educational content curator."
|
| 20 |
+
"It executes the generated queries and gathers high-value, trustworthy information."
|
| 21 |
+
"The agent is trained to filter out irrelevant, commercial, or low-quality content, ensuring that "
|
| 22 |
+
"only academic and pedagogically useful resources are kept."
|
| 23 |
+
"for building interactive e-learning content are retrieved."
|
| 24 |
+
"It balances global knowledge with local cultural enrichment by including both English and Arabic sources."
|
| 25 |
+
),
|
| 26 |
+
llm=llm,
|
| 27 |
+
verbose=True,
|
| 28 |
+
tools=[search_engine_tool],
|
| 29 |
+
)
|
| 30 |
+
|
| 31 |
+
search_engine_task = Task(
|
| 32 |
+
description="\n".join(
|
| 33 |
+
[
|
| 34 |
+
"The task is to search the web for relevant and reliable resources about {topic} using the suggested search queries.",
|
| 35 |
+
"You must collect results from multiple queries to ensure diversity of perspectives and sources.",
|
| 36 |
+
"Here are the queries you can use to search:",
|
| 37 |
+
"{queries}",
|
| 38 |
+
"For each query, retrieve at least 1 link and a maximum of {no_links} links only.",
|
| 39 |
+
"Prioritize scholarly, academic, and educational resources (journals, books, institutional websites).",
|
| 40 |
+
"Filter out irrelevant, suspicious, or low-quality results (e.g., personal blogs, spam, commercial ads).",
|
| 41 |
+
"Apply score filtering: ignore results with a confidence score lower than {score_th}.",
|
| 42 |
+
"The final results will serve as the knowledge base for building trusted, high-quality content, ",
|
| 43 |
+
"with a focus on supporting the course’s educational objectives and cultural enrichment goals.",
|
| 44 |
+
"with a focus on supporting the course’s educational objectives and cultural enrichment goals.",
|
| 45 |
+
]
|
| 46 |
+
),
|
| 47 |
+
expected_output=(
|
| 48 |
+
"Return ONLY a valid Python dictionary.\n"
|
| 49 |
+
"- Do not include explanations, markdown, or code fences.\n"
|
| 50 |
+
"- The dictionary must be UTF-8 safe and directly usable in Python with ast.literal_eval.\n"
|
| 51 |
+
"- Keys must be wrapped in double quotes.\n\n"
|
| 52 |
+
"Format example:\n"
|
| 53 |
+
"{\n"
|
| 54 |
+
' "results": [\n'
|
| 55 |
+
" {\n"
|
| 56 |
+
' "url": "...",\n'
|
| 57 |
+
' "title": "...",\n'
|
| 58 |
+
' "content": "...",\n'
|
| 59 |
+
' "score": 0.85,\n'
|
| 60 |
+
' "search_query": "..."\n'
|
| 61 |
+
" }\n"
|
| 62 |
+
" ]\n"
|
| 63 |
+
"}"
|
| 64 |
+
"Make the out compatible with ast python library because i use r1 = result.dict()['raw'] f_result = ast.literal_eval(r1)"
|
| 65 |
+
"Make sure there is no unterminated string literal and no invalid syntax, errors will happen when parsing"
|
| 66 |
+
"Make sure that the output is only as the format example i give you before, dont include Thoughts or anything else"
|
| 67 |
+
),
|
| 68 |
+
agent=search_engine_agent,
|
| 69 |
+
)
|
agents/final_outliners/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .subtopics_generator import subtopics_generator_agent, subtopics_generation_task
|
| 2 |
+
from .validator import validator_agent, validation_task
|
| 3 |
+
# from .units_langchain import units_langchain_agent
|
| 4 |
+
from .units_langchain_1v import units_langchain1_agent
|
agents/final_outliners/subtopics_generator.py
ADDED
|
@@ -0,0 +1,129 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm_5m, llm_g
|
| 5 |
+
from schemas import FullCurriculumStructure
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
subtopics_generator_agent = Agent(
|
| 9 |
+
role="Arabic Educational Subtopic Generator (Subtopic Developer)",
|
| 10 |
+
goal=(
|
| 11 |
+
"Analyze the provided metadata ({topic}, {domain}, {audience}, {content_type}, {material_type}) "
|
| 12 |
+
"along with the CurriculumStructure (containing the main concept, General_objectives_of_the_plan, and list of units and their details). "
|
| 13 |
+
"For each unit — based on its title and details — generate list of coherent and progressive Arabic subtopics (axes). "
|
| 14 |
+
"These subtopics should represent a logical and educational flow from foundational understanding "
|
| 15 |
+
"to advanced application and creativity. "
|
| 16 |
+
"Each unit's subtopic should represent a specific stage of learning progression — starting from basic knowledge acquisition "
|
| 17 |
+
"and moving toward critical thinking and creative application. "
|
| 18 |
+
## ADD
|
| 19 |
+
"Example:"
|
| 20 |
+
"- Unit: التفكير التصميمي وحل المشكلات"
|
| 21 |
+
"- Given Subtopics:"
|
| 22 |
+
" • ماذا يعنى حل المشكلة؟"
|
| 23 |
+
" • 4 خطوات لحل المشكلة"
|
| 24 |
+
" • الفرق بين التفكير التحليلي والتصميمي في حل المشكلات"
|
| 25 |
+
" • نهج التفكير التصميمي لحل المشكلات"
|
| 26 |
+
" • نماذج تطبيقية ناجحة في حل المشكلات بالتفكير التصميمي"
|
| 27 |
+
"- Observation: The first two are introductory — essential for understanding the later applied parts."
|
| 28 |
+
## ADD
|
| 29 |
+
"Finally, ensure that all generated subtopics comply with the approved Arabic educational titling standards:\n"
|
| 30 |
+
"- Titles must be clear, direct, and precise, avoiding ambiguous or poetic phrasing.\n"
|
| 31 |
+
"- Avoid dual or compound titles; use a single, focused phrasing.\n"
|
| 32 |
+
"- Each title must reflect its actual educational content accurately.\n"
|
| 33 |
+
# "- Limited creativity is acceptable, but without exaggeration or metaphorical obscurity.\n"
|
| 34 |
+
"- Always adapt the title to the target audience’s cultural and cognitive level.\n"
|
| 35 |
+
"These standards ensure the linguistic clarity and educational value of all generated subtopics."
|
| 36 |
+
"Ensure that the subtopics are written as Arabic educational subheadings that align with the unit’s focus, "
|
| 37 |
+
"support conceptual growth, and maintain thematic coherence across the curriculum."
|
| 38 |
+
"Ensure all subtopics are contextually relevant to the unit's focus and contribute to the learner's comprehensive understanding."
|
| 39 |
+
),
|
| 40 |
+
backstory=(
|
| 41 |
+
"You are a senior Arabic curriculum designer and learning progression specialist. "
|
| 42 |
+
# "You possess deep expertise in Arabic pedagogy and cognitive development frameworks such as Bloom’s Taxonomy. "
|
| 43 |
+
"You skillfully expand each educational unit into coherent Arabic subtopics that reflect a logical learning progression — "
|
| 44 |
+
"starting from basic understanding and moving toward higher-order thinking and creative application. "
|
| 45 |
+
"Each subtopic builds upon the previous one to form a cohesive and culturally relevant learning journey. "
|
| 46 |
+
"Your designs prioritize conceptual clarity, educational depth, and alignment with Arabic academic standards."
|
| 47 |
+
"You also ensure that each generated subtopic is research-backed and can be supported by credible educational materials available online, enabling later integration with content retrieval systems."
|
| 48 |
+
## ADD
|
| 49 |
+
"You strictly follow the approved Arabic educational title formulation standards, ensuring clarity, precision, and appropriateness for the learner’s level."
|
| 50 |
+
),
|
| 51 |
+
output_format=(
|
| 52 |
+
"Return valid JSON strictly following this structure:\n"
|
| 53 |
+
"{\n"
|
| 54 |
+
" 'main_concept': '...',\n"
|
| 55 |
+
" 'units': [\n"
|
| 56 |
+
" {\n"
|
| 57 |
+
" 'unit_number': 1,\n"
|
| 58 |
+
" 'title': 'الوحدة الأولى: ...',\n"
|
| 59 |
+
" 'focus': '...',\n"
|
| 60 |
+
" 'axes': [\n"
|
| 61 |
+
" {'axis_number': 1, 'title': '...', 'purpose': '...'},\n"
|
| 62 |
+
" {'axis_number': 2, 'title': '...', 'purpose': '...'},\n"
|
| 63 |
+
" {'axis_number': 3, 'title': '...', 'purpose': '...'},\n"
|
| 64 |
+
" {'axis_number': 4, 'title': '...', 'purpose': '...'},\n"
|
| 65 |
+
" {'axis_number': 5, 'title': '...', 'purpose': '...'}\n"
|
| 66 |
+
" ]\n"
|
| 67 |
+
" }, ...\n"
|
| 68 |
+
" ]\n"
|
| 69 |
+
"}"
|
| 70 |
+
),
|
| 71 |
+
# llm=llm_open_c35,
|
| 72 |
+
llm=llm_g,
|
| 73 |
+
allow_delegation=False,
|
| 74 |
+
verbose=True,
|
| 75 |
+
reasoning=True,
|
| 76 |
+
max_iter=100,
|
| 77 |
+
)
|
| 78 |
+
|
| 79 |
+
# ============================================================
|
| 80 |
+
# 🧩 3. Axis Generation Task
|
| 81 |
+
# ============================================================
|
| 82 |
+
|
| 83 |
+
subtopics_generation_task = Task(
|
| 84 |
+
description=(
|
| 85 |
+
"## GOAL\n"
|
| 86 |
+
"Expand each educational unit from the given file into number of structured Arabic subtopics: {units}. "
|
| 87 |
+
# "Each axis should develop the learner’s understanding progressively — starting with remembering, "
|
| 88 |
+
# "then understanding, applying, analyzing, and finally creating.\n"
|
| 89 |
+
"Each subtopic should represent a cognitive development stage — moving from foundational understanding to applied mastery.\n\n"
|
| 90 |
+
"## CONTEXT\n"
|
| 91 |
+
# "You are provided with a units_agent_conceptual JSON (containing the main concept, related concepts, and list of units). "
|
| 92 |
+
"You are provided with a CurriculumStructure JSON (containing the main concept, General_objectives_of_the_plan, and list of units and their details). "
|
| 93 |
+
# "Each unit includes a title and conceptual focus.\n\n"
|
| 94 |
+
"## STEPS\n"
|
| 95 |
+
"1. Read the CurriculumStructure carefully to understand the hierarchy and conceptual logic.\n"
|
| 96 |
+
"2. For each unit:\n"
|
| 97 |
+
" - Identify its title and details.\n"
|
| 98 |
+
" - Generate list of progressive subtopics that unfold logically.\n"
|
| 99 |
+
" - Each subtopic must include:\n"
|
| 100 |
+
" • 'subtopic_number': numerical order of the subtopic in the unit.\n"
|
| 101 |
+
" • 'title': Arabic title that feels like a subheading in a textbook.\n"
|
| 102 |
+
" • 'purpose': one-sentence explanation of the educational goal behind that subtopic.\n\n"
|
| 103 |
+
"3. For each generated subtopic\n"
|
| 104 |
+
" - Prefer subtopics that are well-established in educational or academic literature.\n"
|
| 105 |
+
" - Avoid overly niche or abstract titles that would lack sufficient learning resources.\n\n"
|
| 106 |
+
## ADD
|
| 107 |
+
"4. Validate that each subtopic:\n"
|
| 108 |
+
" - Aligns with Arabic educational title standards (clarity, focus, precision, and appropriateness).\n"
|
| 109 |
+
" - Avoids dual titles, poetic phrasing, or abstract metaphors.\n\n"
|
| 110 |
+
"5. **Subtopics Title Quality & Language Validation**\n"
|
| 111 |
+
" - Each subtopic title is the learner’s first point of contact with the concept, so ensure the following:\n"
|
| 112 |
+
" Title length: concise (4–8 words preferred).\n"
|
| 113 |
+
" Clear and contextually linked to its unit or topic.\n"
|
| 114 |
+
" Written in tone appropriate for {audience}.\n"
|
| 115 |
+
" Avoids punctuation marks (– , ; : . ! ? , /) except for simple questions.\n"
|
| 116 |
+
" Represents one coherent idea — avoid compound or dual phrasing.\n"
|
| 117 |
+
" Avoids activity-based terms like 'ورشة عمل' or 'نشاط'.\n"
|
| 118 |
+
" Sounds realistic, teachable, and suitable for Arabic educational content.\n"
|
| 119 |
+
" can be in form of short sentence or a question\n\n"
|
| 120 |
+
"## NOTES\n"
|
| 121 |
+
# "- Make sure the subtopics flow naturally, covering introduction, comprehension, practice, and innovation.\n"
|
| 122 |
+
# "- The 5 axes should reflect a natural flow following Bloom’s taxonomy: Remember → Understand → Apply → Analyze → Create.\n"
|
| 123 |
+
"- Ensure the titles sound academic, culturally appropriate, and pedagogically progressive.\n"
|
| 124 |
+
"- Return the result as a valid FullCurriculumStructure JSON containing all units with their subtopics."
|
| 125 |
+
),
|
| 126 |
+
expected_output="A FullCurriculumStructure JSON object containing all units and their respective list of subtopics each.",
|
| 127 |
+
agent=subtopics_generator_agent,
|
| 128 |
+
output_json=FullCurriculumStructure,
|
| 129 |
+
)
|
agents/final_outliners/units_langchain.py
ADDED
|
@@ -0,0 +1,67 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# from langchain.agents import create_tool_calling_agent, AgentExecutor
|
| 2 |
+
# from langchain.prompts import ChatPromptTemplate
|
| 3 |
+
# from modules import model, llm_g
|
| 4 |
+
# import json
|
| 5 |
+
# import re
|
| 6 |
+
# import pandas as pd
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# def units_langchain_agent(topic: str, units_number: int):
|
| 10 |
+
# # الخطوة 1: نطلب من llm_g إنشاء Markdown plan
|
| 11 |
+
# result = llm_g.call(
|
| 12 |
+
# f"Create a structured {units_number}-unit study plan for the topic [{topic}]"
|
| 13 |
+
# )
|
| 14 |
+
|
| 15 |
+
# # الخطوة 2: الـ System Prompt الخاص بالاستخراج
|
| 16 |
+
# system_prompt = """
|
| 17 |
+
# You will receive Markdown text representing a study plan.
|
| 18 |
+
# Extract structured data and return it strictly in this JSON format:
|
| 19 |
+
|
| 20 |
+
# {{
|
| 21 |
+
# "topic": "<topic name>",
|
| 22 |
+
# "General_objectives_of_the_plan": ["string", "string", ...],
|
| 23 |
+
# "total_units": <total_units_number>,
|
| 24 |
+
# "units": [
|
| 25 |
+
# {{
|
| 26 |
+
# "unit_number": 1,
|
| 27 |
+
# "unit_title": "string",
|
| 28 |
+
# "description": "string",
|
| 29 |
+
# "unit_objectives": ["string", "string", ...],
|
| 30 |
+
# "unit_main_topics": ["string", "string", ...]
|
| 31 |
+
# }},
|
| 32 |
+
# ...
|
| 33 |
+
# ]
|
| 34 |
+
# }}
|
| 35 |
+
|
| 36 |
+
# Output **only valid JSON**, no explanations, markdown, or extra text.
|
| 37 |
+
# """
|
| 38 |
+
|
| 39 |
+
# # الخطوة 3: إنشاء prompt فيه متغير agent_scratchpad المطلوب
|
| 40 |
+
# prompt = ChatPromptTemplate.from_messages(
|
| 41 |
+
# [
|
| 42 |
+
# ("system", system_prompt),
|
| 43 |
+
# ("user", "{input}"),
|
| 44 |
+
# ("assistant", "{agent_scratchpad}"), # << الإضافة المطلوبة
|
| 45 |
+
# ]
|
| 46 |
+
# )
|
| 47 |
+
|
| 48 |
+
# # الخطوة 4: إنشاء الـ Agent
|
| 49 |
+
# tools = [] # مفيش Tools هنا
|
| 50 |
+
# agent = create_tool_calling_agent(model, tools, prompt=prompt)
|
| 51 |
+
|
| 52 |
+
# # الخطوة 5: تنفيذ الـ Agent
|
| 53 |
+
# agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
|
| 54 |
+
# response = agent_executor.invoke({"input": result, "agent_scratchpad": ""})
|
| 55 |
+
|
| 56 |
+
# # الخطوة 6: استخراج النتيجة
|
| 57 |
+
# raw_output = response.get("output", "").strip()
|
| 58 |
+
|
| 59 |
+
# # الخطوة 7: تنظيف وتحويل JSON
|
| 60 |
+
# try:
|
| 61 |
+
# structured_data = json.loads(raw_output)
|
| 62 |
+
# except json.JSONDecodeError:
|
| 63 |
+
# cleaned = re.sub(r"```json|```", "", raw_output).strip()
|
| 64 |
+
# structured_data = json.loads(cleaned)
|
| 65 |
+
|
| 66 |
+
# return structured_data
|
| 67 |
+
|
agents/final_outliners/units_langchain_1v.py
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from modules import model, llm_g
|
| 2 |
+
import json
|
| 3 |
+
import re
|
| 4 |
+
from langchain.agents import create_agent
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
def units_langchain1_agent(topic: str, units_number: int):
|
| 8 |
+
# الخطوة 1: نطلب من llm_g إنشاء Markdown plan
|
| 9 |
+
result = llm_g.call(
|
| 10 |
+
f"Create a structured {units_number}-unit study plan for the topic [{topic}] focuses on logical sequencing and educational activities without delving into scientific or technical details, The plan should be similar to a training plan that can be presented in a workshop or short course."
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
# الخطوة 2: الـ System Prompt الخاص بالاستخراج
|
| 14 |
+
system_prompt = """
|
| 15 |
+
extract structured data from Markdown text you will be given.
|
| 16 |
+
|
| 17 |
+
The JSON should have this exact structure:
|
| 18 |
+
{
|
| 19 |
+
"topic": "<topic name>",
|
| 20 |
+
"General_objectives_of_the_plan": ["string", "string", ...]
|
| 21 |
+
"total_units": <total_units_number>,
|
| 22 |
+
"units": [
|
| 23 |
+
{
|
| 24 |
+
"unit_number": 1,
|
| 25 |
+
"unit_title": "string",
|
| 26 |
+
"description": "string",
|
| 27 |
+
"unit_objectives": ["string", "string", ...],
|
| 28 |
+
"unit_main_topics": ["string", "string", ...]
|
| 29 |
+
},
|
| 30 |
+
...
|
| 31 |
+
]
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
NOTE:
|
| 35 |
+
if any descriptions are missing from the given file you can generate them after understanding the context.
|
| 36 |
+
|
| 37 |
+
Output **only valid JSON**, no explanations, markdown, or extra text.
|
| 38 |
+
"""
|
| 39 |
+
|
| 40 |
+
agent = create_agent(
|
| 41 |
+
model=model,
|
| 42 |
+
system_prompt=system_prompt,
|
| 43 |
+
)
|
| 44 |
+
|
| 45 |
+
response = agent.invoke({"messages": [{"role": "user", "content": result}]})
|
| 46 |
+
|
| 47 |
+
#######################
|
| 48 |
+
# الخطوة 6: استخراج النتيجة
|
| 49 |
+
raw_output = response['messages'][1].content.strip()
|
| 50 |
+
|
| 51 |
+
# الخطوة 7: تنظيف وتحويل JSON
|
| 52 |
+
try:
|
| 53 |
+
structured_data = json.loads(raw_output)
|
| 54 |
+
except json.JSONDecodeError:
|
| 55 |
+
cleaned = re.sub(r"```json|```", "", raw_output).strip()
|
| 56 |
+
structured_data = json.loads(cleaned)
|
| 57 |
+
|
| 58 |
+
return structured_data
|
agents/final_outliners/validator.py
ADDED
|
@@ -0,0 +1,139 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm_5m, llm_g
|
| 5 |
+
from schemas import ValidatedCurriculumOutput, validated_parser
|
| 6 |
+
from functools import cache
|
| 7 |
+
|
| 8 |
+
validator_agent = Agent(
|
| 9 |
+
role="Arabic Educational Validator (Curriculum Quality & Integrity Specialist)",
|
| 10 |
+
goal=(
|
| 11 |
+
"Ensure that all educational units and subtopics are conceptually complete, logically sequenced, linguistically refined, "
|
| 12 |
+
"and pedagogically sound for Arabic learners. Validate and enhance each unit's structure to maintain educational coherence "
|
| 13 |
+
"and clarity while preserving Arabic authenticity. Ensure all titles are in Arabic only. and try to include the notes given in the structure."
|
| 14 |
+
),
|
| 15 |
+
backstory=(
|
| 16 |
+
"You are a senior Arabic educational content validator and curriculum refinement expert. "
|
| 17 |
+
"You specialize in verifying conceptual completeness, depth, and sequencing of educational materials. "
|
| 18 |
+
"You understand Bloom’s taxonomy and Arabic pedagogical standards deeply. "
|
| 19 |
+
"You ensure all subtopics form a coherent, realistic, and progressive learning journey for the audience. "
|
| 20 |
+
"You maintain academic rigor and cultural authenticity while improving clarity and depth."
|
| 21 |
+
),
|
| 22 |
+
output_format=(
|
| 23 |
+
"Return a valid JSON with the following structure:\n"
|
| 24 |
+
"{\n"
|
| 25 |
+
" 'main_concept': '...',\n"
|
| 26 |
+
" 'General_objectives_of_the_plan': '...',\n"
|
| 27 |
+
" 'validated_units': [\n"
|
| 28 |
+
" {\n"
|
| 29 |
+
" 'unit_number': 1,\n"
|
| 30 |
+
" 'title': '...',\n"
|
| 31 |
+
" 'focus': '...',\n"
|
| 32 |
+
" 'validated_axes': [\n"
|
| 33 |
+
" {\n"
|
| 34 |
+
" 'axis_number': 1,\n"
|
| 35 |
+
" 'original_title': '...',\n"
|
| 36 |
+
" 'validated_title': '...',\n"
|
| 37 |
+
" 'original_purpose': '...',\n"
|
| 38 |
+
" 'validated_purpose': '...',\n"
|
| 39 |
+
" 'status': 'kept' | 'rephrased' | 'added' | 'removed'\n"
|
| 40 |
+
" }\n"
|
| 41 |
+
" ]\n"
|
| 42 |
+
" }\n"
|
| 43 |
+
" ]\n"
|
| 44 |
+
"}"
|
| 45 |
+
),
|
| 46 |
+
# llm=llm_open_c35,
|
| 47 |
+
llm=llm_g,
|
| 48 |
+
allow_delegation=False,
|
| 49 |
+
verbose=True,
|
| 50 |
+
reasoning=True,
|
| 51 |
+
max_iter=100,
|
| 52 |
+
cache=False,
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
validation_task = Task(
|
| 56 |
+
description=(
|
| 57 |
+
"Validate, refine, and enhance all generated educational units and their subtopics (only those needing improvement). "
|
| 58 |
+
"Ensure conceptual completeness, logical sequencing, and pedagogical depth across all units.\n\n"
|
| 59 |
+
"===================================================\n"
|
| 60 |
+
"## INPUT\n"
|
| 61 |
+
"You will be given a FullCurriculumStructure JSON from axis_generator_agent and details: {units}. "
|
| 62 |
+
"NOTES may also be provided {note}. These notes contain additional instructions or required new content. "
|
| 63 |
+
"so think how to achieve this within the educational plan, should you add new subtopic or new unit with new subtopic or modify anything(sure without deleting), "
|
| 64 |
+
"The agent must interpret the notes and add the required new subtopics or axes to the appropriate unit. "
|
| 65 |
+
"Example: If the note says 'تناول الاستخدامات الحديثة لتحليل البيانات في محور واحد', "
|
| 66 |
+
"you must add a new subtopic titled 'الاستخدامات الحديثة لتحليل البيانات' or any academically suitable Arabic title, "
|
| 67 |
+
"place it in the correct unit, and mark its status as 'added'.\n\n"
|
| 68 |
+
"===================================================\n"
|
| 69 |
+
"PRIMARY OBJECTIVE\n"
|
| 70 |
+
"===================================================\n"
|
| 71 |
+
"Ensure each unit exhibits:\n"
|
| 72 |
+
"1- Full conceptual and pedagogical integration.\n"
|
| 73 |
+
"2- Logical sequencing of ideas.\n"
|
| 74 |
+
"3- Arabic educational clarity and realism.\n"
|
| 75 |
+
"4- Comprehensive coverage of all described relations, aspects, and intentions.\n"
|
| 76 |
+
"5- Ensure the unit name best expresses its content in professional Arabic.\n"
|
| 77 |
+
"6- Avoid punctuation marks (– , ; : . ! ? , /) except for simple questions.\n"
|
| 78 |
+
"7- If removing punctuation affects grammar, enhance the title for natural Arabic style.\n\n"
|
| 79 |
+
"===================================================\n"
|
| 80 |
+
"PHASE 1 — COMPREHENSIVENESS & DEPTH ANALYSIS\n"
|
| 81 |
+
"===================================================\n"
|
| 82 |
+
"1. Analyze all subtopics for each unit and unit details.\n"
|
| 83 |
+
"2. Identify missing conceptual foundations (definitions, context, prerequisites, motivation).\n"
|
| 84 |
+
"3. Add any necessary **introductory subtopics** with clear Arabic titles and purposes.\n"
|
| 85 |
+
"4. Detect and remove any redundant or overlapping axes.\n\n"
|
| 86 |
+
"===================================================\n"
|
| 87 |
+
"PHASE 2 — INTEGRATION & SEQUENCING VALIDATION\n"
|
| 88 |
+
"===================================================\n"
|
| 89 |
+
"1. Ensure smooth conceptual progression from basic to advanced.\n"
|
| 90 |
+
"2. Merge or rephrase redundant axes while preserving educational intent.\n"
|
| 91 |
+
"3. Add **bridging subtopics** if conceptual jumps exist.\n"
|
| 92 |
+
"4. Reorder axes if needed to restore logical flow.\n\n"
|
| 93 |
+
"===================================================\n"
|
| 94 |
+
"PHASE 3 — REALISM & COVERAGE VALIDATION\n"
|
| 95 |
+
"===================================================\n"
|
| 96 |
+
"1. Confirm every conceptual aspect in the unit’s focus and all details is represented.\n"
|
| 97 |
+
"2. Ensure subtopics are realistic and pedagogically valid for the target audience.\n"
|
| 98 |
+
"3. Add missing real-world or practical dimensions.\n"
|
| 99 |
+
"4. Maintain natural, professional Arabic phrasing.\n\n"
|
| 100 |
+
"===================================================\n"
|
| 101 |
+
"PHASE 4 — SUBTOPICS TITLE QUALITY & LANGUAGE VALIDATION\n"
|
| 102 |
+
"===================================================\n"
|
| 103 |
+
"4. Validate that each Subtopic:\n"
|
| 104 |
+
" - Aligns with Arabic educational title standards (clarity, focus, precision, and appropriateness).\n"
|
| 105 |
+
" - Avoids dual titles, poetic phrasing, or abstract metaphors.\n\n"
|
| 106 |
+
"5. **Subtopics Title Quality & Language Validation**\n"
|
| 107 |
+
" - Title length: concise (4–8 words preferred).\n"
|
| 108 |
+
" - Clear and contextually linked to its unit.\n"
|
| 109 |
+
" - Tone appropriate for {audience}.\n"
|
| 110 |
+
" - Avoids punctuation marks except for simple questions.\n"
|
| 111 |
+
" - Represents one coherent idea, not compound.\n"
|
| 112 |
+
" - Avoids activity-based terms like 'ورشة عمل' or 'نشاط'.\n"
|
| 113 |
+
" - Sounds realistic, teachable, and suitable for Arabic educational content.\n\n"
|
| 114 |
+
"===================================================\n"
|
| 115 |
+
"PHASE 4.1 — ARABIC LANGUAGE INTEGRITY ENFORCEMENT\n"
|
| 116 |
+
"===================================================\n"
|
| 117 |
+
"1. Ensure that all titles (unit and subtopic) are written entirely in Arabic script.\n"
|
| 118 |
+
"2. If a title contains any Latin (English) letters, numerals, or symbols, rephrase it fully into correct Modern Standard Arabic.\n"
|
| 119 |
+
"3. Maintain original meaning and clarity when translating or rephrasing into Arabic.\n"
|
| 120 |
+
"4. Titles must not contain any transliterations (e.g., 'Entrepreneurship', 'AI', 'Design Thinking'). Replace them with Arabic equivalents.\n"
|
| 121 |
+
"5. Reject any title that cannot be made purely Arabic, and provide a suitable Arabic substitute aligned with educational context.\n\n"
|
| 122 |
+
"===================================================\n"
|
| 123 |
+
"PHASE 5 — OUTPUT STRUCTURE\n"
|
| 124 |
+
"===================================================\n"
|
| 125 |
+
"Return validated curriculum in JSON format with units, subtopics, and validation status.\n\n"
|
| 126 |
+
"===================================================\n"
|
| 127 |
+
"## NOTES\n"
|
| 128 |
+
"- Keep phrasing in professional Modern Standard Arabic.\n"
|
| 129 |
+
"- Avoid dual, poetic, or abstract titles.\n"
|
| 130 |
+
"- Ensure all outputs are grammatically correct and stylistically natural Arabic.\n"
|
| 131 |
+
"- Titles must not include any English or foreign words."
|
| 132 |
+
"- don't let the added notes destroy any of the curriculum structur only add what is needed."
|
| 133 |
+
),
|
| 134 |
+
# guardrail="",
|
| 135 |
+
expected_output="A JSON object showing validated units and subtopics with Arabic-only titles.",
|
| 136 |
+
output_json=ValidatedCurriculumOutput,
|
| 137 |
+
output_parser=validated_parser,
|
| 138 |
+
agent=validator_agent,
|
| 139 |
+
)
|
agents/outliner_phase/Deep_Semantic_Topics_Generator_1.py
ADDED
|
@@ -0,0 +1,118 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
from schemas import CurriculumOutline, DeepSemanticTopicsOutput
|
| 6 |
+
|
| 7 |
+
# ---------------------------
|
| 8 |
+
# === Agent 1: Deep Semantic Topics Generator (Full Coverage + Metadata Adaptive) ===
|
| 9 |
+
# ---------------------------
|
| 10 |
+
|
| 11 |
+
research_agent = Agent(
|
| 12 |
+
role="Deep Semantic Topics Generator (Educational Research Agent)",
|
| 13 |
+
goal="\n".join(
|
| 14 |
+
[
|
| 15 |
+
"Generate as many interconnected and realistic Arabic topics as possible for the curriculum title: {topic}.",
|
| 16 |
+
"Do NOT divide topics into units — just produce a comprehensive standalone list of high-quality topics.",
|
| 17 |
+
"Your mission is to achieve *maximum conceptual and practical coverage* of the topic: cover every visible and implicit meaning embedded in the title: {topic}.",
|
| 18 |
+
"Interpret the topic deeply and explore all related sub-concepts, tools, methods, applications, personal skills, frameworks, real-world examples, and future trends.",
|
| 19 |
+
"No aspect of the topic should remain uncovered — ensure total thematic coverage from theory to practice.",
|
| 20 |
+
# === Adaptation & Metadata awareness ===
|
| 21 |
+
"Always adapt to metadata: domain ({domain}), content_type ({content_type}), audience ({audience}), material_type ({material_type}).",
|
| 22 |
+
"Adjust tone, complexity, and depth according to the audience and domain type.",
|
| 23 |
+
"Apply DNA methodology explicitly in topic design:",
|
| 24 |
+
"- material_type:",
|
| 25 |
+
"-- Conceptual: theories, principles, abstract knowledge.",
|
| 26 |
+
"-- Procedural: step-by-step instructions or methods.",
|
| 27 |
+
"-- Structural: frameworks, models, or system views.",
|
| 28 |
+
"-- Personal: learner reflection, skills, or self-development aspects.",
|
| 29 |
+
"-- Realistic: real-world examples, applications, or case studies.",
|
| 30 |
+
"- content_type:",
|
| 31 |
+
"-- Educational → for structured learning (e.g., lessons, modules).",
|
| 32 |
+
"-- Awareness → for informative or awareness-raising purposes (e.g., campaigns, workshops).",
|
| 33 |
+
"-- Training → for hands-on skill development (e.g., exercises, applied learning).",
|
| 34 |
+
# === Learning progression ===
|
| 35 |
+
"Ensure logical educational progression throughout the topics:",
|
| 36 |
+
" 1️⃣ Start with conceptual understanding (definitions, foundations, importance).",
|
| 37 |
+
" 2️⃣ Then practical tools and applications (methods, workflows, tools).",
|
| 38 |
+
" 3️⃣ Then analysis and real-world case studies (evaluation, lessons learned).",
|
| 39 |
+
" 4️⃣ End with strategies, integration, and innovation (advanced synthesis, policies, or future directions).",
|
| 40 |
+
# === Title & Content validation ===
|
| 41 |
+
"Each topic must be realistic and searchable in Arabic or bilingual educational sources.",
|
| 42 |
+
"Before finalizing each topic, mentally confirm that real Arabic educational content exists online for it.",
|
| 43 |
+
"Reject or replace any vague, repetitive, or non-educational topics.",
|
| 44 |
+
"Avoid vague or redundant points — every topic must be unique and non-overlapping.",
|
| 45 |
+
# === Arabic educational title standards ===
|
| 46 |
+
"Follow Arabic educational title standards strictly:",
|
| 47 |
+
" - Clear, concise, and direct phrasing (no metaphors or poetic language).",
|
| 48 |
+
" - Titles should be between 4–7 words long.",
|
| 49 |
+
" - Represent a clear learning focus, suitable for the target audience ({audience}).",
|
| 50 |
+
" - Example good: مهارات التفكير النقدي واتخاذ القرار",
|
| 51 |
+
" - Example bad: رحلة العقل نحو التفكير النقدي وصناعة القرار",
|
| 52 |
+
# === Output schema ===
|
| 53 |
+
"For each topic, provide the following JSON fields exactly:",
|
| 54 |
+
" - title: Arabic, concise and direct",
|
| 55 |
+
" - description: 1–2 lines Arabic summarizing the topic",
|
| 56 |
+
" - dna: one of [Conceptual, Procedural, Structural, Personal, Realistic] and [Educational, Awareness, Training]",
|
| 57 |
+
" - suggested_unit: integer (1–4) showing depth progression (1=basic → 4=advanced)",
|
| 58 |
+
" - search_terms: 3–6 Arabic keywords relevant to the topic",
|
| 59 |
+
" - source: optional Arabic or bilingual educational source name/title (if known)",
|
| 60 |
+
# === Output constraints ===
|
| 61 |
+
"Output must be a valid JSON list (no commentary, no explanations).",
|
| 62 |
+
"List must be ordered by suggested_unit (1 → 4) to reflect gradual learning progression.",
|
| 63 |
+
]
|
| 64 |
+
),
|
| 65 |
+
backstory="\n".join(
|
| 66 |
+
[
|
| 67 |
+
"You are a senior educational researcher and curriculum architect with deep expertise in Arabic educational design and semantic topic analysis.",
|
| 68 |
+
"You deeply interpret the input topic — uncovering both its explicit and implicit meanings to ensure total thematic coverage.",
|
| 69 |
+
"You create coherent, realistic, and pedagogically structured topic sets that form a logical educational progression.",
|
| 70 |
+
"Each topic you design is grounded in actual Arabic or bilingual educational resources, ensuring that every subject can be realistically taught or studied.",
|
| 71 |
+
"You think step by step before finalizing outputs — validating realism, logical sequence, and online content availability.",
|
| 72 |
+
"Your work directly feeds the downstream Outline Agent, so clarity, precision, and educational completeness are essential in every topic you produce.",
|
| 73 |
+
]
|
| 74 |
+
),
|
| 75 |
+
allow_delegation=False,
|
| 76 |
+
llm=llm,
|
| 77 |
+
reasoning=True,
|
| 78 |
+
verbose=True,
|
| 79 |
+
max_reasoning_attempts=4,
|
| 80 |
+
max_iter=100,
|
| 81 |
+
)
|
| 82 |
+
|
| 83 |
+
# ---------------------------
|
| 84 |
+
# === Task 1: Generate Deep & Comprehensive Topics ===
|
| 85 |
+
# ---------------------------
|
| 86 |
+
|
| 87 |
+
research_task = Task(
|
| 88 |
+
description="\n".join(
|
| 89 |
+
[
|
| 90 |
+
"Generate a comprehensive, realistic, and logically structured list of Arabic topics for {topic}.",
|
| 91 |
+
"Ensure full semantic coverage — address both the explicit and implicit meanings of the topic title to cover all relevant dimensions and perspectives.",
|
| 92 |
+
"Include topics that collectively span all DNA dimensions and metadata parameters: content_type ({content_type}) and material_type ({material_type}).",
|
| 93 |
+
"Each topic must be unique, clear, and pedagogically meaningful — avoiding repetition, overlap, or vague expressions.",
|
| 94 |
+
"All topics must be realistic and supported by potential Arabic or bilingual educational resources available online.",
|
| 95 |
+
"Ensure educational progression: begin with conceptual foundations and definitions, then move through methods and tools, practical applications, case studies, and finally strategic or innovative insights.",
|
| 96 |
+
"Maintain alignment with Arabic educational title standards: concise, direct, single-part titles with clear learning focus.",
|
| 97 |
+
"Output must be a valid JSON list following the schema below — no explanations, introductions, or extra commentary.",
|
| 98 |
+
]
|
| 99 |
+
),
|
| 100 |
+
expected_output=(
|
| 101 |
+
"A valid JSON list ordered by suggested_unit ascending:\n"
|
| 102 |
+
"[\n"
|
| 103 |
+
" {\n"
|
| 104 |
+
' "title": "string (Arabic)",\n'
|
| 105 |
+
' "description": "string (1–2 lines in Arabic)",\n'
|
| 106 |
+
' "dna": "Conceptual|Procedural|Structural|Personal|Realistic",\n'
|
| 107 |
+
' "suggested_unit": 1|2|3|4,\n'
|
| 108 |
+
' "search_terms": ["string (Arabic keyword)", ...],\n'
|
| 109 |
+
' "source": "string (optional)"\n'
|
| 110 |
+
" }, ...\n"
|
| 111 |
+
"]\n"
|
| 112 |
+
"The output must be valid JSON, without markdown formatting or code blocks."
|
| 113 |
+
),
|
| 114 |
+
params={"min_topics": 10, "max_topics": 30}, # expand to ensure deeper coverage
|
| 115 |
+
output_json=DeepSemanticTopicsOutput,
|
| 116 |
+
# output_file=os.path.join(output_dir, "deep_semantic_topics.json"),
|
| 117 |
+
agent=research_agent,
|
| 118 |
+
)
|
agents/outliner_phase/__init__.py
ADDED
|
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .Deep_Semantic_Topics_Generator_1 import research_agent, research_task
|
| 2 |
+
from .topic_expander_2 import structure_agent, structure_task
|
| 3 |
+
from .module_organizer_3 import designer_agent, design_task
|
| 4 |
+
from .review_agent_4 import review_agent, review_task
|
agents/outliner_phase/module_organizer_3.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
from schemas import CurriculumOutline
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
# ---------------------------
|
| 9 |
+
# === Agent 3: Module Organizer ===
|
| 10 |
+
# ---------------------------
|
| 11 |
+
designer_agent = Agent(
|
| 12 |
+
role="Module Organizer Agent (Group into 4 modules)",
|
| 13 |
+
goal=(
|
| 14 |
+
"استلم الـ20 محورًا من Agent2. نظّمهم إلى **4 وحدات**، كل وحدة تحتوي على **5 مواضيع** "
|
| 15 |
+
"مرتبة متسلسلة ومنطقية. أعطِ كل وحدة عنوانًا واضحًا ومعبّرًا (module_title بالعربية)، "
|
| 16 |
+
"وقصّر عناوين المواضيع بحيث تكون جاهزة للاستخدام في الـ Curriculum (كل موضوع عبارة "
|
| 17 |
+
"عن جملة قصيرة أو عبارة). أعد صياغة المواضيع إن لزم لتكون متجانسة معًا."
|
| 18 |
+
),
|
| 19 |
+
backstory=(
|
| 20 |
+
"أنت كبير مصممي مناهج. مهمتك إخراج المخرجات بصيغة CurriculumOutline المتوافقة مع الـ schema."
|
| 21 |
+
),
|
| 22 |
+
llm=llm,
|
| 23 |
+
allow_delegation=False,
|
| 24 |
+
verbose=True,
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
design_task = Task(
|
| 29 |
+
description="تنظيم المحاور العشرين إلى 4 وحدات × 5 مواضيع في كل وحدة.",
|
| 30 |
+
expected_output=(
|
| 31 |
+
"A valid JSON object with this structure:\n"
|
| 32 |
+
"{\n"
|
| 33 |
+
' "title": "string (Arabic curriculum title)",\n'
|
| 34 |
+
' "units": [\n'
|
| 35 |
+
" {\n"
|
| 36 |
+
' "unit_title": "string (Arabic, must reflect the title)",\n'
|
| 37 |
+
' "topics": ["topic1", "topic2", "topic3", "topic4", "topic5"]\n'
|
| 38 |
+
" }, ... (4 units total)\n"
|
| 39 |
+
" ]\n"
|
| 40 |
+
"}\n"
|
| 41 |
+
"The output must be valid JSON, without markdown formatting or code blocks."
|
| 42 |
+
),
|
| 43 |
+
output_json=CurriculumOutline,
|
| 44 |
+
# output_file=os.path.join(output_dir, "curriculum_outline.json"),
|
| 45 |
+
agent=designer_agent,
|
| 46 |
+
)
|
agents/outliner_phase/review_agent_4.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
from schemas import CurriculumOutline
|
| 6 |
+
|
| 7 |
+
# ---------------------------
|
| 8 |
+
# === Agent 4: Final Reviewer (اختياري) ===
|
| 9 |
+
# ---------------------------
|
| 10 |
+
review_agent = Agent(
|
| 11 |
+
role="Final Review Agent",
|
| 12 |
+
goal=(
|
| 13 |
+
"راجع الناتج النهائي (4 وحدات × 5 مواضيع). صحح اللغة، احذف التكرار، وحسّن العناوين لتكون واضحة "
|
| 14 |
+
"وتتماشى مع الأسلوب التدريبي. تأكد أن 'title' يطابق الـ topic المدخل (بالعربية)."
|
| 15 |
+
),
|
| 16 |
+
backstory=(
|
| 17 |
+
"أنت محرر تعليمي يركز على وضوح الصياغة والاتساق. لا تغيّر المحتوى الجوهري، فقط حسن الصياغة."
|
| 18 |
+
),
|
| 19 |
+
llm=llm,
|
| 20 |
+
allow_delegation=False,
|
| 21 |
+
verbose=True,
|
| 22 |
+
)
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
review_task = Task(
|
| 26 |
+
description="مراجعة نهائية لغوية وتنسيقية للـ Curriculum النهائي.",
|
| 27 |
+
expected_output=(
|
| 28 |
+
"Final polished JSON identical in structure to CurriculumOutline, "
|
| 29 |
+
"with clear Arabic titles and consistent formatting. "
|
| 30 |
+
"The output must be valid JSON, without markdown formatting or code blocks."
|
| 31 |
+
),
|
| 32 |
+
output_json=CurriculumOutline,
|
| 33 |
+
# output_file=os.path.join(output_dir, "curriculum_outline_final.json"),
|
| 34 |
+
agent=review_agent,
|
| 35 |
+
)
|
agents/outliner_phase/topic_expander_2.py
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import Agent, Task, Crew, Process, LLM
|
| 2 |
+
import os
|
| 3 |
+
import json
|
| 4 |
+
from modules import llm
|
| 5 |
+
from schemas import ExpandedTopicsList
|
| 6 |
+
|
| 7 |
+
# ---------------------------
|
| 8 |
+
# === Agent 2: Expander to 20 Topics ===
|
| 9 |
+
# ---------------------------
|
| 10 |
+
structure_agent = Agent(
|
| 11 |
+
role="Expander to 20 Topics Agent (Structure & Relations)",
|
| 12 |
+
goal=(
|
| 13 |
+
"استلم قائمة المحاور المبدئية من Agent1. راجعها لإزالة التكرار ودمج المتقارب منها، "
|
| 14 |
+
"ثم أكمل ووسع القائمة لتصل إلى **بالضبط 20 محورًا** مترابطًا. "
|
| 15 |
+
"لكل محور اكتب وصفًا تفصيليًا 3-5 سطور يشرح محتوى المحور، ولماذا هو مهم، "
|
| 16 |
+
"واذكر علاقات واضحة بين المحاور (مثال: 'مرتبط بـ X لأن...'، أو 'يأتي بعد Y لأنه...'). "
|
| 17 |
+
"لا تقسم الوحدات بعد — فقط اضمن اتساق وترابط المحاور الـ20."
|
| 18 |
+
),
|
| 19 |
+
backstory=(
|
| 20 |
+
"أنت مصمم تعليمي بارع في بناء التسلسل المنطقي بين الموضوعات. مهمتك تحويل قائمة أولية "
|
| 21 |
+
"إلى خريطة معرفية من 20 محورًا."
|
| 22 |
+
),
|
| 23 |
+
llm=llm,
|
| 24 |
+
allow_delegation=False,
|
| 25 |
+
verbose=True,
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
structure_task = Task(
|
| 30 |
+
description="تنظيف القائمة السابقة وتوسيعها لتصل إلى 20 محورًا مترابطًا مع وصف مفصل.",
|
| 31 |
+
expected_output=(
|
| 32 |
+
"A JSON list of exactly 20 items:\n"
|
| 33 |
+
"[\n"
|
| 34 |
+
' { "title": "string (topic title)",\n'
|
| 35 |
+
' "description": "string (3–5 lines)",\n'
|
| 36 |
+
' "relation": "string (e.g., related to X because...)" }\n'
|
| 37 |
+
"]\n"
|
| 38 |
+
"The output must be valid JSON, without markdown formatting or code blocks."
|
| 39 |
+
),
|
| 40 |
+
output_json=ExpandedTopicsList,
|
| 41 |
+
# output_file=os.path.join(output_dir, "expanded_20_topics.json"),
|
| 42 |
+
agent=structure_agent,
|
| 43 |
+
)
|
app.py
ADDED
|
@@ -0,0 +1,60 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import shutil
|
| 3 |
+
# Force HOME to /tmp so CrewAI doesn't try writing to /.local
|
| 4 |
+
os.environ["HOME"] = "/tmp"
|
| 5 |
+
os.environ["XDG_DATA_HOME"] = "/tmp/.local/share"
|
| 6 |
+
os.environ["CREWAI_STORAGE_PATH"] = "/tmp/crewai_data"
|
| 7 |
+
os.environ["CREWAI_HOME"] = "/tmp/crewai_home"
|
| 8 |
+
|
| 9 |
+
# Create safe directories
|
| 10 |
+
os.makedirs("/tmp/.local/share", exist_ok=True)
|
| 11 |
+
os.makedirs("/tmp/crewai_data", exist_ok=True)
|
| 12 |
+
os.makedirs("/tmp/crewai_home", exist_ok=True)
|
| 13 |
+
from crewai import Crew, Process
|
| 14 |
+
import json
|
| 15 |
+
from fastapi import FastAPI
|
| 16 |
+
from routers import objective_route, outliner_route, outcome_route,introduction_route
|
| 17 |
+
|
| 18 |
+
|
| 19 |
+
app = FastAPI(title="AI Agent Project", version="1.0.0")
|
| 20 |
+
|
| 21 |
+
app.include_router(outliner_route.router)
|
| 22 |
+
app.include_router(objective_route.router)
|
| 23 |
+
app.include_router(outcome_route.router)
|
| 24 |
+
app.include_router(introduction_route.router)
|
| 25 |
+
|
| 26 |
+
# Clear Cashe
|
| 27 |
+
@app.get("/reset-cache")
|
| 28 |
+
def reset_cache():
|
| 29 |
+
|
| 30 |
+
paths = [
|
| 31 |
+
"/tmp/crewai_data",
|
| 32 |
+
"/tmp/crewai_home",
|
| 33 |
+
"/tmp/.local/share",
|
| 34 |
+
]
|
| 35 |
+
|
| 36 |
+
for path in paths:
|
| 37 |
+
if os.path.exists(path):
|
| 38 |
+
shutil.rmtree(path, ignore_errors=True)
|
| 39 |
+
|
| 40 |
+
os.makedirs("/tmp/crewai_data", exist_ok=True)
|
| 41 |
+
os.makedirs("/tmp/crewai_home", exist_ok=True)
|
| 42 |
+
os.makedirs("/tmp/.local/share", exist_ok=True)
|
| 43 |
+
|
| 44 |
+
return {"message": "✅ Cache cleared successfully."}
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
# Example root endpoint
|
| 48 |
+
@app.get("/")
|
| 49 |
+
def read_root():
|
| 50 |
+
return {"message": "Welcome to AI Agent Project API 🚀"}
|
| 51 |
+
|
| 52 |
+
|
| 53 |
+
# ------------------------
|
| 54 |
+
# ✅ نقطة تشغيل السيرفر
|
| 55 |
+
# ------------------------
|
| 56 |
+
|
| 57 |
+
# if __name__ == "__main__":
|
| 58 |
+
# import uvicorn
|
| 59 |
+
|
| 60 |
+
# uvicorn.run("main:app", host="127.0.0.1", port=8000, reload=True)
|
modules/__init__.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .env import (
|
| 2 |
+
llm,
|
| 3 |
+
llm_g,
|
| 4 |
+
llm_5m,
|
| 5 |
+
llm_4m,
|
| 6 |
+
llm_5n,
|
| 7 |
+
llm_oss,
|
| 8 |
+
llm_open_c3,
|
| 9 |
+
llm_open_c35,
|
| 10 |
+
model,
|
| 11 |
+
)
|
| 12 |
+
from .inputs import (
|
| 13 |
+
TRUSTED_SITES,
|
| 14 |
+
bloom_taxonomy_1,
|
| 15 |
+
bloom_taxonomy_2,
|
| 16 |
+
html_template,
|
| 17 |
+
objectives_dimensions,
|
| 18 |
+
# outlines,
|
| 19 |
+
# objectives,
|
| 20 |
+
)
|
| 21 |
+
|
| 22 |
+
# from .directory import (
|
| 23 |
+
# output_dir,
|
| 24 |
+
# keywords_dir,
|
| 25 |
+
# outliner_dir,
|
| 26 |
+
# scraper_dir,
|
| 27 |
+
# urls_dir
|
| 28 |
+
# )
|
modules/directory.py
ADDED
|
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# import os
|
| 2 |
+
|
| 3 |
+
# current_dir = os.path.dirname(os.path.abspath(__file__))
|
| 4 |
+
# base_dir = os.path.dirname(current_dir)
|
| 5 |
+
|
| 6 |
+
# output_dir = os.path.join(base_dir, "assets", "ai_agent_output")
|
| 7 |
+
# keywords_dir = os.path.join(base_dir, "assets", "keywords")
|
| 8 |
+
# outliner_dir = os.path.join(base_dir, "assets", "outliner_sections")
|
| 9 |
+
# scraper_dir = os.path.join(base_dir, "assets", "scraped_data")
|
| 10 |
+
# urls_dir = os.path.join(base_dir, "assets", "urls")
|
| 11 |
+
|
| 12 |
+
|
modules/env.py
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from crewai import LLM
|
| 2 |
+
import os
|
| 3 |
+
from dotenv import load_dotenv
|
| 4 |
+
from pathlib import Path
|
| 5 |
+
from langchain_openai import ChatOpenAI
|
| 6 |
+
|
| 7 |
+
env_path = Path(__file__).resolve().parents[1] / ".env"
|
| 8 |
+
# Load variables from .env file
|
| 9 |
+
load_dotenv(dotenv_path=env_path)
|
| 10 |
+
|
| 11 |
+
# Now you can access them
|
| 12 |
+
gemini_key = os.getenv("GEMINI_API_KEY")
|
| 13 |
+
tavily_key = os.getenv("TAVILY_API_KEY")
|
| 14 |
+
openrouter_key = os.getenv("OPENROUTER_API_KEY")
|
| 15 |
+
os.environ["ANTHROPIC_API_KEY"] = openrouter_key
|
| 16 |
+
# llm = LLM(model="gemini/gemini-2.5-flash", temperature=0, api_key=gemini_key)
|
| 17 |
+
llm = LLM(
|
| 18 |
+
model="openrouter/openai/gpt-oss-20b:free",
|
| 19 |
+
api_key=openrouter_key,
|
| 20 |
+
base_url="https://openrouter.ai/api/v1",
|
| 21 |
+
)
|
| 22 |
+
llm_oss = LLM(
|
| 23 |
+
model="openrouter/openai/gpt-oss-20b:free",
|
| 24 |
+
api_key=openrouter_key,
|
| 25 |
+
base_url="https://openrouter.ai/api/v1",
|
| 26 |
+
)
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
llm_g = LLM(
|
| 30 |
+
model="openrouter/google/gemini-2.5-flash",
|
| 31 |
+
temperature=0,
|
| 32 |
+
api_key=openrouter_key,
|
| 33 |
+
base_url="https://openrouter.ai/api/v1",
|
| 34 |
+
)
|
| 35 |
+
|
| 36 |
+
llm_5m = LLM(
|
| 37 |
+
model="gpt-5-mini-2025-08-07",
|
| 38 |
+
)
|
| 39 |
+
|
| 40 |
+
llm_4m = LLM(
|
| 41 |
+
model="gpt-4.1-mini-2025-04-14",
|
| 42 |
+
)
|
| 43 |
+
|
| 44 |
+
llm_5n = LLM(
|
| 45 |
+
model="gpt-5-nano-2025-08-07",
|
| 46 |
+
)
|
| 47 |
+
|
| 48 |
+
llm_open_c3 = LLM(
|
| 49 |
+
api_key=os.environ["OPENROUTER_API_KEY"],
|
| 50 |
+
base_url="https://openrouter.ai/api/v1",
|
| 51 |
+
model="openrouter/anthropic/claude-3-haiku",
|
| 52 |
+
streaming=False,
|
| 53 |
+
)
|
| 54 |
+
|
| 55 |
+
llm_open_c35 = LLM(
|
| 56 |
+
api_key=os.environ["OPENROUTER_API_KEY"],
|
| 57 |
+
base_url="https://openrouter.ai/api/v1",
|
| 58 |
+
model="openrouter/anthropic/claude-3.5-haiku",
|
| 59 |
+
streaming=False,
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
# Initialize Gemini model
|
| 63 |
+
model = ChatOpenAI(
|
| 64 |
+
model="google/gemini-2.5-flash",
|
| 65 |
+
temperature=0,
|
| 66 |
+
api_key=openrouter_key,
|
| 67 |
+
base_url="https://openrouter.ai/api/v1",
|
| 68 |
+
)
|
| 69 |
+
|
| 70 |
+
|
| 71 |
+
# # check llm
|
| 72 |
+
# response=llm_g.call("Hello, how are you?")
|
| 73 |
+
# print(response)
|
modules/inputs.py
ADDED
|
@@ -0,0 +1,736 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
# from .directory import output_dir
|
| 4 |
+
###################--Inputs--#######################
|
| 5 |
+
"""
|
| 6 |
+
/*********************************************************************************************************************************************/
|
| 7 |
+
title="The main topic to generate an outline for",
|
| 8 |
+
description="The specific subject or concept that the outline should focus on. Example: 'Time Management', 'Machine Learning Basics', 'Healthy Nutrition'")
|
| 9 |
+
/*********************************************************************************************************************************************/
|
| 10 |
+
title="Knowledge domain",
|
| 11 |
+
description="The broader field of knowledge or industry where the topic belongs. Example: IT, Engineering, Education, Healthcare, Business"
|
| 12 |
+
/*********************************************************************************************************************************************/
|
| 13 |
+
title="Type of content",
|
| 14 |
+
description=(
|
| 15 |
+
"Educational → for structured learning (e.g., lessons, modules)\n"
|
| 16 |
+
"Awareness → for informative/raising awareness purposes (e.g., campaigns, workshops)\n"
|
| 17 |
+
"Training → for skill development with step-by-step practice (e.g., hands-on, exercises)"
|
| 18 |
+
)
|
| 19 |
+
/*********************************************************************************************************************************************/
|
| 20 |
+
title="Target audience",
|
| 21 |
+
description=(
|
| 22 |
+
"The group of people intended to benefit from the material. Example:\n"
|
| 23 |
+
"- Kids (age 6–12)\n"
|
| 24 |
+
"- High School Students (teenagers)\n"
|
| 25 |
+
"- University Students (academic level)\n"
|
| 26 |
+
"- Professionals (working individuals)\n"
|
| 27 |
+
"- General Public (all ages, non-technical)"
|
| 28 |
+
)
|
| 29 |
+
/*********************************************************************************************************************************************/
|
| 30 |
+
title="Nature of the scientific material",
|
| 31 |
+
description=(
|
| 32 |
+
"Defines the learning approach:\n"
|
| 33 |
+
"- Conceptual → focuses on theories, principles, and abstract knowledge.\n"
|
| 34 |
+
"- Procedural → step-by-step methods, instructions, or processes.\n"
|
| 35 |
+
"- Structural → frameworks, models, and organized structures.\n"
|
| 36 |
+
"- Personal → reflections, personal skills, and self-development aspects.\n"
|
| 37 |
+
"- Realistic → practical, case-based, real-world examples and applications."
|
| 38 |
+
)
|
| 39 |
+
/*********************************************************************************************************************************************/
|
| 40 |
+
|
| 41 |
+
"""
|
| 42 |
+
|
| 43 |
+
# inputs={
|
| 44 |
+
# "topic":"بدله الفضاء",
|
| 45 |
+
# "domain": "Aerospace Engineering",
|
| 46 |
+
# "content_type": "Educational",
|
| 47 |
+
# "audience": "University Students",
|
| 48 |
+
# "material_type": ["Procedural","Realistic","Personal"]
|
| 49 |
+
# }
|
| 50 |
+
|
| 51 |
+
|
| 52 |
+
TRUSTED_SITES = [
|
| 53 |
+
"scholar.google.com",
|
| 54 |
+
"researchgate.net",
|
| 55 |
+
"doaj.org",
|
| 56 |
+
"scopus.com",
|
| 57 |
+
"academia.edu",
|
| 58 |
+
"almanhal.com",
|
| 59 |
+
"digitallibrary.un.org",
|
| 60 |
+
"virtuallrc.com",
|
| 61 |
+
"dlc.dlib.indiana.edu",
|
| 62 |
+
"pubmed.ncbi.nlm.nih.gov",
|
| 63 |
+
"arxiv.org",
|
| 64 |
+
"archiveshub.jisc.ac.uk",
|
| 65 |
+
]
|
| 66 |
+
|
| 67 |
+
|
| 68 |
+
###################--BLOOM 1--#######################
|
| 69 |
+
bloom_taxonomy_1 = {
|
| 70 |
+
"Remember": """The process of recalling facts, terms, concepts, or basic principles from memory
|
| 71 |
+
without necessarily understanding them. This level involves recognition and recall
|
| 72 |
+
of previously learned material, such as definitions, lists, dates, formulas, or key terms.
|
| 73 |
+
The focus is strictly on accurate retrieval, not comprehension or application.
|
| 74 |
+
It is the foundation for higher-order thinking because learners must first be able
|
| 75 |
+
to retrieve information before they can understand, apply, or analyze it.""",
|
| 76 |
+
"Understand": """The process of constructing meaning from instructional materials and messages.
|
| 77 |
+
It involves explaining ideas or concepts, interpreting information, summarizing content,
|
| 78 |
+
and demonstrating comprehension of facts, rules, or principles. Learners show that they
|
| 79 |
+
grasp the essence of material by restating it in their own words, providing basic
|
| 80 |
+
interpretations, or making connections. At this level, students demonstrate they
|
| 81 |
+
understand the 'what' and 'why' of knowledge rather than just memorizing it.""",
|
| 82 |
+
"Apply": """The process of using learned material in new and concrete situations.
|
| 83 |
+
It includes executing procedures, implementing methods, or applying principles
|
| 84 |
+
to solve problems. Learners demonstrate their ability to transfer knowledge to
|
| 85 |
+
practical tasks, exercises, or unfamiliar contexts. This involves using facts,
|
| 86 |
+
techniques, and rules in a different way than originally learned, adapting them
|
| 87 |
+
to meet the needs of new situations. Application shows the ability to move beyond
|
| 88 |
+
rote memory and demonstrate understanding through action.""",
|
| 89 |
+
"Analyze": """The process of examining material in detail and breaking it into smaller components
|
| 90 |
+
to understand its structure and relationships. This involves identifying motives, causes,
|
| 91 |
+
assumptions, or evidence and distinguishing between facts and opinions. Learners also
|
| 92 |
+
draw conclusions, detect patterns, and find evidence to support generalizations.
|
| 93 |
+
Analysis requires uncovering how parts work together and how they contribute
|
| 94 |
+
to the overall meaning or outcome. It is a critical step that prepares learners
|
| 95 |
+
for evaluation and creation.""",
|
| 96 |
+
"Evaluate": """The process of presenting opinions and defending them by making judgments
|
| 97 |
+
about information, the validity of ideas, or the quality of work based on a set
|
| 98 |
+
of criteria. It includes checking, critiquing, and reviewing by applying logical reasoning
|
| 99 |
+
or evidence. Learners assess the strengths and weaknesses of approaches, solutions,
|
| 100 |
+
or arguments, providing justification for their conclusions. Evaluation demands both
|
| 101 |
+
critical thinking and the ability to apply standards consistently, making it
|
| 102 |
+
a higher-order skill that guides decision-making.""",
|
| 103 |
+
"Create": """The process of putting elements together to form a novel, functional whole.
|
| 104 |
+
It involves reorganizing concepts into a new pattern or structure, such as through planning,
|
| 105 |
+
design, or production. Learners generate original ideas, propose innovative solutions,
|
| 106 |
+
or produce unique work by combining existing knowledge in new ways. This level requires
|
| 107 |
+
synthesis, imagination, and innovation. Creation is the highest level of Bloom’s taxonomy,
|
| 108 |
+
demonstrating mastery by building something entirely new from prior knowledge
|
| 109 |
+
and skills.""",
|
| 110 |
+
}
|
| 111 |
+
|
| 112 |
+
|
| 113 |
+
###################--BLOOM 2--#######################
|
| 114 |
+
|
| 115 |
+
bloom_taxonomy_2 = {
|
| 116 |
+
"Remember": {
|
| 117 |
+
"description": """The process of recalling facts, terms, concepts, or basic principles from memory
|
| 118 |
+
without necessarily understanding them. This level involves recognition and recall
|
| 119 |
+
of previously learned material, such as definitions, lists, dates, formulas, or key terms.
|
| 120 |
+
The focus is strictly on accurate retrieval, not comprehension or application.
|
| 121 |
+
It is the foundation for higher-order thinking because learners must first be able
|
| 122 |
+
to retrieve information before they can understand, apply, or analyze it.""",
|
| 123 |
+
"Remember_verbs_examples": [
|
| 124 |
+
"يختار",
|
| 125 |
+
"يراقب",
|
| 126 |
+
"يعرض",
|
| 127 |
+
"ينسخ",
|
| 128 |
+
"يتهجى",
|
| 129 |
+
"يُعرّف",
|
| 130 |
+
"يقتبس",
|
| 131 |
+
"يقرأ",
|
| 132 |
+
"يتعرف على",
|
| 133 |
+
"يحدد",
|
| 134 |
+
"يكرر",
|
| 135 |
+
"يكتب",
|
| 136 |
+
"يعيد سرد",
|
| 137 |
+
"يصف",
|
| 138 |
+
"يطابق",
|
| 139 |
+
"يسمي",
|
| 140 |
+
"يرقم",
|
| 141 |
+
"يتلو",
|
| 142 |
+
"يبحث",
|
| 143 |
+
],
|
| 144 |
+
},
|
| 145 |
+
"Understand": {
|
| 146 |
+
"description": """The process of constructing meaning from instructional materials and messages.
|
| 147 |
+
It involves explaining ideas or concepts, interpreting information, summarizing content,
|
| 148 |
+
and demonstrating comprehension of facts, rules, or principles. Learners show that they
|
| 149 |
+
grasp the essence of material by restating it in their own words, providing basic
|
| 150 |
+
interpretations, or making connections. At this level, students demonstrate they
|
| 151 |
+
understand the 'what' and 'why' of knowledge rather than just memorizing it.""",
|
| 152 |
+
"Understand_verbs_examples": [
|
| 153 |
+
"يسأل",
|
| 154 |
+
"يستشهد",
|
| 155 |
+
"يعمم",
|
| 156 |
+
"يتنبأ",
|
| 157 |
+
"يصنف",
|
| 158 |
+
"يقارن",
|
| 159 |
+
"يوضح",
|
| 160 |
+
"يَعُد",
|
| 161 |
+
"يناقش",
|
| 162 |
+
"يستدل",
|
| 163 |
+
"يراجع",
|
| 164 |
+
"يفسر",
|
| 165 |
+
"يعرض",
|
| 166 |
+
"يشرح",
|
| 167 |
+
"يلخص",
|
| 168 |
+
"يعبر عن",
|
| 169 |
+
"يترجم",
|
| 170 |
+
"يربط",
|
| 171 |
+
"يصف",
|
| 172 |
+
"يحول",
|
| 173 |
+
"يكتشف",
|
| 174 |
+
"يميز",
|
| 175 |
+
"يجمع",
|
| 176 |
+
"يحدد",
|
| 177 |
+
"يعيد الصياغة",
|
| 178 |
+
"يلخص",
|
| 179 |
+
],
|
| 180 |
+
},
|
| 181 |
+
"Apply": {
|
| 182 |
+
"description": """The process of using learned material in new and concrete situations.
|
| 183 |
+
It includes executing procedures, implementing methods, or applying principles
|
| 184 |
+
to solve problems. Learners demonstrate their ability to transfer knowledge to
|
| 185 |
+
practical tasks, exercises, or unfamiliar contexts. This involves using facts,
|
| 186 |
+
techniques, and rules in a different way than originally learned, adapting them
|
| 187 |
+
to meet the needs of new situations. Application shows the ability to move beyond
|
| 188 |
+
rote memory and demonstrate understanding through action.""",
|
| 189 |
+
"Apply_verbs_examples": [
|
| 190 |
+
"يمثل",
|
| 191 |
+
"يوظف",
|
| 192 |
+
"يمارس",
|
| 193 |
+
"يدير",
|
| 194 |
+
"يجرب",
|
| 195 |
+
"يبني",
|
| 196 |
+
"يحسب",
|
| 197 |
+
"يحاكي",
|
| 198 |
+
"يحل",
|
| 199 |
+
"يستخدم",
|
| 200 |
+
"ينظم",
|
| 201 |
+
"يطور",
|
| 202 |
+
"يؤدي",
|
| 203 |
+
"يخطط",
|
| 204 |
+
"ينفذ",
|
| 205 |
+
"يرسم بياني",
|
| 206 |
+
"يستكمل",
|
| 207 |
+
"يفحص",
|
| 208 |
+
"��شرح",
|
| 209 |
+
"يحرر",
|
| 210 |
+
"يحمل",
|
| 211 |
+
"يشغل",
|
| 212 |
+
"يلون",
|
| 213 |
+
"يلعب",
|
| 214 |
+
"يحضر",
|
| 215 |
+
"يشارك",
|
| 216 |
+
"يرسم",
|
| 217 |
+
"يستخدم",
|
| 218 |
+
],
|
| 219 |
+
},
|
| 220 |
+
"Analyze": {
|
| 221 |
+
"description": """The process of examining material in detail and breaking it into smaller components
|
| 222 |
+
to understand its structure and relationships. This involves identifying motives, causes,
|
| 223 |
+
assumptions, or evidence and distinguishing between facts and opinions. Learners also
|
| 224 |
+
draw conclusions, detect patterns, and find evidence to support generalizations.
|
| 225 |
+
Analysis requires uncovering how parts work together and how they contribute
|
| 226 |
+
to the overall meaning or outcome. It is a critical step that prepares learners
|
| 227 |
+
for evaluation and creation.""",
|
| 228 |
+
"Analyze_verbs_examples": [
|
| 229 |
+
"يحلل",
|
| 230 |
+
"يفحص",
|
| 231 |
+
"يحدد الأولويات",
|
| 232 |
+
"يجد",
|
| 233 |
+
"يرتب",
|
| 234 |
+
"يفترض",
|
| 235 |
+
"يوظف",
|
| 236 |
+
"يسلط الضوء",
|
| 237 |
+
"يناقش",
|
| 238 |
+
"يعيد تنظيم",
|
| 239 |
+
"يبحث",
|
| 240 |
+
"يستدل",
|
| 241 |
+
"يحدد الاختلافات",
|
| 242 |
+
"يكتشف",
|
| 243 |
+
"يبسط",
|
| 244 |
+
"يشرح",
|
| 245 |
+
"يحذف",
|
| 246 |
+
"يقارن",
|
| 247 |
+
"يربط بين",
|
| 248 |
+
"يستنتج",
|
| 249 |
+
"يفرق",
|
| 250 |
+
"يميز",
|
| 251 |
+
"يفصل",
|
| 252 |
+
"يقدر",
|
| 253 |
+
"يرسم الخرائط الذهنية",
|
| 254 |
+
"يحدد الخطوط العريضة بخطط",
|
| 255 |
+
],
|
| 256 |
+
},
|
| 257 |
+
"Evaluate": {
|
| 258 |
+
"description": """The process of presenting opinions and defending them by making judgments
|
| 259 |
+
about information, the validity of ideas, or the quality of work based on a set
|
| 260 |
+
of criteria. It includes checking, critiquing, and reviewing by applying logical reasoning
|
| 261 |
+
or evidence. Learners assess the strengths and weaknesses of approaches, solutions,
|
| 262 |
+
or arguments, providing justification for their conclusions. Evaluation demands both
|
| 263 |
+
critical thinking and the ability to apply standards consistently, making it
|
| 264 |
+
a higher-order skill that guides decision-making.""",
|
| 265 |
+
"Evaluate_verbs_examples": [
|
| 266 |
+
"يعطي رأي",
|
| 267 |
+
"يدحض",
|
| 268 |
+
"يقيس",
|
| 269 |
+
"يُقيم",
|
| 270 |
+
"يجادل",
|
| 271 |
+
"يقدر",
|
| 272 |
+
"يقنع",
|
| 273 |
+
"يثبت",
|
| 274 |
+
"يعطي الأسباب",
|
| 275 |
+
"يومي",
|
| 276 |
+
"يصدر حكم على",
|
| 277 |
+
"يدعم",
|
| 278 |
+
"يضع معايير",
|
| 279 |
+
"يتحقق من صحة",
|
| 280 |
+
"يقرر",
|
| 281 |
+
"يفسر",
|
| 282 |
+
"يحكم على",
|
| 283 |
+
"يبرر",
|
| 284 |
+
"يتجادل",
|
| 285 |
+
"ينتقد",
|
| 286 |
+
"يناقش",
|
| 287 |
+
"يدافع",
|
| 288 |
+
"يحرر",
|
| 289 |
+
"يفترض",
|
| 290 |
+
"يقيس",
|
| 291 |
+
"يراقب",
|
| 292 |
+
"يتنبأ",
|
| 293 |
+
"يعيد صياغة",
|
| 294 |
+
],
|
| 295 |
+
},
|
| 296 |
+
"Create": {
|
| 297 |
+
"description": """The process of putting elements together to form a novel, functional whole.
|
| 298 |
+
It involves reorganizing concepts into a new pattern or structure, such as through planning,
|
| 299 |
+
design, or production. Learners generate original ideas, propose innovative solutions,
|
| 300 |
+
or produce unique work by combining existing knowledge in new ways. This level requires
|
| 301 |
+
synthesis, imagination, and innovation. Creation is the highest level of Bloom’s taxonomy,
|
| 302 |
+
demonstrating mastery by building something entirely new from prior knowledge
|
| 303 |
+
and skills.""",
|
| 304 |
+
"Create_verbs_examples": [
|
| 305 |
+
"يدون",
|
| 306 |
+
"يتعاون",
|
| 307 |
+
"يؤلف",
|
| 308 |
+
"يبني",
|
| 309 |
+
"يصمم",
|
| 310 |
+
"يبتكر",
|
| 311 |
+
"يوجه",
|
| 312 |
+
"يضع تصور",
|
| 313 |
+
"يعيد صياغة",
|
| 314 |
+
"يخترع",
|
| 315 |
+
"يخلط",
|
| 316 |
+
"يعيد مزج",
|
| 317 |
+
"يعدل",
|
| 318 |
+
"يتفاوض",
|
| 319 |
+
"يخطط",
|
| 320 |
+
"ينتج",
|
| 321 |
+
"يبرمج",
|
| 322 |
+
"ينشر",
|
| 323 |
+
"يلعب الأدوار",
|
| 324 |
+
"يحاكي",
|
| 325 |
+
"يقترح حل",
|
| 326 |
+
"يعيد هيكلة",
|
| 327 |
+
"يكتب",
|
| 328 |
+
],
|
| 329 |
+
},
|
| 330 |
+
}
|
| 331 |
+
|
| 332 |
+
|
| 333 |
+
objectives_dimensions = {
|
| 334 |
+
"Knowledge": {
|
| 335 |
+
"description": "المجال المعرفي (Cognitive Domain): يركز على العمليات العقلية والفكرية، ويشمل اكتساب المعلومات، الفهم، التطبيق، التحليل، التقييم، والإبداع. يتدرج من مستويات التفكير الدنيا إلى العليا حسب تصنيف بلوم المعدل.",
|
| 336 |
+
"levels": [
|
| 337 |
+
{
|
| 338 |
+
"level_name": "Remember (التذكر)",
|
| 339 |
+
"description": "استرجاع المعلومات والمعارف من الذاكرة طويلة المدى",
|
| 340 |
+
"verbs_examples": [
|
| 341 |
+
"يذكر",
|
| 342 |
+
"يعرف",
|
| 343 |
+
"يحدد",
|
| 344 |
+
"يصنف",
|
| 345 |
+
"يسمي",
|
| 346 |
+
"يعدد",
|
| 347 |
+
"يسترجع",
|
| 348 |
+
],
|
| 349 |
+
},
|
| 350 |
+
{
|
| 351 |
+
"level_name": "Understand (الفهم)",
|
| 352 |
+
"description": "بناء المعنى من المعلومات الشفهية والمكتوبة والرسومية",
|
| 353 |
+
"verbs_examples": [
|
| 354 |
+
"يفسر",
|
| 355 |
+
"يستنتج",
|
| 356 |
+
"يصف",
|
| 357 |
+
"يناقش",
|
| 358 |
+
"يترجم",
|
| 359 |
+
"يميز",
|
| 360 |
+
"يشرح",
|
| 361 |
+
"يلخص",
|
| 362 |
+
],
|
| 363 |
+
},
|
| 364 |
+
{
|
| 365 |
+
"level_name": "Apply (التطبيق)",
|
| 366 |
+
"description": "تنفيذ أو استخدام إجراء معين في موقف محدد",
|
| 367 |
+
"verbs_examples": [
|
| 368 |
+
"يستخدم",
|
| 369 |
+
"يطبق",
|
| 370 |
+
"يجرب",
|
| 371 |
+
"يشرح",
|
| 372 |
+
"يبرهن",
|
| 373 |
+
"ينفذ",
|
| 374 |
+
"يحل",
|
| 375 |
+
],
|
| 376 |
+
},
|
| 377 |
+
{
|
| 378 |
+
"level_name": "Analyze (التحليل)",
|
| 379 |
+
"description": "تقسيم المادة إلى أجزائها المكونة وتحديد العلاقات بينها",
|
| 380 |
+
"verbs_examples": [
|
| 381 |
+
"يحلل",
|
| 382 |
+
"يربط",
|
| 383 |
+
"يقارن",
|
| 384 |
+
"يوازن",
|
| 385 |
+
"يفحص",
|
| 386 |
+
"يميز",
|
| 387 |
+
"يصنف",
|
| 388 |
+
],
|
| 389 |
+
},
|
| 390 |
+
{
|
| 391 |
+
"level_name": "Evaluate (التقويم)",
|
| 392 |
+
"description": "إصدار أحكام بناءً على معايير ومحكات محددة",
|
| 393 |
+
"verbs_examples": [
|
| 394 |
+
"يقيم",
|
| 395 |
+
"ينقد",
|
| 396 |
+
"يبرر",
|
| 397 |
+
"يوازن",
|
| 398 |
+
"يحكم",
|
| 399 |
+
"يدافع عن",
|
| 400 |
+
"يختار",
|
| 401 |
+
],
|
| 402 |
+
},
|
| 403 |
+
{
|
| 404 |
+
"level_name": "Create (الإبداع)",
|
| 405 |
+
"description": "دمج العناصر لتكوين كل متماسك أو وظيفي جديد وإعادة تنظيم العناصر في نمط أو بنية جديدة",
|
| 406 |
+
"verbs_examples": [
|
| 407 |
+
"يصمم",
|
| 408 |
+
"يبتكر",
|
| 409 |
+
"يطور",
|
| 410 |
+
"يؤلف",
|
| 411 |
+
"ينشئ",
|
| 412 |
+
"يخطط",
|
| 413 |
+
"يبني",
|
| 414 |
+
],
|
| 415 |
+
},
|
| 416 |
+
],
|
| 417 |
+
},
|
| 418 |
+
"Ability": {
|
| 419 |
+
"description": "المجال الوجداني/الانفعالي (Affective Domain): يتعلق بالمشاعر والاتجاهات والقيم والميول. يتدرج من مجرد الاستقبال السلبي إلى التبني الكامل للقيم وجعلها جزءاً من شخصية المتعلم.",
|
| 420 |
+
"levels": [
|
| 421 |
+
{
|
| 422 |
+
"level_name": "Reception (الاستقبال)",
|
| 423 |
+
"description": "الوعي والانتباه والاستعداد لاستقبال الظواهر والمثيرات",
|
| 424 |
+
"verbs_examples": ["ينتبه", "يختار", "يشعر", "يصغي", "يستقبل", "يلاحظ"],
|
| 425 |
+
},
|
| 426 |
+
{
|
| 427 |
+
"level_name": "Response (الاستجابة)",
|
| 428 |
+
"description": "المشاركة النشطة والتفاعل مع الظواهر والاستجابة لها",
|
| 429 |
+
"verbs_examples": [
|
| 430 |
+
"يستجيب",
|
| 431 |
+
"يشارك",
|
| 432 |
+
"يعاون",
|
| 433 |
+
"يمتثل",
|
| 434 |
+
"يتطوع",
|
| 435 |
+
"يساعد",
|
| 436 |
+
"يناقش",
|
| 437 |
+
],
|
| 438 |
+
},
|
| 439 |
+
{
|
| 440 |
+
"level_name": "Valuing (التقييم)",
|
| 441 |
+
"description": "إعطاء قيمة للأشياء والظواهر والسلوكيات والالتزام بها",
|
| 442 |
+
"verbs_examples": [
|
| 443 |
+
"يقدر",
|
| 444 |
+
"يحترم",
|
| 445 |
+
"يؤيد",
|
| 446 |
+
"يدعم",
|
| 447 |
+
"يظهر اقتناعاً",
|
| 448 |
+
"يعتز",
|
| 449 |
+
],
|
| 450 |
+
},
|
| 451 |
+
{
|
| 452 |
+
"level_name": "Organization (التنظيم)",
|
| 453 |
+
"description": "تنظيم القيم المختلفة وحل التناقضات بينها وبناء نظام قيمي متسق",
|
| 454 |
+
"verbs_examples": [
|
| 455 |
+
"ينظم",
|
| 456 |
+
"يقارن",
|
| 457 |
+
"يلتزم",
|
| 458 |
+
"يوازن",
|
| 459 |
+
"يرت��",
|
| 460 |
+
"يدمج",
|
| 461 |
+
"يوحد",
|
| 462 |
+
],
|
| 463 |
+
},
|
| 464 |
+
{
|
| 465 |
+
"level_name": "Characterization (التمييز/التشخيص)",
|
| 466 |
+
"description": "امتلاك نظام قيمي يتحكم في السلوك بشكل ثابت ومتسق ويصبح جزءاً من شخصية الفرد",
|
| 467 |
+
"verbs_examples": [
|
| 468 |
+
"يميز",
|
| 469 |
+
"يفضل",
|
| 470 |
+
"يتبنى",
|
| 471 |
+
"يلتزم",
|
| 472 |
+
"يمارس",
|
| 473 |
+
"يحل",
|
| 474 |
+
"يتصرف وفقاً لـ",
|
| 475 |
+
],
|
| 476 |
+
},
|
| 477 |
+
],
|
| 478 |
+
},
|
| 479 |
+
"Skills": {
|
| 480 |
+
"description": "المجال المهاري/النفسحركي (Psychomotor Domain): يركز على المهارات الحركية والجسدية التي تتطلب تنسيقاً بين العقل والعضلات. يتدرج من الملاحظة البسيطة إلى الإتقان والإبداع الحركي.",
|
| 481 |
+
"levels": [
|
| 482 |
+
{
|
| 483 |
+
"level_name": "Readiness (الاستعداد)",
|
| 484 |
+
"description": "الاستعداد الذهني والجسدي والانفعالي للقيام بالمهارة",
|
| 485 |
+
"verbs_examples": [
|
| 486 |
+
"يتهيأ",
|
| 487 |
+
"يستعد",
|
| 488 |
+
"يظهر رغبة",
|
| 489 |
+
"يبدي اهتماماً",
|
| 490 |
+
"يتخذ وضعية",
|
| 491 |
+
],
|
| 492 |
+
},
|
| 493 |
+
{
|
| 494 |
+
"level_name": "Guided Response/Imitation (الاستجابة الموجهة/التقليد)",
|
| 495 |
+
"description": "محاكاة وتقليد المهارة تحت الإشراف والتوجيه",
|
| 496 |
+
"verbs_examples": ["يقلد", "يحاكي", "يكرر", "يتبع", "يجرب", "يستجيب"],
|
| 497 |
+
},
|
| 498 |
+
{
|
| 499 |
+
"level_name": "Mechanism/Practice (الآلية/الممارسة)",
|
| 500 |
+
"description": "أداء المهارة بثقة ودقة دون الحاجة للتوجيه المستمر",
|
| 501 |
+
"verbs_examples": ["يمارس", "يطبق", "يؤدي", "ينفذ", "يكمل", "يعمل"],
|
| 502 |
+
},
|
| 503 |
+
{
|
| 504 |
+
"level_name": "Complex Overt Response (الاستجابة الظاهرة المعقدة)",
|
| 505 |
+
"description": "أداء المهارة بسلاسة وإتقان وبشكل تلقائي",
|
| 506 |
+
"verbs_examples": [
|
| 507 |
+
"يؤدي بسلاسة",
|
| 508 |
+
"يستخدم بانتظام",
|
| 509 |
+
"يتقن",
|
| 510 |
+
"ينجز بمهارة",
|
| 511 |
+
"يعمل بكفاءة",
|
| 512 |
+
],
|
| 513 |
+
},
|
| 514 |
+
{
|
| 515 |
+
"level_name": "Adaptation (التكيف)",
|
| 516 |
+
"description": "تعديل وتكييف المهارات لتناسب المواقف المختلفة",
|
| 517 |
+
"verbs_examples": [
|
| 518 |
+
"يعدل",
|
| 519 |
+
"يطور",
|
| 520 |
+
"يبدل",
|
| 521 |
+
"يكيف",
|
| 522 |
+
"يعيد تنظيم",
|
| 523 |
+
"يحسن",
|
| 524 |
+
],
|
| 525 |
+
},
|
| 526 |
+
{
|
| 527 |
+
"level_name": "Origination/Creativity (الإبداع)",
|
| 528 |
+
"description": "ابتكار حركات وأنماط مهارية جديدة وإبداعية",
|
| 529 |
+
"verbs_examples": [
|
| 530 |
+
"يبتكر",
|
| 531 |
+
"يصمم",
|
| 532 |
+
"يبدع",
|
| 533 |
+
"يخترع",
|
| 534 |
+
"يطور أسلوباً جديداً",
|
| 535 |
+
"يؤلف",
|
| 536 |
+
],
|
| 537 |
+
},
|
| 538 |
+
],
|
| 539 |
+
},
|
| 540 |
+
}
|
| 541 |
+
###############################################################
|
| 542 |
+
html_template = """
|
| 543 |
+
<!DOCTYPE html>
|
| 544 |
+
<html lang="ar" dir="rtl">
|
| 545 |
+
|
| 546 |
+
<head>
|
| 547 |
+
<meta charset="UTF-8">
|
| 548 |
+
<title>مرحلة التحليل</title>
|
| 549 |
+
<style>
|
| 550 |
+
body {
|
| 551 |
+
font-family: "Tahoma", sans-serif;
|
| 552 |
+
direction: rtl;
|
| 553 |
+
margin: 0;
|
| 554 |
+
padding: 0;
|
| 555 |
+
}
|
| 556 |
+
|
| 557 |
+
.header {
|
| 558 |
+
background: #c79810;
|
| 559 |
+
/* ذهبي */
|
| 560 |
+
color: white;
|
| 561 |
+
text-align: center;
|
| 562 |
+
font-weight: bold;
|
| 563 |
+
padding: 12px;
|
| 564 |
+
font-size: 20px;
|
| 565 |
+
}
|
| 566 |
+
|
| 567 |
+
.sub-header {
|
| 568 |
+
background: #000;
|
| 569 |
+
color: white;
|
| 570 |
+
text-align: center;
|
| 571 |
+
padding: 10px;
|
| 572 |
+
font-size: 16px;
|
| 573 |
+
font-weight: bold;
|
| 574 |
+
}
|
| 575 |
+
|
| 576 |
+
table {
|
| 577 |
+
width: 100%;
|
| 578 |
+
border-collapse: collapse;
|
| 579 |
+
}
|
| 580 |
+
|
| 581 |
+
td {
|
| 582 |
+
border: 1px solid #000;
|
| 583 |
+
padding: 8px 12px;
|
| 584 |
+
vertical-align: top;
|
| 585 |
+
line-height: 1.6;
|
| 586 |
+
}
|
| 587 |
+
|
| 588 |
+
.main-col {
|
| 589 |
+
background: #666;
|
| 590 |
+
color: white;
|
| 591 |
+
width: 20%;
|
| 592 |
+
font-weight: bold;
|
| 593 |
+
text-align: center;
|
| 594 |
+
}
|
| 595 |
+
|
| 596 |
+
.sub-col {
|
| 597 |
+
background: #e6e6e6;
|
| 598 |
+
width: 20%;
|
| 599 |
+
font-weight: bold;
|
| 600 |
+
text-align: right;
|
| 601 |
+
}
|
| 602 |
+
|
| 603 |
+
ul {
|
| 604 |
+
margin: 6px 0;
|
| 605 |
+
padding-right: 20px;
|
| 606 |
+
}
|
| 607 |
+
</style>
|
| 608 |
+
</head>
|
| 609 |
+
|
| 610 |
+
<body>
|
| 611 |
+
|
| 612 |
+
<div class="header">إدارة الوقت</div>
|
| 613 |
+
<div class="sub-header">مرحلة التحليل</div>
|
| 614 |
+
|
| 615 |
+
<table>
|
| 616 |
+
<!-- الهدف -->
|
| 617 |
+
<tr>
|
| 618 |
+
<td class="main-col">المتوقع تحقيقه (النهائي)</td>
|
| 619 |
+
<td colspan="2">
|
| 620 |
+
أن يتمكّن المتدرب من اكتساب مهارة إدارة وقته بفعالية، من خلال فهم المفهوم والأسس،
|
| 621 |
+
وتطبيق المهارات والتقنيات العملية، بما ينعكس على إنجاز أهدافه الشخصية والعملية بكفاءة عالية.
|
| 622 |
+
</td>
|
| 623 |
+
</tr>
|
| 624 |
+
|
| 625 |
+
<!-- الفئة المستهدفة -->
|
| 626 |
+
<tr>
|
| 627 |
+
<td class="main-col" rowspan="4">الفئة المستهدفة</td>
|
| 628 |
+
<td class="sub-col">أعمارهم</td>
|
| 629 |
+
<td>18 إلى 35 عامًا.</td>
|
| 630 |
+
</tr>
|
| 631 |
+
|
| 632 |
+
<tr>
|
| 633 |
+
<td class="sub-col">الخبرات السابقة</td>
|
| 634 |
+
<td>
|
| 635 |
+
<ul>
|
| 636 |
+
<li>ممارسة أعمال أو مهام تتطلب التخطيط أو التنظيم.</li>
|
| 637 |
+
<li>حضور أنشطة أو دورات سابقة في التنمية الذاتية أو المهارات الحياتية.</li>
|
| 638 |
+
<li>إلمام جزئي بأساسيات إدارة العمل أو الأنشطة التربوية.</li>
|
| 639 |
+
</ul>
|
| 640 |
+
</td>
|
| 641 |
+
</tr>
|
| 642 |
+
|
| 643 |
+
<tr>
|
| 644 |
+
<td class="sub-col">خصائص المتدربين</td>
|
| 645 |
+
<td>
|
| 646 |
+
<ul>
|
| 647 |
+
<li>امتلاك حصيلة لغوية جيدة مع قدرة على التعبير.</li>
|
| 648 |
+
<li>القدرة على التفكير التحليلي والمنطقي وحل المشكلات.</li>
|
| 649 |
+
<li>الرغبة في التفاعل مع المجموعات وتقدير العلاقات القائمة على الاحترام.</li>
|
| 650 |
+
<li>ميل قوي للاستقلالية في اتخاذ القرارات وحمل المسؤوليات.</li>
|
| 651 |
+
<li>ظهور ميول متزايدة بالذات والحاجة إلى التحكم في الانفعالات.</li>
|
| 652 |
+
<li>السعي لتطوير الهوية الذاتية والاجتماعية وتعزيز الثقة بالنفس.</li>
|
| 653 |
+
<li>تفضيل التعلم التفاعلي القائم على الأنشطة التطبيقية.</li>
|
| 654 |
+
</ul>
|
| 655 |
+
</td>
|
| 656 |
+
</tr>
|
| 657 |
+
|
| 658 |
+
<tr>
|
| 659 |
+
<td class="sub-col">احتياجات المتدربين</td>
|
| 660 |
+
<td>
|
| 661 |
+
<ul>
|
| 662 |
+
<li>تمييز أسباب ضياع الوقت الشخصي والتنظيمي.</li>
|
| 663 |
+
<li>تحقيق التوازن بين المهام والأهداف.</li>
|
| 664 |
+
<li>امتلاك أدوات عملية لتحديد الأولويات.</li>
|
| 665 |
+
<li>استخدام تقنيات جديدة أكثر كفاءة.</li>
|
| 666 |
+
<li>ضبط التوتر الناتج عن ضغوط المهام.</li>
|
| 667 |
+
<li>أساليب مجرَّبة ناجحة في استثمار الوقت.</li>
|
| 668 |
+
</ul>
|
| 669 |
+
</td>
|
| 670 |
+
</tr>
|
| 671 |
+
|
| 672 |
+
<!-- القيود -->
|
| 673 |
+
<tr>
|
| 674 |
+
<td class="main-col" rowspan="2">القيود</td>
|
| 675 |
+
<td class="sub-col">بالنسبة للمدرب</td>
|
| 676 |
+
<td>
|
| 677 |
+
<ul>
|
| 678 |
+
<li>صعوبة التعامل مع تفاوت الخلفيات المعرفية.</li>
|
| 679 |
+
<li>محدودية الوقت المخصص للأنشطة التدريبية.</li>
|
| 680 |
+
<li>حاجة إلى تكييف الأمثلة بما يناسب الجمهور.</li>
|
| 681 |
+
<li>صعوبة متابعة الأداء الفردي لجميع المتدربين.</li>
|
| 682 |
+
</ul>
|
| 683 |
+
</td>
|
| 684 |
+
</tr>
|
| 685 |
+
<tr>
|
| 686 |
+
<td class="sub-col">بالنسبة للمتدرب</td>
|
| 687 |
+
<td>
|
| 688 |
+
<ul>
|
| 689 |
+
<li>محدودية الخبرة السابقة في إدارة الوقت.</li>
|
| 690 |
+
<li>صعوبة الالتزام بجميع التمارين المقترحة.</li>
|
| 691 |
+
<li>التأثر بالضغوط الشخصية والاجتماعية.</li>
|
| 692 |
+
<li>مقاومة تغيي�� العادات السلبية القديمة.</li>
|
| 693 |
+
</ul>
|
| 694 |
+
</td>
|
| 695 |
+
</tr>
|
| 696 |
+
|
| 697 |
+
<!-- المدة الزمنية -->
|
| 698 |
+
<tr>
|
| 699 |
+
<td class="main-col">المدة الزمنية</td>
|
| 700 |
+
<td colspan="2">مدة الكورس محسوبة بعدد الأيام (اليوم = 4 ساعات).</td>
|
| 701 |
+
</tr>
|
| 702 |
+
|
| 703 |
+
<!-- جمع البيانات -->
|
| 704 |
+
<tr>
|
| 705 |
+
<td class="main-col">جمع البيانات وتحليلها</td>
|
| 706 |
+
<td colspan="2">
|
| 707 |
+
<ul>
|
| 708 |
+
<li>تحديد محاور الدورة التدريبية.</li>
|
| 709 |
+
<li>تحليل الاحتياجات التدريبية.</li>
|
| 710 |
+
<li>تحديد الفجوات المعرفية والمهارية.</li>
|
| 711 |
+
<li>تصميم أنشطة لمعالجة الفجوات.</li>
|
| 712 |
+
<li>تجريب الأنشطة وتقييمها.</li>
|
| 713 |
+
<li>تطوير الأنشطة وتحسينها.</li>
|
| 714 |
+
</ul>
|
| 715 |
+
</td>
|
| 716 |
+
</tr>
|
| 717 |
+
</table>
|
| 718 |
+
|
| 719 |
+
</body>
|
| 720 |
+
|
| 721 |
+
</html>
|
| 722 |
+
"""
|
| 723 |
+
|
| 724 |
+
|
| 725 |
+
##########################################################
|
| 726 |
+
# # This is an input For === Objectives Agent ===
|
| 727 |
+
# with open(os.path.join(output_dir, "curriculum_outline_final.json"), "r", encoding="utf-8") as f:
|
| 728 |
+
# outlines = json.load(f)
|
| 729 |
+
|
| 730 |
+
# # This is an input For === Outcomes Agent ===
|
| 731 |
+
# with open(
|
| 732 |
+
# os.path.join(output_dir, "step_analysis_2_objectives.json"),
|
| 733 |
+
# "r",
|
| 734 |
+
# encoding="utf-8",
|
| 735 |
+
# ) as f:
|
| 736 |
+
# objectives = json.load(f)
|
requirements.txt
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
crewai[tools]
|
| 2 |
+
tavily-python
|
| 3 |
+
scrapegraph-py
|
| 4 |
+
scrapegraphai
|
| 5 |
+
PyPDF2
|
| 6 |
+
reportlab
|
| 7 |
+
langchain_openai
|
| 8 |
+
litellm
|
| 9 |
+
openai
|
| 10 |
+
fastapi
|
| 11 |
+
crewai[anthropic]
|
| 12 |
+
crewai[google-genai]
|
| 13 |
+
langchain
|
| 14 |
+
langchain_core
|
| 15 |
+
langchain-community
|
routers/introduction_route.py
ADDED
|
@@ -0,0 +1,59 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from crewai import Crew, Process
|
| 3 |
+
import json
|
| 4 |
+
from fastapi import APIRouter, HTTPException, Depends
|
| 5 |
+
from agents.analysis_phase import (
|
| 6 |
+
intro_agent,
|
| 7 |
+
intro_task,
|
| 8 |
+
)
|
| 9 |
+
from modules import (
|
| 10 |
+
llm,
|
| 11 |
+
inputs,
|
| 12 |
+
)
|
| 13 |
+
from schemas import (
|
| 14 |
+
ValidatedCurriculumOutput,
|
| 15 |
+
LearningOutcomesOutput,
|
| 16 |
+
DNAMetadata,
|
| 17 |
+
OutlineInput,
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
router = APIRouter(prefix="/analysis", tags=["Introduction"])
|
| 22 |
+
|
| 23 |
+
# ------------------------------------
|
| 24 |
+
# === Agent 7:Training Generator ===
|
| 25 |
+
# ------------------------------------
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@router.post("/introduction")
|
| 29 |
+
def run_training(
|
| 30 |
+
data: OutlineInput,
|
| 31 |
+
outlines: ValidatedCurriculumOutput,
|
| 32 |
+
outcomes: LearningOutcomesOutput,
|
| 33 |
+
units:dict,
|
| 34 |
+
):
|
| 35 |
+
training_crew = Crew(
|
| 36 |
+
agents=[intro_agent],
|
| 37 |
+
tasks=[intro_task],
|
| 38 |
+
process=Process.sequential,
|
| 39 |
+
)
|
| 40 |
+
|
| 41 |
+
inputs = data.dict()
|
| 42 |
+
user_inputs = DNAMetadata(
|
| 43 |
+
topic=inputs["topic"],
|
| 44 |
+
domain=inputs["domain"],
|
| 45 |
+
content_type=inputs["content_type"],
|
| 46 |
+
audience=inputs["audience"],
|
| 47 |
+
material_type=inputs["material_type"],
|
| 48 |
+
).dict()
|
| 49 |
+
|
| 50 |
+
merged_inputs = {
|
| 51 |
+
**user_inputs,
|
| 52 |
+
"outlines": outlines.dict(),
|
| 53 |
+
"outcomes": outcomes.dict(),
|
| 54 |
+
"units": units,
|
| 55 |
+
}
|
| 56 |
+
result = training_crew.kickoff(inputs=merged_inputs)
|
| 57 |
+
print(result.json_dict)
|
| 58 |
+
|
| 59 |
+
return {"message": "Introduction Generated Well 🚀", "result": result}
|
routers/objective_route.py
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from crewai import Crew, Process
|
| 3 |
+
import json
|
| 4 |
+
from fastapi import APIRouter, HTTPException, Depends
|
| 5 |
+
from agents.analysis_phase import (
|
| 6 |
+
objectives_generator,
|
| 7 |
+
objectives_task,
|
| 8 |
+
)
|
| 9 |
+
from modules import (
|
| 10 |
+
llm_g,
|
| 11 |
+
inputs,
|
| 12 |
+
)
|
| 13 |
+
from schemas import (
|
| 14 |
+
ValidatedCurriculumOutput,
|
| 15 |
+
DNAMetadata,
|
| 16 |
+
OutlineInput,
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
router = APIRouter(prefix="/analysis", tags=["Objectives"])
|
| 21 |
+
|
| 22 |
+
|
| 23 |
+
# ------------------------------------
|
| 24 |
+
# === Agent 5:Objectives Generator ===
|
| 25 |
+
# ------------------------------------
|
| 26 |
+
|
| 27 |
+
|
| 28 |
+
@router.post("/objectives")
|
| 29 |
+
def run_objectives(
|
| 30 |
+
data: OutlineInput, outlines: ValidatedCurriculumOutput, units: dict
|
| 31 |
+
):
|
| 32 |
+
objectives_crew = Crew(
|
| 33 |
+
agents=[objectives_generator],
|
| 34 |
+
tasks=[objectives_task],
|
| 35 |
+
process=Process.sequential,
|
| 36 |
+
)
|
| 37 |
+
inputs = data.dict()
|
| 38 |
+
user_inputs = DNAMetadata(
|
| 39 |
+
topic=inputs["topic"],
|
| 40 |
+
domain=inputs["domain"],
|
| 41 |
+
content_type=inputs["content_type"],
|
| 42 |
+
audience=inputs["audience"],
|
| 43 |
+
material_type=inputs["material_type"],
|
| 44 |
+
).dict()
|
| 45 |
+
merged_inputs = {**user_inputs, "units":units,"outlines": outlines.dict()}
|
| 46 |
+
|
| 47 |
+
result = objectives_crew.kickoff(inputs=merged_inputs)
|
| 48 |
+
|
| 49 |
+
print(result.json_dict)
|
| 50 |
+
|
| 51 |
+
return {"message": "Objectives Generated Well 🚀", "result": result}
|
routers/outcome_route.py
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from crewai import Crew, Process
|
| 3 |
+
import json
|
| 4 |
+
from fastapi import APIRouter, HTTPException, Depends
|
| 5 |
+
from agents.analysis_phase import (
|
| 6 |
+
outcomes_generator,
|
| 7 |
+
outcomes_task,
|
| 8 |
+
)
|
| 9 |
+
from modules import (
|
| 10 |
+
llm_g,
|
| 11 |
+
inputs,
|
| 12 |
+
)
|
| 13 |
+
from schemas import (
|
| 14 |
+
ObjectivesOutput,
|
| 15 |
+
LearningObjectivesOutput,
|
| 16 |
+
DNAMetadata,
|
| 17 |
+
OutlineInput,
|
| 18 |
+
)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
router = APIRouter(prefix="/analysis", tags=["outcomes"])
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
# ------------------------------------
|
| 25 |
+
# === Agent 6:Outcomes Generator ===
|
| 26 |
+
# ------------------------------------
|
| 27 |
+
|
| 28 |
+
|
| 29 |
+
@router.post("/outcomes")
|
| 30 |
+
def run_outcomes(data: OutlineInput, objectives: LearningObjectivesOutput):
|
| 31 |
+
outcomes_crew = Crew(
|
| 32 |
+
agents=[outcomes_generator],
|
| 33 |
+
tasks=[outcomes_task],
|
| 34 |
+
process=Process.sequential,
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
inputs = data.dict()
|
| 38 |
+
user_inputs = DNAMetadata(
|
| 39 |
+
topic=inputs["topic"],
|
| 40 |
+
domain=inputs["domain"],
|
| 41 |
+
content_type=inputs["content_type"],
|
| 42 |
+
audience=inputs["audience"],
|
| 43 |
+
material_type=inputs["material_type"],
|
| 44 |
+
).dict()
|
| 45 |
+
merged_inputs = {**user_inputs, "objectives": objectives.dict()}
|
| 46 |
+
|
| 47 |
+
result = outcomes_crew.kickoff(inputs=merged_inputs)
|
| 48 |
+
print(result.json_dict)
|
| 49 |
+
|
| 50 |
+
return {"message": "Outcomes Generated Well 🚀", "result": result}
|
routers/outliner_route.py
ADDED
|
@@ -0,0 +1,66 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
from crewai import Crew, Process
|
| 3 |
+
import json
|
| 4 |
+
from fastapi import APIRouter, HTTPException, Depends
|
| 5 |
+
from agents.final_outliners import (
|
| 6 |
+
subtopics_generator_agent,
|
| 7 |
+
subtopics_generation_task,
|
| 8 |
+
validator_agent,
|
| 9 |
+
validation_task,
|
| 10 |
+
units_langchain1_agent,
|
| 11 |
+
)
|
| 12 |
+
from modules import (
|
| 13 |
+
llm_5m,
|
| 14 |
+
inputs,
|
| 15 |
+
)
|
| 16 |
+
from schemas import (
|
| 17 |
+
DNAMetadata,
|
| 18 |
+
OutlineInput,
|
| 19 |
+
)
|
| 20 |
+
|
| 21 |
+
|
| 22 |
+
router = APIRouter(prefix="/outliner", tags=["Outliner"])
|
| 23 |
+
|
| 24 |
+
|
| 25 |
+
# === Agent 1: Unit Generator ===
|
| 26 |
+
# === Agent 2: Axis Generator===
|
| 27 |
+
# === Agent 3: Validator ===
|
| 28 |
+
# === Agent 4: Final Reviewer (اختياري) ===
|
| 29 |
+
# -----------------------------------------------
|
| 30 |
+
@router.post("/run_outliner_agents")
|
| 31 |
+
def run_outliner_agents(data: OutlineInput):
|
| 32 |
+
outline_crew = Crew(
|
| 33 |
+
agents=[subtopics_generator_agent, validator_agent],
|
| 34 |
+
tasks=[subtopics_generation_task, validation_task],
|
| 35 |
+
process=Process.sequential,
|
| 36 |
+
)
|
| 37 |
+
|
| 38 |
+
inputs = data.dict()
|
| 39 |
+
user_inputs = DNAMetadata(
|
| 40 |
+
topic=inputs["topic"],
|
| 41 |
+
domain=inputs["domain"],
|
| 42 |
+
content_type=inputs["content_type"],
|
| 43 |
+
audience=inputs["audience"],
|
| 44 |
+
material_type=inputs["material_type"],
|
| 45 |
+
note=inputs["note"],
|
| 46 |
+
).dict()
|
| 47 |
+
|
| 48 |
+
units = units_langchain1_agent(
|
| 49 |
+
topic=inputs["topic"], units_number=inputs["units_number"]
|
| 50 |
+
)
|
| 51 |
+
|
| 52 |
+
merged_input = {
|
| 53 |
+
**user_inputs,
|
| 54 |
+
"units": units,
|
| 55 |
+
}
|
| 56 |
+
|
| 57 |
+
result = outline_crew.kickoff(inputs=merged_input)
|
| 58 |
+
|
| 59 |
+
print("units: ", units)
|
| 60 |
+
print("-" * 50)
|
| 61 |
+
print("final result: ", result.json_dict)
|
| 62 |
+
return {
|
| 63 |
+
"message": "Outliner Generators works well 🚀",
|
| 64 |
+
"result": result,
|
| 65 |
+
"units": units,
|
| 66 |
+
}
|
schemas/__init__.py
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from .analysis_schema import AnalysisOutput
|
| 2 |
+
from .dna_schema import DNAMetadata
|
| 3 |
+
from .extractor_schema import AllPartsOfContent, SinglePartOfContent, Section
|
| 4 |
+
from .keywoard_schema import SuggestedSearchQueries
|
| 5 |
+
from .objectives_schema import ObjectivesOutput, LearningObjectivesOutput
|
| 6 |
+
from .outcomes_schema import LearningOutcomesOutput
|
| 7 |
+
from .outliner_schema import (
|
| 8 |
+
Subtopic,
|
| 9 |
+
UnitWithAxes,
|
| 10 |
+
FullCurriculumStructure,
|
| 11 |
+
ValidatedAxis,
|
| 12 |
+
ValidatedUnit,
|
| 13 |
+
ValidatedCurriculumOutput,
|
| 14 |
+
validated_parser,
|
| 15 |
+
)
|
| 16 |
+
|
| 17 |
+
from .source_schema import AllResults, SingleResult
|
| 18 |
+
from .introduction_schema import IntroductionOutput
|
| 19 |
+
from .inputs_schema import OutlineInput
|
schemas/analysis_schema.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
# ====== Pydantic Model for Analysis Phase ======
|
| 5 |
+
class AnalysisOutput(BaseModel):
|
| 6 |
+
goal: str = Field(
|
| 7 |
+
...,
|
| 8 |
+
description="Overall training goal, must start with 'أن يتمكّن المتدرب من...'.",
|
| 9 |
+
)
|
| 10 |
+
target_audience: str = Field(
|
| 11 |
+
...,
|
| 12 |
+
description="The target audience group and their average age/professional profile.",
|
| 13 |
+
)
|
| 14 |
+
previous_experiences: List[str] = Field(
|
| 15 |
+
..., description="3–5 short noun-phrases reflecting prior experiences."
|
| 16 |
+
)
|
| 17 |
+
learner_characteristics: List[str] = Field(
|
| 18 |
+
..., description="Learner characteristics based on developmental dimensions."
|
| 19 |
+
)
|
| 20 |
+
training_needs: List[str] = Field(
|
| 21 |
+
...,
|
| 22 |
+
description="6 noun-phrases representing training needs extracted from course topics.",
|
| 23 |
+
)
|
| 24 |
+
constraints: Dict[str, List[str]] = Field(
|
| 25 |
+
...,
|
| 26 |
+
description="Constraints divided into {'trainer': [...], 'trainee': [...]}, 4 noun-phrases each.",
|
| 27 |
+
)
|
| 28 |
+
duration: str = Field(..., description="The duration of the course (days/hours).")
|
| 29 |
+
sources_of_analysis: List[str] = Field(
|
| 30 |
+
...,
|
| 31 |
+
description="Noun-phrases starting and ending with a مصدر, e.g., 'جمع البيانات وتحليلها'.",
|
| 32 |
+
)
|
schemas/dna_schema.py
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
# ========= 1. Parameters for DNA methodology + topic =========
|
| 6 |
+
class DNAMetadata(BaseModel):
|
| 7 |
+
topic: str = Field(
|
| 8 |
+
...,
|
| 9 |
+
title="The main topic to generate an outline for",
|
| 10 |
+
description="The specific subject or concept that the outline should focus on. Example: 'Time Management', 'Machine Learning Basics', 'Healthy Nutrition'",
|
| 11 |
+
)
|
| 12 |
+
|
| 13 |
+
domain: str = Field(
|
| 14 |
+
...,
|
| 15 |
+
title="Knowledge domain",
|
| 16 |
+
description="The broader field of knowledge or industry where the topic belongs. Example: IT, Engineering, Education, Healthcare, Business",
|
| 17 |
+
)
|
| 18 |
+
|
| 19 |
+
# content_type: Literal["Educational", "Awareness", "Training"] = Field(
|
| 20 |
+
|
| 21 |
+
content_type: str = Field(
|
| 22 |
+
...,
|
| 23 |
+
title="Type of content",
|
| 24 |
+
description=(
|
| 25 |
+
"Educational → for structured learning (e.g., lessons, modules)\n"
|
| 26 |
+
"Awareness → for informative/raising awareness purposes (e.g., campaigns, workshops)\n"
|
| 27 |
+
"Training → for skill development with step-by-step practice (e.g., hands-on, exercises)"
|
| 28 |
+
),
|
| 29 |
+
)
|
| 30 |
+
|
| 31 |
+
# audience: str = Field(
|
| 32 |
+
# ...,
|
| 33 |
+
# title="Target audience",
|
| 34 |
+
# description=(
|
| 35 |
+
# "The group of people intended to benefit from the material. Example:\n"
|
| 36 |
+
# "- Kids (age 6–12)\n"
|
| 37 |
+
# "- High School Students (teenagers)\n"
|
| 38 |
+
# "- University Students (academic level)\n"
|
| 39 |
+
# "- Professionals (working individuals)\n"
|
| 40 |
+
# "- General Public (all ages, non-technical)"
|
| 41 |
+
# )
|
| 42 |
+
# )
|
| 43 |
+
|
| 44 |
+
audience: str = Field(
|
| 45 |
+
...,
|
| 46 |
+
title="Target audience",
|
| 47 |
+
description=(
|
| 48 |
+
"The group of people intended to benefit from the material. Examples:\n"
|
| 49 |
+
"- Education (Teachers, Principals, Students, Faculty, Instructional Designers)\n"
|
| 50 |
+
"- Special Education (Special Needs Teachers, Speech Therapists, Psychologists, ABA Specialists, Children with Disabilities)\n"
|
| 51 |
+
"- Family & Child (Parents, Counselors, Social Workers, Children, Adolescents, Youth, Elderly)\n"
|
| 52 |
+
"- Women Empowerment (Mothers, Teenage Girls, Women Entrepreneurs, Researchers, Artists)\n"
|
| 53 |
+
"- Self-Development (Individuals seeking personal growth, Life Coaches, Students, Graduates, Employees)\n"
|
| 54 |
+
"- Training (Soft/Technical Skills Trainers, Training Designers, Training Institutes)\n"
|
| 55 |
+
"- Human Resources (HR Managers, Recruiters, Employee Relations, L&D Officers)\n"
|
| 56 |
+
"- Management & Leadership (CEOs, Directors, Team Leaders, Consultants, Entrepreneurs)\n"
|
| 57 |
+
"- Law (Lawyers, Judges, Prosecutors, Legal Advisors, Notaries)\n"
|
| 58 |
+
"- Public Relations & Media (PR Officers, Journalists, Broadcasters, Media Professionals)\n"
|
| 59 |
+
"- Marketing & Sales (Marketing Managers, Sales Representatives, Digital Marketing Specialists, Content Creators)\n"
|
| 60 |
+
"- Technology & IT (Software Developers, Data Scientists, AI Engineers, Cybersecurity Specialists)\n"
|
| 61 |
+
"- Languages & Translation (Translators, Interpreters, Language Teachers, Proofreaders)\n"
|
| 62 |
+
"- Medicine & Nutrition (Doctors, Nurses, Pharmacists, Nutritionists, Mental Health Specialists)\n"
|
| 63 |
+
"- Occupational Health & Safety (HSE Officers, Safety Inspectors, First Aid Trainers)\n"
|
| 64 |
+
"- Sports (Athletes, Coaches, Referees, Nutritionists, Physiotherapists)\n"
|
| 65 |
+
"- Arts & Fashion (Artists, Designers, Photographers, Art Directors)"
|
| 66 |
+
),
|
| 67 |
+
)
|
| 68 |
+
|
| 69 |
+
material_type: List[str] = Field(
|
| 70 |
+
...,
|
| 71 |
+
title="Nature of the scientific material",
|
| 72 |
+
description=(
|
| 73 |
+
"Defines the learning approach:\n"
|
| 74 |
+
"- Conceptual → focuses on theories, principles, and abstract knowledge.\n"
|
| 75 |
+
"- Procedural → step-by-step methods, instructions, or processes.\n"
|
| 76 |
+
"- Structural → frameworks, models, and organized structures.\n"
|
| 77 |
+
"- Personal → reflections, personal skills, and self-development aspects.\n"
|
| 78 |
+
"- Realistic → practical, case-based, real-world examples and applications."
|
| 79 |
+
),
|
| 80 |
+
)
|
| 81 |
+
|
| 82 |
+
note: Optional[str] = None
|
schemas/extractor_schema.py
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
class Section(BaseModel):
|
| 5 |
+
heading: str
|
| 6 |
+
text: str
|
| 7 |
+
|
| 8 |
+
class SinglePartOfContent(BaseModel):
|
| 9 |
+
page_url: str = Field(..., title="URL of the page containing the content")
|
| 10 |
+
title: str = Field(..., title="Title of the content")
|
| 11 |
+
sections: List[Section] = Field(..., title="Sections of the content")
|
| 12 |
+
img_url: List[str] = Field( title="URL of the image associated with the content")
|
| 13 |
+
video_url: List[str] = Field( title="URL of the video associated with the content")
|
| 14 |
+
audio_url: List[str] = Field( title="URL of the audio associated with the content")
|
| 15 |
+
pdf_url: List[str] = Field( title="URL of the pdf associated with the content")
|
| 16 |
+
agent_recommendation_rank: float = Field(..., title="Rank of the content as per the agent recommendation, (out of 5, Higher is Better) in the recommendation list ordering from the best to the worst")
|
| 17 |
+
agent_recommendation_notes: str = Field(..., title="A set of notes why would you recommend or not recommend this content to the company")
|
| 18 |
+
header: str = Field(..., title="the header this content belongs to")
|
| 19 |
+
sub_header: str = Field(..., title="the sub_header this content belongs to")
|
| 20 |
+
|
| 21 |
+
class AllPartsOfContent(BaseModel):
|
| 22 |
+
parts: List[SinglePartOfContent]
|
schemas/inputs_schema.py
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel
|
| 2 |
+
|
| 3 |
+
|
| 4 |
+
# Step 1️⃣: Create a Pydantic model for inputs
|
| 5 |
+
class OutlineInput(BaseModel):
|
| 6 |
+
topic: str
|
| 7 |
+
domain: str
|
| 8 |
+
content_type: str
|
| 9 |
+
audience: str
|
| 10 |
+
material_type: list
|
| 11 |
+
units_number: int
|
| 12 |
+
note: str
|
| 13 |
+
|
| 14 |
+
|
| 15 |
+
# {
|
| 16 |
+
# "topic": "إدارة الوقت",
|
| 17 |
+
# "domain": "Management",
|
| 18 |
+
# "content_type": "Educational",
|
| 19 |
+
# "audience": "kids",
|
| 20 |
+
# "material_type": ["Procedural", "Realistic", "Personal"],
|
| 21 |
+
# }
|
| 22 |
+
|
| 23 |
+
# {
|
| 24 |
+
# "topic": "(Design thinking) تقنيات التفكير التصميمي لحل المشكلات واتخاذ القرارات",
|
| 25 |
+
# "domain": "Management",
|
| 26 |
+
# "content_type": "تدريبي",
|
| 27 |
+
# "audience": "القادة والموظفون والإداريون",
|
| 28 |
+
# "material_type": ["مفاهمية", "هيكلية", "شخصية", "واقعية", "اجرائية"],
|
| 29 |
+
# }
|
schemas/introduction_schema.py
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class IntroductionOutput(BaseModel):
|
| 6 |
+
introduction: str = Field(
|
| 7 |
+
...,
|
| 8 |
+
title="Introduction",
|
| 9 |
+
description="engaging introduction to the training program content, max 300 words.",
|
| 10 |
+
)
|
schemas/keywoard_schema.py
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
no_keywords = 25
|
| 6 |
+
|
| 7 |
+
|
| 8 |
+
class SuggestedSearchQueries(BaseModel):
|
| 9 |
+
queries: List[str] = Field(
|
| 10 |
+
...,
|
| 11 |
+
title="List of suggested search queries",
|
| 12 |
+
min_items=1,
|
| 13 |
+
max_items=no_keywords,
|
| 14 |
+
)
|
schemas/objectives_schema.py
ADDED
|
@@ -0,0 +1,65 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
from typing import List
|
| 4 |
+
from pydantic import BaseModel, Field
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class Objective(BaseModel):
|
| 8 |
+
unit: str = Field(..., description="The title of the unit.")
|
| 9 |
+
unit_description: str = Field(..., description="A brief summary of the unit scope.")
|
| 10 |
+
subtopic: str = Field(..., description="The title of the subtopic (axis).")
|
| 11 |
+
module_description: str = Field(
|
| 12 |
+
..., description="A brief summary of what this subtopic covers."
|
| 13 |
+
)
|
| 14 |
+
level: str = Field(
|
| 15 |
+
..., description="Bloom's level assigned based on subtopic analysis."
|
| 16 |
+
)
|
| 17 |
+
verbs: List[str] = Field(
|
| 18 |
+
..., description="A list of verbs used to define the learning objective."
|
| 19 |
+
)
|
| 20 |
+
objective: str = Field(
|
| 21 |
+
...,
|
| 22 |
+
description="A measurable Arabic objective derived from the subtopic purpose.",
|
| 23 |
+
)
|
| 24 |
+
|
| 25 |
+
|
| 26 |
+
class ObjectivesOutput(BaseModel):
|
| 27 |
+
objectives: List[Objective] = Field(
|
| 28 |
+
...,
|
| 29 |
+
description="List of objectives including unit, subtopic, and measurable goals.",
|
| 30 |
+
)
|
| 31 |
+
|
| 32 |
+
from pydantic import BaseModel, Field
|
| 33 |
+
from typing import List, Dict, Literal, Optional
|
| 34 |
+
|
| 35 |
+
|
| 36 |
+
class LearningObjective(BaseModel):
|
| 37 |
+
"""Schema for a single learning objective"""
|
| 38 |
+
|
| 39 |
+
unit: str = Field(description="The title of the unit this objective belongs to")
|
| 40 |
+
unit_description: str = Field(
|
| 41 |
+
description="Brief summary of the unit scope and learning journey"
|
| 42 |
+
)
|
| 43 |
+
subtopic: str = Field(description="The title of the specific subtopic")
|
| 44 |
+
module_description: str = Field(
|
| 45 |
+
description="Brief summary of what this subtopic covers"
|
| 46 |
+
)
|
| 47 |
+
level: str = Field(
|
| 48 |
+
description="Bloom's Taxonomy level or learning domain level assigned based on subtopic analysis"
|
| 49 |
+
)
|
| 50 |
+
verbs: List[str] = Field(
|
| 51 |
+
description="List of three relevant Bloom's verbs suitable for the audience",
|
| 52 |
+
min_items=3,
|
| 53 |
+
max_items=3,
|
| 54 |
+
)
|
| 55 |
+
objective: str = Field(
|
| 56 |
+
description="One measurable learning objective in Arabic derived from the subtopic purpose"
|
| 57 |
+
)
|
| 58 |
+
|
| 59 |
+
|
| 60 |
+
class LearningObjectivesOutput(BaseModel):
|
| 61 |
+
"""Schema for the complete learning objectives output"""
|
| 62 |
+
|
| 63 |
+
objectives: List[LearningObjective] = Field(
|
| 64 |
+
description="Complete list of learning objectives for all subtopics in the curriculum"
|
| 65 |
+
)
|
schemas/outcomes_schema.py
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from typing import List
|
| 2 |
+
from pydantic import BaseModel, Field
|
| 3 |
+
|
| 4 |
+
|
| 5 |
+
class LearningOutcomeItem(BaseModel):
|
| 6 |
+
unit: str = Field(
|
| 7 |
+
...,
|
| 8 |
+
description="The title of the training unit for which the outcome is designed.",
|
| 9 |
+
)
|
| 10 |
+
unit_description: str = Field(
|
| 11 |
+
...,
|
| 12 |
+
description="A brief summary describing the scope and purpose of this unit.",
|
| 13 |
+
)
|
| 14 |
+
unit_outcome: str = Field(
|
| 15 |
+
...,
|
| 16 |
+
description=(
|
| 17 |
+
"One concise, measurable Arabic learning outcome derived from the unit description "
|
| 18 |
+
"and its subtopics and their purposes. The outcome should be written in مصدر form (infinitive noun), "
|
| 19 |
+
"be measurable, realistic, and aligned with Bloom’s taxonomy and DNA methodology."
|
| 20 |
+
),
|
| 21 |
+
)
|
| 22 |
+
|
| 23 |
+
|
| 24 |
+
class LearningOutcomesOutput(BaseModel):
|
| 25 |
+
outcomes: List[LearningOutcomeItem] = Field(
|
| 26 |
+
...,
|
| 27 |
+
description="A list of unit-level Arabic learning outcomes covering all units in the program.",
|
| 28 |
+
)
|
schemas/outliner_schema.py
ADDED
|
@@ -0,0 +1,207 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import os
|
| 2 |
+
import json
|
| 3 |
+
import requests
|
| 4 |
+
import time
|
| 5 |
+
import re
|
| 6 |
+
from pydantic import BaseModel, Field, ValidationError
|
| 7 |
+
from typing import List, Dict, Literal, Optional
|
| 8 |
+
from .dna_schema import DNAMetadata
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
################==NEW==################
|
| 12 |
+
class Subtopic(BaseModel):
|
| 13 |
+
"""
|
| 14 |
+
Represents a single subtopic within an educational unit.
|
| 15 |
+
|
| 16 |
+
Each subtopic embodies a progressive learning step that moves from
|
| 17 |
+
basic understanding toward higher-order thinking such as
|
| 18 |
+
application, analysis, or creative synthesis.
|
| 19 |
+
"""
|
| 20 |
+
|
| 21 |
+
subtopic_number: int = Field(
|
| 22 |
+
...,
|
| 23 |
+
title="Subtopic Number",
|
| 24 |
+
description="The sequential order of this subtopic within the unit.",
|
| 25 |
+
)
|
| 26 |
+
|
| 27 |
+
title: str = Field(
|
| 28 |
+
...,
|
| 29 |
+
title="Subtopic Title",
|
| 30 |
+
description=(
|
| 31 |
+
"The Arabic title of the subtopic inside the unit. "
|
| 32 |
+
"Each subtopic defines a distinct conceptual or cognitive step "
|
| 33 |
+
"that contributes to the overall unit progression."
|
| 34 |
+
),
|
| 35 |
+
)
|
| 36 |
+
|
| 37 |
+
purpose: str = Field(
|
| 38 |
+
...,
|
| 39 |
+
title="Subtopic Purpose",
|
| 40 |
+
description=(
|
| 41 |
+
"A concise statements describing the educational intent of this subtopic — "
|
| 42 |
+
"what learners should achieve cognitively (e.g., understanding, applying, analyzing, creating)."
|
| 43 |
+
),
|
| 44 |
+
)
|
| 45 |
+
|
| 46 |
+
|
| 47 |
+
############################################################################################################
|
| 48 |
+
class UnitWithAxes(BaseModel):
|
| 49 |
+
"""
|
| 50 |
+
Represents a curriculum unit that contains multiple learning subtopics.
|
| 51 |
+
|
| 52 |
+
Each unit defines a coherent topic focus and consists of number of subtopics,
|
| 53 |
+
each representing a structured subtopic or cognitive level that guides
|
| 54 |
+
the learner progressively from comprehension to advanced application.
|
| 55 |
+
"""
|
| 56 |
+
|
| 57 |
+
unit_number: int = Field(
|
| 58 |
+
...,
|
| 59 |
+
title="The sequential number of this unit within the overall curriculum (e.g., 1, 2, 3).",
|
| 60 |
+
)
|
| 61 |
+
|
| 62 |
+
title: str = Field(
|
| 63 |
+
...,
|
| 64 |
+
title="Unit Title",
|
| 65 |
+
description="The Arabic title or name of the educational unit, clearly representing its theme or purpose.",
|
| 66 |
+
)
|
| 67 |
+
|
| 68 |
+
focus: str = Field(
|
| 69 |
+
...,
|
| 70 |
+
title="Unit Focus",
|
| 71 |
+
description=(
|
| 72 |
+
"A concise overview highlighting the main concepts, skills, and learning outcomes "
|
| 73 |
+
"covered in this unit. It describes what learners should understand or achieve after completing it."
|
| 74 |
+
"It sets the intellectual direction for the included subtopics."
|
| 75 |
+
),
|
| 76 |
+
)
|
| 77 |
+
|
| 78 |
+
subtopics: List[Subtopic] = Field(
|
| 79 |
+
...,
|
| 80 |
+
title="Unit Subtopics",
|
| 81 |
+
description=(
|
| 82 |
+
"A list of coherent Arabic subtopics that make up the unit. "
|
| 83 |
+
"Each subtopic represents a progressive cognitive step — from foundational understanding "
|
| 84 |
+
"to creative synthesis — ensuring a balanced learning journey."
|
| 85 |
+
),
|
| 86 |
+
)
|
| 87 |
+
|
| 88 |
+
|
| 89 |
+
############################################################################################################
|
| 90 |
+
class FullCurriculumStructure(BaseModel):
|
| 91 |
+
"""
|
| 92 |
+
Represents the complete process of subtopic generation for an educational curriculum.
|
| 93 |
+
|
| 94 |
+
This model integrates educational metadata (via DNAMetadata), the conceptual hierarchy
|
| 95 |
+
(main and related concepts), and the pedagogical structure (units and subtopics).
|
| 96 |
+
It serves as the core structure for AI-driven generation, evaluation, and organization
|
| 97 |
+
of educational subtopics aligned with learner needs and content goals.
|
| 98 |
+
"""
|
| 99 |
+
|
| 100 |
+
Metadata: List["DNAMetadata"] = Field(
|
| 101 |
+
...,
|
| 102 |
+
title="List of DNA Metadata Objects",
|
| 103 |
+
description=(
|
| 104 |
+
"A list of DNAMetadata items, where each item represents a distinct topic or concept "
|
| 105 |
+
"along with its domain, audience, content type, and material nature.\n"
|
| 106 |
+
"This allows the agent to process multiple curriculum components or educational segments "
|
| 107 |
+
"within a single structured input."
|
| 108 |
+
),
|
| 109 |
+
)
|
| 110 |
+
|
| 111 |
+
main_concept: str = Field(
|
| 112 |
+
...,
|
| 113 |
+
title="Main Concept",
|
| 114 |
+
description=(
|
| 115 |
+
"The central or core idea around which the curriculum is built. "
|
| 116 |
+
"It defines the overarching theme that connects all units and topics together."
|
| 117 |
+
),
|
| 118 |
+
)
|
| 119 |
+
|
| 120 |
+
related_concepts: List[str] = Field(
|
| 121 |
+
...,
|
| 122 |
+
title="Related Concepts",
|
| 123 |
+
description=(
|
| 124 |
+
"A set of secondary or supporting ideas that complement or expand upon the main concept. "
|
| 125 |
+
"These help the agent establish conceptual links and subtopics within the curriculum."
|
| 126 |
+
),
|
| 127 |
+
)
|
| 128 |
+
|
| 129 |
+
units: List[UnitWithAxes] = Field(
|
| 130 |
+
...,
|
| 131 |
+
title="Units with Subtopics",
|
| 132 |
+
description=(
|
| 133 |
+
"A structured list of educational units. Each unit includes its title, "
|
| 134 |
+
"conceptual focus, and number of well-defined subtopics that progressively develop the learner’s understanding."
|
| 135 |
+
),
|
| 136 |
+
)
|
| 137 |
+
|
| 138 |
+
|
| 139 |
+
############################################################################################################
|
| 140 |
+
# ---- Custom Pydantic parser ----
|
| 141 |
+
class PydanticOutputParser:
|
| 142 |
+
"""Safely parses model output into a Pydantic schema."""
|
| 143 |
+
|
| 144 |
+
def __init__(self, pydantic_object):
|
| 145 |
+
self.model = pydantic_object
|
| 146 |
+
|
| 147 |
+
def parse(self, raw_output: str):
|
| 148 |
+
# Extract JSON substring between first { and last }
|
| 149 |
+
match = re.search(r"\{.*\}", raw_output, re.S)
|
| 150 |
+
if not match:
|
| 151 |
+
raise ValueError("❌ No JSON object found in model output.")
|
| 152 |
+
cleaned = match.group()
|
| 153 |
+
try:
|
| 154 |
+
return self.model.model_validate_json(cleaned)
|
| 155 |
+
except ValidationError as e:
|
| 156 |
+
raise ValueError(f"❌ JSON validation failed: {e}")
|
| 157 |
+
|
| 158 |
+
|
| 159 |
+
class ValidatedAxis(BaseModel):
|
| 160 |
+
"""Schema for a validated subtopics"""
|
| 161 |
+
|
| 162 |
+
subtopic_number: int = Field(
|
| 163 |
+
description="Sequential number of the subtopic within the unit", ge=1
|
| 164 |
+
)
|
| 165 |
+
|
| 166 |
+
title: str = Field(
|
| 167 |
+
description="The improved/validated subtopic title in Arabic (4-8 words, clear, focused)"
|
| 168 |
+
)
|
| 169 |
+
|
| 170 |
+
purpose: str = Field(
|
| 171 |
+
description="The subtopic purpose explaining its educational intent"
|
| 172 |
+
)
|
| 173 |
+
status: Literal["kept", "rephrased", "added", "removed"] = Field(
|
| 174 |
+
description="Validation status: 'kept' (unchanged), 'rephrased' (edited), 'added' (new), 'removed' (deleted/merged)"
|
| 175 |
+
)
|
| 176 |
+
|
| 177 |
+
|
| 178 |
+
class ValidatedUnit(BaseModel):
|
| 179 |
+
"""Schema for a validated educational unit"""
|
| 180 |
+
|
| 181 |
+
unit_number: int = Field(
|
| 182 |
+
description="Sequential number of the unit in the curriculum", ge=1
|
| 183 |
+
)
|
| 184 |
+
title: str = Field(description="The title of the unit in Arabic")
|
| 185 |
+
focus: str = Field(
|
| 186 |
+
description="Description of the unit's main educational focus and objectives"
|
| 187 |
+
)
|
| 188 |
+
axes: List[ValidatedAxis] = Field(
|
| 189 |
+
description="List of validated subtopics for this unit", min_items=1
|
| 190 |
+
)
|
| 191 |
+
|
| 192 |
+
|
| 193 |
+
class ValidatedCurriculumOutput(BaseModel):
|
| 194 |
+
"""Schema for the complete validated curriculum output"""
|
| 195 |
+
|
| 196 |
+
main_concept: str = Field(
|
| 197 |
+
description="The main concept or topic of the entire curriculum"
|
| 198 |
+
)
|
| 199 |
+
General_objectives_of_the_plan: List[str] = Field(
|
| 200 |
+
description="the main gaols of this educational plan"
|
| 201 |
+
)
|
| 202 |
+
validated_units: List[ValidatedUnit] = Field(
|
| 203 |
+
description="List of all validated educational units with their subtopics"
|
| 204 |
+
)
|
| 205 |
+
|
| 206 |
+
|
| 207 |
+
validated_parser = PydanticOutputParser(pydantic_object=ValidatedCurriculumOutput)
|
schemas/source_schema.py
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
from pydantic import BaseModel, Field
|
| 2 |
+
from typing import List, Dict, Literal, Optional
|
| 3 |
+
|
| 4 |
+
class SingleResult(BaseModel):
|
| 5 |
+
url: str
|
| 6 |
+
title: str
|
| 7 |
+
content: str
|
| 8 |
+
score: float
|
| 9 |
+
search_query: str
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class AllResults(BaseModel):
|
| 13 |
+
results: List[SingleResult]
|
tools/__init__.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# from .chapter_division import split_json
|
| 2 |
+
# from .scraper import web_scraping_tool
|
| 3 |
+
# from .tavily import search_engine_tool, is_recent
|
tools/chapter_division.py
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# import os
|
| 2 |
+
# import json
|
| 3 |
+
# import re
|
| 4 |
+
# from modules import outliner_dir, output_dir
|
| 5 |
+
|
| 6 |
+
# # ---------- Helper: sanitize file names ----------
|
| 7 |
+
# def safe_filename(name: str) -> str:
|
| 8 |
+
# return re.sub(r'[\\/*?:"<>|]', "", name).strip()
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
# # ---------- Main function ----------
|
| 12 |
+
# def split_json(input_file: str, output_dir: str):
|
| 13 |
+
# # Load JSON
|
| 14 |
+
# with open(input_file, "r", encoding="utf-8") as f:
|
| 15 |
+
# data = json.load(f)
|
| 16 |
+
|
| 17 |
+
# main_headings = data.get("main_headings", [])
|
| 18 |
+
# sub_headings = data.get("sub_headings", [])
|
| 19 |
+
# sub_sub_headings = data.get("sub_sub_headings", None)
|
| 20 |
+
|
| 21 |
+
# # Ensure output folder exists
|
| 22 |
+
# os.makedirs(output_dir, exist_ok=True)
|
| 23 |
+
|
| 24 |
+
# for idx, main in enumerate(main_headings):
|
| 25 |
+
# headers = sub_headings[idx] if idx < len(sub_headings) else []
|
| 26 |
+
|
| 27 |
+
# # لو فيه sub_sub_headings نجيبها، لو مش فيه نخليها null
|
| 28 |
+
# if sub_sub_headings and idx < len(sub_sub_headings):
|
| 29 |
+
# subs = sub_sub_headings[idx]
|
| 30 |
+
# else:
|
| 31 |
+
# subs = None
|
| 32 |
+
|
| 33 |
+
# section = {"headers": headers, "sub_sub_headings": subs}
|
| 34 |
+
|
| 35 |
+
# file_name = safe_filename(main) + ".json"
|
| 36 |
+
# file_path = os.path.join(output_dir, file_name)
|
| 37 |
+
|
| 38 |
+
# with open(file_path, "w", encoding="utf-8") as out_f:
|
| 39 |
+
# json.dump(section, out_f, ensure_ascii=False, indent=2)
|
| 40 |
+
|
| 41 |
+
# print(f"✅ Saved {file_name}")
|
| 42 |
+
|
| 43 |
+
|
| 44 |
+
# # ---------- Example usage ----------
|
| 45 |
+
# if __name__ == "__main__":
|
| 46 |
+
# split_json("/content/ai_agent_output/step_1_outlines.json", "output_sections")
|
tools/scraper.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# from crewai.tools import tool
|
| 2 |
+
# from scrapegraphai.graphs import SmartScraperGraph
|
| 3 |
+
# from schemas.extractor_schema import SinglePartOfContent
|
| 4 |
+
# from modules import llm
|
| 5 |
+
|
| 6 |
+
# @tool
|
| 7 |
+
# def web_scraping_tool(page_url: str):
|
| 8 |
+
# """
|
| 9 |
+
# An AI Tool to help an agent to scrape a web page using ScrapegraphAI.
|
| 10 |
+
# """
|
| 11 |
+
# try:
|
| 12 |
+
# graph = SmartScraperGraph(
|
| 13 |
+
# prompt=(
|
| 14 |
+
# "Extract ALL detailed content from the web page without summarizing. "
|
| 15 |
+
# "Preserve full paragraphs, lists, and section headers. "
|
| 16 |
+
# "Include associated media (images, videos, audios, pdfs). "
|
| 17 |
+
# "Fit everything into this schema:\n"
|
| 18 |
+
# "```json\n" + SinglePartOfContent.schema_json() + "\n```"
|
| 19 |
+
# ),
|
| 20 |
+
# source=page_url,
|
| 21 |
+
# llm=llm,
|
| 22 |
+
# )
|
| 23 |
+
|
| 24 |
+
# details = graph.run()
|
| 25 |
+
|
| 26 |
+
# return {
|
| 27 |
+
# "page_url": page_url,
|
| 28 |
+
# "details": details,
|
| 29 |
+
# }
|
| 30 |
+
|
| 31 |
+
# except Exception as e:
|
| 32 |
+
# raise RuntimeError(f"Scraping failed for {page_url}: {str(e)}")
|
tools/tavily.py
ADDED
|
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# import os
|
| 2 |
+
# from tavily import TavilyClient
|
| 3 |
+
# from crewai.tools import tool
|
| 4 |
+
# from modules import TRUSTED_SITES
|
| 5 |
+
|
| 6 |
+
# search_tool = TavilyClient(api_key=os.environ["TAVILY_API_KEY"])
|
| 7 |
+
|
| 8 |
+
|
| 9 |
+
# def is_recent(result, min_year=2021):
|
| 10 |
+
# """Validate result date is >= min_year if available."""
|
| 11 |
+
# pub_date = result.get("published_date")
|
| 12 |
+
# if not pub_date:
|
| 13 |
+
# return False # skip if no date
|
| 14 |
+
# try:
|
| 15 |
+
# year = int(pub_date.split("-")[0])
|
| 16 |
+
# return year >= min_year
|
| 17 |
+
# except Exception:
|
| 18 |
+
# return False
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
# @tool
|
| 22 |
+
# def search_engine_tool(query: str):
|
| 23 |
+
# """Execute a focused web search for the given query.
|
| 24 |
+
|
| 25 |
+
# - Prioritize **scholarly resources** (academic papers, books, journals, trusted educational sites).
|
| 26 |
+
# - Filters results to only those published/updated >= 2021.
|
| 27 |
+
# - Include **Arabic sources** when contextually relevant, but prioritize **English academic sources**.
|
| 28 |
+
# - Retrieve only **diverse and high-quality** results (avoid spam, low-quality blogs, or purely commercial pages).
|
| 29 |
+
# - For each result, ensure useful metadata is returned:
|
| 30 |
+
# * url
|
| 31 |
+
# * title
|
| 32 |
+
# * short content/summary
|
| 33 |
+
# * relevance score
|
| 34 |
+
# - Use a maximum of 5 results per query to keep output precise and useful.
|
| 35 |
+
# """
|
| 36 |
+
# # Step 1: Normal Tavily search
|
| 37 |
+
# # tavily_results = search_tool.search(query)
|
| 38 |
+
|
| 39 |
+
# site_query = f"{query} after:2020"
|
| 40 |
+
# tavily_results = search_tool.search(query=site_query, max_results=10)
|
| 41 |
+
# # Step 2: Force search inside trusted domains
|
| 42 |
+
# trusted_results = []
|
| 43 |
+
# for site in TRUSTED_SITES:
|
| 44 |
+
# site_query = f"site:{site} {query}"
|
| 45 |
+
# try:
|
| 46 |
+
# res = search_tool.search(site_query)
|
| 47 |
+
# if res and "results" in res:
|
| 48 |
+
# trusted_results.extend(res["results"])
|
| 49 |
+
# except Exception as e:
|
| 50 |
+
# print(f"Skipping {site}: {e}")
|
| 51 |
+
|
| 52 |
+
# # Step 3: Merge + deduplicate
|
| 53 |
+
# all_results = tavily_results.get("results", []) + trusted_results
|
| 54 |
+
# seen = set()
|
| 55 |
+
# filtered = []
|
| 56 |
+
# for r in all_results:
|
| 57 |
+
# if r["url"] not in seen:
|
| 58 |
+
# seen.add(r["url"])
|
| 59 |
+
# filtered.append(r)
|
| 60 |
+
|
| 61 |
+
# # Step 4: Limit to 5 best results
|
| 62 |
+
# final_results = sorted(filtered, key=lambda x: x.get("score", 0), reverse=True)[:5]
|
| 63 |
+
|
| 64 |
+
# return {"results": final_results}
|