ziadsameh32 commited on
Commit
24a01ba
·
0 Parent(s):

v3 initial

Browse files
Files changed (49) hide show
  1. .gitignore +6 -0
  2. Dockerfile +21 -0
  3. README.md +10 -0
  4. agents/analysis_phase/Introduction.py +111 -0
  5. agents/analysis_phase/__init__.py +10 -0
  6. agents/analysis_phase/analysis.py +99 -0
  7. agents/analysis_phase/analysis_report.py +61 -0
  8. agents/analysis_phase/objectives.py +287 -0
  9. agents/analysis_phase/outcomes.py +305 -0
  10. agents/analysis_phase/outliner.py +97 -0
  11. agents/design_phase/__init__.py +3 -0
  12. agents/design_phase/extractor.py +75 -0
  13. agents/design_phase/keywoard_researcher.py +50 -0
  14. agents/design_phase/source_finder.py +69 -0
  15. agents/final_outliners/__init__.py +4 -0
  16. agents/final_outliners/subtopics_generator.py +129 -0
  17. agents/final_outliners/units_langchain.py +67 -0
  18. agents/final_outliners/units_langchain_1v.py +58 -0
  19. agents/final_outliners/validator.py +139 -0
  20. agents/outliner_phase/Deep_Semantic_Topics_Generator_1.py +118 -0
  21. agents/outliner_phase/__init__.py +4 -0
  22. agents/outliner_phase/module_organizer_3.py +46 -0
  23. agents/outliner_phase/review_agent_4.py +35 -0
  24. agents/outliner_phase/topic_expander_2.py +43 -0
  25. app.py +60 -0
  26. modules/__init__.py +28 -0
  27. modules/directory.py +12 -0
  28. modules/env.py +73 -0
  29. modules/inputs.py +736 -0
  30. requirements.txt +15 -0
  31. routers/introduction_route.py +59 -0
  32. routers/objective_route.py +51 -0
  33. routers/outcome_route.py +50 -0
  34. routers/outliner_route.py +66 -0
  35. schemas/__init__.py +19 -0
  36. schemas/analysis_schema.py +32 -0
  37. schemas/dna_schema.py +82 -0
  38. schemas/extractor_schema.py +22 -0
  39. schemas/inputs_schema.py +29 -0
  40. schemas/introduction_schema.py +10 -0
  41. schemas/keywoard_schema.py +14 -0
  42. schemas/objectives_schema.py +65 -0
  43. schemas/outcomes_schema.py +28 -0
  44. schemas/outliner_schema.py +207 -0
  45. schemas/source_schema.py +13 -0
  46. tools/__init__.py +3 -0
  47. tools/chapter_division.py +46 -0
  48. tools/scraper.py +32 -0
  49. 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}