Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
A
AI Tutor
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Salma Mohammed Hamed
AI Tutor
Commits
3556e8ce
Commit
3556e8ce
authored
Sep 17, 2025
by
SalmaMohammedHamedMustafa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Socratic Questioning v0
parent
afcd284e
Changes
2
Show whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
153 additions
and
0 deletions
+153
-0
agent_service.py
self_hosted_env/voice_agent/services/agent_service.py
+25
-0
pedagogy_service.py
self_hosted_env/voice_agent/services/pedagogy_service.py
+128
-0
No files found.
self_hosted_env/voice_agent/services/agent_service.py
View file @
3556e8ce
...
@@ -9,6 +9,7 @@ from core import StudentNationality, Models
...
@@ -9,6 +9,7 @@ from core import StudentNationality, Models
from
services.pgvector_service
import
PGVectorService
from
services.pgvector_service
import
PGVectorService
from
services.openai_service
import
OpenAIService
from
services.openai_service
import
OpenAIService
from
services.chat_database_service
import
ChatDatabaseService
from
services.chat_database_service
import
ChatDatabaseService
from
services.pedagogy_service
import
PedagogyService
logger
=
logging
.
getLogger
(
__name__
)
logger
=
logging
.
getLogger
(
__name__
)
...
@@ -77,6 +78,10 @@ class AgentService:
...
@@ -77,6 +78,10 @@ class AgentService:
self
.
db_service
=
ChatDatabaseService
()
self
.
db_service
=
ChatDatabaseService
()
self
.
pgvector
=
PGVectorService
()
if
use_pgvector
else
None
self
.
pgvector
=
PGVectorService
()
if
use_pgvector
else
None
# Initialize pedagogy service for Socratic questioning
self
.
pedagogy_service
=
PedagogyService
()
logger
.
info
(
"AgentService initialized with PedagogyService for Socratic questioning"
)
def
is_available
(
self
)
->
bool
:
def
is_available
(
self
)
->
bool
:
return
self
.
client
is
not
None
return
self
.
client
is
not
None
...
@@ -161,6 +166,17 @@ class AgentService:
...
@@ -161,6 +166,17 @@ class AgentService:
formatted_base_prompt
=
base_system_prompt
.
format
(
student_name
=
student_name
)
formatted_base_prompt
=
base_system_prompt
.
format
(
student_name
=
student_name
)
subject_specific_prompt
=
f
"{formatted_base_prompt}
\n\n
إنت بتدرّس مادة {subject} للطفل {student_name}."
subject_specific_prompt
=
f
"{formatted_base_prompt}
\n\n
إنت بتدرّس مادة {subject} للطفل {student_name}."
# Add Socratic questioning instructions if applicable (grades 4-6)
socratic_instructions
=
self
.
pedagogy_service
.
get_socratic_instructions
(
student_info
[
'grade'
],
student_info
[
'nationality'
]
)
if
socratic_instructions
:
subject_specific_prompt
+=
f
"
\n\n
{socratic_instructions}"
logger
.
info
(
f
"Added Socratic questioning instructions for grade {student_info['grade']}, nationality: {student_info['nationality']}"
)
else
:
logger
.
debug
(
f
"No Socratic instructions for grade {student_info['grade']}"
)
logger
.
info
(
f
"Using nationality: {nationality}, subject: {subject}, and student name: {student_name} for student: {student_id}"
)
logger
.
info
(
f
"Using nationality: {nationality}, subject: {subject}, and student name: {student_name} for student: {student_id}"
)
# Prepare messages
# Prepare messages
...
@@ -287,6 +303,15 @@ class AgentService:
...
@@ -287,6 +303,15 @@ class AgentService:
formatted_base_prompt
=
base_system_prompt
.
format
(
student_name
=
student_name
)
formatted_base_prompt
=
base_system_prompt
.
format
(
student_name
=
student_name
)
subject_specific_prompt
=
f
"{formatted_base_prompt}
\n\n
إنت بتدرّس مادة {subject} للطفل {student_name}."
subject_specific_prompt
=
f
"{formatted_base_prompt}
\n\n
إنت بتدرّس مادة {subject} للطفل {student_name}."
# Add Socratic questioning instructions if applicable
socratic_instructions
=
self
.
pedagogy_service
.
get_socratic_instructions
(
student_info
[
'grade'
],
student_info
[
'nationality'
]
)
if
socratic_instructions
:
subject_specific_prompt
+=
f
"
\n\n
{socratic_instructions}"
logger
.
info
(
f
"Added Socratic instructions when updating subject context for grade {student_info['grade']}"
)
self
.
add_message_to_history
(
student_id
,
subject_specific_prompt
,
"system"
)
self
.
add_message_to_history
(
student_id
,
subject_specific_prompt
,
"system"
)
logger
.
info
(
f
"Updated subject context to {subject} for student {student_id} ({student_name})"
)
logger
.
info
(
f
"Updated subject context to {subject} for student {student_id} ({student_name})"
)
...
...
self_hosted_env/voice_agent/services/pedagogy_service.py
0 → 100644
View file @
3556e8ce
import
logging
from
typing
import
Dict
,
List
from
enum
import
Enum
logger
=
logging
.
getLogger
(
__name__
)
class
QuestionType
(
Enum
):
CLARIFICATION
=
"clarification"
APPLICATION
=
"application"
REFLECTION
=
"reflection"
class
PedagogyService
:
"""Service class for managing pedagogical strategies for elementary students (grades 4-6)"""
def
__init__
(
self
):
# Egyptian Arabic Socratic Question Libraries
self
.
egyptian_questions
=
{
QuestionType
.
CLARIFICATION
:
[
"تقصد إيه بالكلمة دي في المثال؟"
,
"ممكن تشرح بكلمة أبسط؟"
,
"إيه معنى المصطلح دا هنا؟"
,
"تحب أشرحها بجملة تانية؟"
,
"فهمت كدا ولا تحب أوضح أكتر؟"
],
QuestionType
.
APPLICATION
:
[
"تفتكر ينفع نفس الفكرة في البيت أو المدرسة؟"
,
"ممكن تقوللي موقف حصل معاك شبه دا؟"
,
"إزاي ممكن نستعمل دا في حياتنا اليومية؟"
,
"تفتكر لو كنا في الصحرا كنا نعمل إيه عشان نتأقلم؟"
],
QuestionType
.
REFLECTION
:
[
"ليه الكائن دا محتاج الجزء دا من جسمه عشان يعيش؟"
,
"إزاي نتاكد إن المعلومة دي صح؟"
,
"إيه السبب اللي يخلي دا يحصل؟"
,
"تفتكر فيه حيوان تاني متأقلم أحسن للصحرا؟"
,
"إيه اللي ممكن يحصل لو الظروف اتغيّرت؟"
]
}
# Saudi Arabic Socratic Question Libraries
self
.
saudi_questions
=
{
QuestionType
.
CLARIFICATION
:
[
"وش تقصد بالكلمة هذي في الشرح؟"
,
"تقدر تقولها بكلمة أبسط؟"
,
"وش معنى المصطلح هنا؟"
,
"تحب أقولها بجملة ثانية؟"
,
"فهمت كذا أو تحتاج أوضح أكثر؟"
],
QuestionType
.
APPLICATION
:
[
"تظن ممكن نستخدم الفكرة هذي في البيت أو المدرسة؟"
,
"صار معك موقف يشبه كذا؟"
,
"وين ممكن نشوف الشي هذا في حياتنا اليومية؟"
,
"لو كنا في الصحراء وش ممكن نسوي عشان نتأقلم؟"
],
QuestionType
.
REFLECTION
:
[
"ليش الحيوان يعتمد على هالجزء من جسمه عشان يعيش؟"
,
"كيف نتاكد إن الجواب صحيح؟"
,
"وش السبب اللي يخلي هذا يصير؟"
,
"تظن فيه حيوان متأقلم أكثر للصحرا؟"
,
"وش اللي ممكن يصير لو تغيرت الظروف؟"
]
}
logger
.
info
(
"PedagogyService initialized with Socratic questioning libraries"
)
def
_get_question_library
(
self
,
nationality
:
str
)
->
Dict
[
QuestionType
,
List
[
str
]]:
"""Get the appropriate question library based on nationality"""
nationality_lower
=
nationality
.
lower
()
.
strip
()
if
nationality_lower
==
'saudi'
:
return
self
.
saudi_questions
elif
nationality_lower
==
'egyptian'
:
return
self
.
egyptian_questions
else
:
# Default to Egyptian if nationality is not recognized
logger
.
warning
(
f
"Unknown nationality '{nationality}', defaulting to Egyptian question library"
)
return
self
.
egyptian_questions
def
_format_questions_for_prompt
(
self
,
questions
:
Dict
[
QuestionType
,
List
[
str
]])
->
str
:
"""Format question libraries for inclusion in system prompt"""
formatted_questions
=
[]
clarification_list
=
", "
.
join
([
f
'"{q}"'
for
q
in
questions
[
QuestionType
.
CLARIFICATION
]])
formatted_questions
.
append
(
f
"- Clarification: [{clarification_list}]"
)
application_list
=
", "
.
join
([
f
'"{q}"'
for
q
in
questions
[
QuestionType
.
APPLICATION
]])
formatted_questions
.
append
(
f
"- Application: [{application_list}]"
)
reflection_list
=
", "
.
join
([
f
'"{q}"'
for
q
in
questions
[
QuestionType
.
REFLECTION
]])
formatted_questions
.
append
(
f
"- Reflection: [{reflection_list}]"
)
return
"
\n
"
.
join
(
formatted_questions
)
def
get_socratic_instructions
(
self
,
grade
:
int
,
nationality
:
str
)
->
str
:
"""Get Socratic questioning instructions for the system prompt"""
if
grade
not
in
[
4
,
5
,
6
]:
logger
.
debug
(
f
"Grade {grade} not in target range (4-6), skipping Socratic instructions"
)
return
""
questions
=
self
.
_get_question_library
(
nationality
)
formatted_questions
=
self
.
_format_questions_for_prompt
(
questions
)
if
nationality
.
lower
()
.
strip
()
==
'saudi'
:
instruction_text
=
f
"""بعد ما تشرح الفكرة للطفل، قيّم إذا يحتاج يتعمّق أكثر:
- لو الشرح كافي ومفهوم → لا تضيف أي سؤال.
- لو تشوف الطفل يستفيد من تفكير أو مثال إضافي → اختر سؤال واحد فقط من القائمة تحت.
ممكن تحط السؤال في النص أو في الآخر حسب ما يكون طبيعي.
الأسئلة الممكنة:
{formatted_questions}"""
else
:
# Egyptian or default
instruction_text
=
f
"""بعد ما تشرح الفكرة للطفل، فكّر هل محتاج يتعمّق أكتر:
- لو الشرح واضح وكافي → خلّص من غير أي سؤال.
- لو هيفيده تفكير أو مثال زيادة → اختار سؤال واحد بس من اللي تحت.
ممكن تحط السؤال في النص أو في الآخر، حسب ما يبان طبيعي.
الأسئلة الممكنة:
{formatted_questions}"""
logger
.
info
(
f
"Generated Socratic instructions for grade {grade}, nationality: {nationality}"
)
return
instruction_text
def
get_available_question_types
(
self
)
->
List
[
str
]:
return
[
qtype
.
value
for
qtype
in
QuestionType
]
def
get_questions_by_type
(
self
,
nationality
:
str
,
question_type
:
QuestionType
)
->
List
[
str
]:
questions
=
self
.
_get_question_library
(
nationality
)
return
questions
.
get
(
question_type
,
[])
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment