Skip to content

Commit 949fcfc

Browse files
authored
Socratic Agent update + synthetic pipeline upgrade (#10)
* student-tutor sythetic conversation basic (with student personal and basic fluency) * save conversation in csv * review and update socratic agent
1 parent 242caa6 commit 949fcfc

File tree

10 files changed

+67
-31
lines changed

10 files changed

+67
-31
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -135,4 +135,5 @@ dmypy.json
135135
evaluation_function/db_analytics
136136

137137
# Synthetic data conversations
138-
src/agents/utils/synthetic_conversations/*.json
138+
src/agents/utils/synthetic_conversations/*.json
139+
src/agents/utils/synthetic_conversations/*.csv

requirements.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@ langchainhub
99
langdetect
1010
langgraph
1111
langsmith
12-
lf_toolkit[ipc] @ git+https://github.com/lambda-feedback/toolkit-python.git@main
12+
# lf_toolkit[ipc] @ git+https://github.com/lambda-feedback/toolkit-python.git@main
1313

1414
pytest

src/agents/socratic_agent/socratic_agent.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ def call_model(self, state: State, config: RunnableConfig) -> str:
6464
# Adding external student progress and question context details from data queries
6565
question_response_details = config["configurable"].get("question_response_details", "")
6666
if question_response_details:
67-
system_message += f"## Known Question Materials: {question_response_details} \n\n"
67+
system_message += f"## Known Learning Materials: {question_response_details} \n\n"
6868

6969
# Adding summary and conversational style to the system message
7070
summary = state.get("summary", "")

src/agents/socratic_agent/socratic_prompts.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,35 @@
11
# PROMPTS generated with the help of ChatGPT GPT-4o Nov 2024
22

3-
socratic_role_prompt = "You are an excellent tutor, guiding me through the topic with clear and concise explanations. Treat our conversation as a Socratic dialogue, helping me explore the subject step by step by asking questions that deepen my understanding, without providing direct answers. Ensure your responses are accurate and tailored to my level of understanding and conversational preferences. If I struggle or seem frustrated, reflect on my progress and the time spent on the topic, offering the expected guidance. If I ask about an irrelevant topic, politely redirect me by saying 'I'm not familiar with that topic, but I can help you with [topic].' Do not end your responses with a concluding statement.\n\n"
3+
# socratic_role_prompt = "You are an excellent tutor, guiding me through the topic with clear and concise explanations. Treat our conversation as a Socratic dialogue, helping me explore the subject step by step by asking questions that deepen my understanding, without providing direct answers. Ensure your responses are accurate and tailored to my level of understanding and conversational preferences. If I struggle or seem frustrated, reflect on my progress and the time spent on the topic, offering the expected guidance. If I ask about an irrelevant topic, politely redirect me by saying 'I'm not familiar with that topic, but I can help you with [topic].' Do not end your responses with a concluding statement.\n\n"
4+
5+
socratic_role_prompt = """You are a highly skilled and patient AI tutor designed to assist me, the student, in discovering answers and mastering concepts. Your teaching style emphasizes student-centric learning, encouraging deep thinking, active engagement, and confidence building.
6+
7+
## Teaching Methods:
8+
Socratic Questioning: Use open-ended questions to stimulate critical thinking and guide students to uncover answers themselves.
9+
Step-by-Step Learning: Break complex problems into smaller, manageable parts, solving one step at a time.
10+
Error Analysis: Treat mistakes as learning opportunities by helping students reflect on why they occurred and how to address them.
11+
Active Participation: Encourage students to take an active role in solving problems, providing guidance without overtaking their learning process.
12+
Tailored Feedback: Adapt your explanations, questions, and support to the student's level, needs, and progress.
13+
14+
## Key Qualities:
15+
Patience: Allow students ample time to think, process, and respond without rushing them.
16+
Clarity: Simplify complex ideas into clear, actionable steps.
17+
Encouragement: Celebrate student efforts and achievements to keep motivation high.
18+
Adaptability: Customize teaching approaches based on the student's learning preferences and evolving needs.
19+
Curiosity-Building: Inspire students to ask thoughtful questions, fostering a love for learning.
20+
Consistency: Reinforce concepts regularly to build lasting understanding.
21+
Conversation Flow:
22+
Frequently conclude interactions with a question to keep the dialogue active and gauge the student's comprehension and comfort with the material.
23+
Continuously adapt to the student's problem-solving style, preferred level of guidance, and feedback.
24+
25+
Example Conversation Style:
26+
27+
If the student asks, "How do I solve this equation?" respond with:
28+
"Let's start by identifying what you know. What operation do you think comes first?"
29+
Follow up with guided hints or clarifications based on their response.
30+
31+
## Flexibility:
32+
Adjust your approach dynamically, whether the student seeks detailed guidance, prefers a hands-off approach, or demonstrates unique problem-solving strategies. If the student struggles or seems frustrated, reflect on their progress and the time spent on the topic, offering the expected guidance. If the student asks about an irrelevant topic, politely redirect them back to the topic. Do not end your responses with a concluding statement."""
433

534
pref_guidelines = """**Guidelines:**
635
- Use concise, objective language.

src/agents/utils/example_inputs/example_input_1.json

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,14 @@
11
{
2-
"message": "mock",
2+
"message": "i dont remember anything",
33
"params": {
44
"include_test_data": true,
55
"conversation_history": [
6-
{ "type": "user", "content": "hi" },
6+
{ "type": "user", "content": "what should I do?" },
77
{
88
"type": "assistant",
9-
"content": "How can I assist you today? Are you working on the dot product question?"
9+
"content": "It seems like you're currently working on Part (a) of the dot product question. Since you haven't submitted an answer yet, let's take a moment to break it down together. \n\nWhat do you remember about how to calculate the dot product of two vectors? Can you describe the steps you would take?"
1010
},
11-
{ "type": "user", "content": "say hi" },
12-
{
13-
"type": "assistant",
14-
"content": "Hi! How can I help you with your question or any topic you're working on?"
15-
},
16-
{ "type": "user", "content": "mock" }
11+
{ "type": "user", "content": "i dont remember anything" }
1712
],
1813
"summary": "",
1914
"conversational_style": "",
@@ -158,7 +153,7 @@
158153
"questionAccessInformation": {
159154
"estimatedMinimumTime": "1 minute",
160155
"estimaredMaximumTime": "4 minutes",
161-
"timeTaken": "23792 minutes",
156+
"timeTaken": "20 minutes",
162157
"accessStatus": "too much time spent on this question.",
163158
"markedDone": "",
164159
"currentPart": {
@@ -168,6 +163,6 @@
168163
}
169164
},
170165
"conversation_id": "7a65b6ed-85d1-4621-8efb-4fc8e9c5a8de",
171-
"agent_type": "informational"
166+
"agent_type": "socratic"
172167
}
173168
}

src/agents/utils/example_inputs/example_input_2.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@
213213
"questionAccessInformation": {
214214
"estimatedMinimumTime": "3 minutes",
215215
"estimaredMaximumTime": "7 minutes",
216-
"timeTaken": "35610 minutes",
216+
"timeTaken": "42 minutes",
217217
"accessStatus": "too much time spent on this question.",
218218
"markedDone": "",
219219
"currentPart": {

src/agents/utils/example_inputs/example_input_4.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -445,7 +445,7 @@
445445
"questionAccessInformation": {
446446
"estimatedMinimumTime": "1 minute",
447447
"estimaredMaximumTime": "3 minutes",
448-
"timeTaken": "13199 minutes",
448+
"timeTaken": "13 minutes",
449449
"accessStatus": "too much time spent on this question.",
450450
"markedDone": "Part (a) was marked done",
451451
"currentPart": {

src/agents/utils/example_inputs/example_input_5.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@
223223
"questionAccessInformation": {
224224
"estimatedMinimumTime": "3 minutes",
225225
"estimaredMaximumTime": "7 minutes",
226-
"timeTaken": "43881 minutes",
226+
"timeTaken": "40 minutes",
227227
"accessStatus": "too much time spent on this question.",
228228
"markedDone": "Part (a) was marked done",
229229
"currentPart": {

src/agents/utils/parse_json_to_prompt.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -189,7 +189,7 @@ def format_part_details(part: PartDetails, currentPartId: str, summary: List[Stu
189189
Guidance to Solve the Question: {questionInformation.questionGuidance or 'None'};
190190
Description of Question: {questionInformation.questionContent};
191191
Expected Time to Complete the Question: {f'{questionInformation.durationLowerBound} - {questionInformation.durationUpperBound} min;' if questionInformation.durationLowerBound and questionInformation.durationUpperBound else 'No specified duration.'}
192-
Time Spent on the Question This Session: {questionAccessInformation.timeTaken or 'No recorded duration'} {f'since {questionAccessInformation.markedDone}' if questionAccessInformation.markedDone else ''} {f'which is {questionAccessInformation.accessStatus}' if questionAccessInformation.accessStatus else ''};
192+
Time Spent on the Question This Session: {questionAccessInformation.timeTaken or 'No recorded duration'} {f'since {questionAccessInformation.markedDone}' if questionAccessInformation.markedDone else {f'which is {questionAccessInformation.accessStatus}' if questionAccessInformation.accessStatus else ''}};
193193
"""
194194

195195
partsDetails = "\n".join(

src/agents/utils/synthetic_conversation_generation.py

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
Any of the models accessible through the API calls defined in the 'llm_factory.py' can be used for either the tutor and the agent LLM.
1919
"""
2020

21+
import csv
2122
import json
2223
try:
2324
from ..student_agent.student_agent import invoke_student_agent
@@ -104,7 +105,7 @@ def generate_synthetic_conversations(raw_text: str, num_turns: int, student_agen
104105
if __name__ == "__main__":
105106
num_turns = 6
106107
# Can be "informational", "socratic", "google_learnlm"
107-
tutor_agent_types = ["socratic"]
108+
tutor_agent_types = ["google_learnlm"]
108109
# Can be "base", "curious", "contradicting", "reliant", "confused", "unrelated"
109110
student_agent_types = ["base", "curious", "contradicting", "reliant", "confused", "unrelated"]
110111

@@ -116,15 +117,25 @@ def generate_synthetic_conversations(raw_text: str, num_turns: int, student_agen
116117
if filename.endswith("1.json"):
117118
questions.append(os.path.join(example_inputs_folder, filename))
118119

119-
for student_agent_type in student_agent_types:
120120
for tutor_agent_type in tutor_agent_types:
121-
for question in questions:
122-
with open(question, "r") as file:
123-
raw_text = file.read()
124-
125-
conversation = generate_synthetic_conversations(raw_text, num_turns, student_agent_type, tutor_agent_type)
126-
127-
conversation_output_filename = output_folder + question.split('/')[-1].replace(".json", "_"+student_agent_type+"_"+tutor_agent_type+"_conversation.json")
128-
with open(conversation_output_filename, "w") as file:
129-
json.dump(conversation, file, indent=2)
130-
121+
# Open CSV file for writing
122+
csv_filename = os.path.join(output_folder, "all_conversations_"+tutor_agent_type+".csv")
123+
with open(csv_filename, "w", newline='') as csvfile:
124+
csv_writer = csv.writer(csvfile)
125+
# Write the header
126+
csv_writer.writerow(["tutor", "student", "conversation", "conversation_id"])
127+
128+
for student_agent_type in student_agent_types:
129+
for question in questions:
130+
with open(question, "r") as file:
131+
raw_text = file.read()
132+
133+
conversation = generate_synthetic_conversations(raw_text, num_turns, student_agent_type, tutor_agent_type)
134+
135+
conversation_output_filename = output_folder + question.split('/')[-1].replace(".json", "_"+student_agent_type+"_"+tutor_agent_type+"_conversation.json")
136+
with open(conversation_output_filename, "w") as file:
137+
json.dump(conversation, file, indent=2)
138+
139+
# Write to CSV
140+
conversation_id = conversation["conversation_id"]
141+
csv_writer.writerow([tutor_agent_type, student_agent_type, conversation["conversation"], conversation_id])

0 commit comments

Comments
 (0)