samu commited on
Commit
525c716
·
1 Parent(s): 8ea91af
Files changed (34) hide show
  1. backend/CurriculumManager/__init__.py +0 -0
  2. backend/CurriculumManager/__pycache__/__init__.cpython-312.pyc +0 -0
  3. backend/CurriculumManager/__pycache__/generate_curriculum.cpython-312.pyc +0 -0
  4. backend/CurriculumManager/config.json +0 -1
  5. backend/CurriculumManager/generate_curriculum.py +0 -41
  6. backend/LessonManager/__init__.py +0 -0
  7. backend/LessonManager/__pycache__/__init__.cpython-312.pyc +0 -0
  8. backend/LessonManager/__pycache__/generate_daily_lesson.cpython-312.pyc +0 -0
  9. backend/LessonManager/__pycache__/generate_lesson.cpython-312.pyc +0 -0
  10. backend/LessonManager/generate_daily_lesson.py +0 -38
  11. backend/LessonManager/generate_lesson.py +0 -38
  12. backend/__init__.py +0 -0
  13. backend/__pycache__/__init__.cpython-312.pyc +0 -0
  14. backend/__pycache__/api.cpython-312.pyc +0 -0
  15. backend/__pycache__/api.cpython-39.pyc +0 -0
  16. backend/__pycache__/config.cpython-312.pyc +0 -0
  17. backend/__pycache__/config.cpython-39.pyc +0 -0
  18. backend/__pycache__/config_manager.cpython-312.pyc +0 -0
  19. backend/__pycache__/main.cpython-312.pyc +0 -0
  20. backend/__pycache__/utils.cpython-312.pyc +0 -0
  21. backend/__pycache__/utils.cpython-39.pyc +0 -0
  22. backend/api.py +39 -0
  23. backend/api/__init__.py +0 -1
  24. backend/api/__pycache__/__init__.cpython-312.pyc +0 -0
  25. backend/api/__pycache__/app.cpython-312.pyc +0 -0
  26. backend/api/__pycache__/models.cpython-312.pyc +0 -0
  27. backend/api/app.py +0 -85
  28. backend/api/models.py +0 -11
  29. backend/config.json +0 -12
  30. backend/config.py +52 -89
  31. backend/config_manager.py +0 -71
  32. backend/main.py +19 -247
  33. backend/requirements.txt +0 -6
  34. backend/utils.py +21 -55
backend/CurriculumManager/__init__.py DELETED
File without changes
backend/CurriculumManager/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (189 Bytes)
 
backend/CurriculumManager/__pycache__/generate_curriculum.cpython-312.pyc DELETED
Binary file (2.4 kB)
 
backend/CurriculumManager/config.json DELETED
@@ -1 +0,0 @@
1
- {}
 
 
backend/CurriculumManager/generate_curriculum.py DELETED
@@ -1,41 +0,0 @@
1
- import json
2
- import os
3
- from openai import OpenAI
4
- from backend.config import config, CURRICULUM_INSTRUCTION
5
- from backend.utils import write_json_file, ensure_directory
6
-
7
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
- output_dir = os.path.join(PROJECT_ROOT, "output")
9
- ensure_directory(output_dir)
10
-
11
- client = OpenAI(
12
- api_key=config.get('api_key'),
13
- base_url=config.get('base_url'),
14
- )
15
-
16
- def get_completion(prompt: str):
17
- response = client.chat.completions.create(
18
- model=config.get('model'),
19
- messages=[
20
- {"role": "system", "content": CURRICULUM_INSTRUCTION},
21
- {"role": "user", "content": prompt},
22
- ],
23
- response_format={"type": "json_object"},
24
- )
25
-
26
- try:
27
- data = json.loads(response.choices[0].message.content)
28
- filename = os.path.join(output_dir, "curriculum.json")
29
-
30
- if write_json_file(filename, data):
31
- print(f"JSON data saved to {filename}")
32
- # Reset the config when new curriculum is generated
33
- config.set("current_week", 0)
34
- config.save()
35
- return data # Return the data instead of True
36
- print("Failed to save data")
37
- return None
38
-
39
- except json.JSONDecodeError as e:
40
- print(f"Error decoding JSON: {e}")
41
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/LessonManager/__init__.py DELETED
File without changes
backend/LessonManager/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (185 Bytes)
 
backend/LessonManager/__pycache__/generate_daily_lesson.cpython-312.pyc DELETED
Binary file (2.23 kB)
 
backend/LessonManager/__pycache__/generate_lesson.cpython-312.pyc DELETED
Binary file (2.21 kB)
 
backend/LessonManager/generate_daily_lesson.py DELETED
@@ -1,38 +0,0 @@
1
- import json
2
- import os
3
- from openai import OpenAI
4
- from backend.config import config
5
- from backend.utils import write_json_file, ensure_directory
6
-
7
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
- output_dir = os.path.join(PROJECT_ROOT, "output")
9
- ensure_directory(output_dir)
10
-
11
- client = OpenAI(
12
- api_key=config.get('api_key'),
13
- base_url=config.get('base_url'),
14
- )
15
-
16
- def get_completion(prompt: str):
17
- response = client.chat.completions.create(
18
- model=config.get('model'),
19
- messages=[
20
- {"role": "system", "content": config.get('daily_lesson_instruction')},
21
- {"role": "user", "content": prompt},
22
- ],
23
- response_format={"type": "json_object"},
24
- )
25
-
26
- try:
27
- data = json.loads(response.choices[0].message.content)
28
- filename = f"{output_dir}/daily_lesson.json"
29
-
30
- if write_json_file(filename, data):
31
- print(f"JSON data saved to {filename}")
32
- else:
33
- print("Failed to save data")
34
- return data
35
-
36
- except json.JSONDecodeError as e:
37
- print(f"Error decoding JSON: {e}")
38
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/LessonManager/generate_lesson.py DELETED
@@ -1,38 +0,0 @@
1
- import json
2
- import os
3
- from openai import OpenAI
4
- from backend.config import config
5
- from backend.utils import write_json_file, ensure_directory
6
-
7
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
8
- output_dir = os.path.join(PROJECT_ROOT, "output")
9
- ensure_directory(output_dir)
10
-
11
- client = OpenAI(
12
- api_key=config.get('api_key'),
13
- base_url=config.get('base_url'),
14
- )
15
-
16
- def get_completion(prompt: str):
17
- response = client.chat.completions.create(
18
- model=config.get('model'),
19
- messages=[
20
- {"role": "system", "content": config.get('lesson_instruction')},
21
- {"role": "user", "content": prompt},
22
- ],
23
- response_format={"type": "json_object"},
24
- )
25
-
26
- try:
27
- data = json.loads(response.choices[0].message.content)
28
- filename = f"{output_dir}/lesson.json"
29
-
30
- if write_json_file(filename, data):
31
- print(f"JSON data saved to {filename}")
32
- else:
33
- print("Failed to save data")
34
- return data
35
-
36
- except json.JSONDecodeError as e:
37
- print(f"Error decoding JSON: {e}")
38
- return None
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/__init__.py DELETED
File without changes
backend/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (171 Bytes)
 
backend/__pycache__/api.cpython-312.pyc ADDED
Binary file (2.02 kB). View file
 
backend/__pycache__/api.cpython-39.pyc ADDED
Binary file (1.56 kB). View file
 
backend/__pycache__/config.cpython-312.pyc CHANGED
Binary files a/backend/__pycache__/config.cpython-312.pyc and b/backend/__pycache__/config.cpython-312.pyc differ
 
backend/__pycache__/config.cpython-39.pyc ADDED
Binary file (3.16 kB). View file
 
backend/__pycache__/config_manager.cpython-312.pyc DELETED
Binary file (3.57 kB)
 
backend/__pycache__/main.cpython-312.pyc CHANGED
Binary files a/backend/__pycache__/main.cpython-312.pyc and b/backend/__pycache__/main.cpython-312.pyc differ
 
backend/__pycache__/utils.cpython-312.pyc CHANGED
Binary files a/backend/__pycache__/utils.cpython-312.pyc and b/backend/__pycache__/utils.cpython-312.pyc differ
 
backend/__pycache__/utils.cpython-39.pyc ADDED
Binary file (748 Bytes). View file
 
backend/api.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from fastapi import FastAPI, HTTPException
2
+ from fastapi.responses import JSONResponse, StreamingResponse
3
+ from fastapi.middleware.cors import CORSMiddleware
4
+ from fastapi import Request
5
+ import uvicorn
6
+ from pydantic import BaseModel, Field
7
+ from typing import Union, List, Dict
8
+ import json
9
+ import asyncio
10
+ from backend.utils import get_completion
11
+ from backend.config import CURRICULUM_INSTRUCTIONS
12
+
13
+ app = FastAPI()
14
+
15
+ app.add_middleware(
16
+ CORSMiddleware,
17
+ allow_origins=["*"],
18
+ allow_credentials=True,
19
+ allow_methods=["*"],
20
+ allow_headers=["*"],
21
+ )
22
+
23
+ # Define a request model
24
+ class QueryRequest(BaseModel):
25
+ user_query: str
26
+
27
+ # Define a response model
28
+ class QueryResponse(BaseModel):
29
+ answer: str
30
+
31
+ @app.get("/")
32
+ async def root():
33
+ return {"message": "Hello World"}
34
+
35
+ @app.post("/curriculum")
36
+ async def get_curriculum(request: QueryRequest):
37
+ query = request.user_query
38
+ response = await get_completion(prompt=query, instruction=CURRICULUM_INSTRUCTIONS)
39
+ return JSONResponse(response, media_type="application/json")
backend/api/__init__.py DELETED
@@ -1 +0,0 @@
1
- # Empty init file
 
 
backend/api/__pycache__/__init__.cpython-312.pyc DELETED
Binary file (175 Bytes)
 
backend/api/__pycache__/app.cpython-312.pyc DELETED
Binary file (5.64 kB)
 
backend/api/__pycache__/models.cpython-312.pyc DELETED
Binary file (903 Bytes)
 
backend/api/app.py DELETED
@@ -1,85 +0,0 @@
1
- import os
2
- import socket
3
- from fastapi import FastAPI, HTTPException
4
- from .models import CurriculumRequest, LessonRequest, DailyLessonRequest
5
- from backend.CurriculumManager.generate_curriculum import get_completion as generate_curriculum
6
- from backend.LessonManager.generate_lesson import get_completion as generate_lesson
7
- from backend.LessonManager.generate_daily_lesson import get_completion as generate_daily_lesson
8
- from backend.config_manager import Config
9
- from backend.utils import read_json_file, ensure_directory
10
-
11
- # Set up paths correctly
12
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(__file__)))
13
- CONFIG_DIR = os.path.join(PROJECT_ROOT, "backend")
14
- CONFIG_PATH = os.path.join(CONFIG_DIR, "config.json")
15
-
16
- # Ensure config directory exists
17
- ensure_directory(CONFIG_DIR)
18
-
19
- # Import and run config setup
20
- from backend.config import (
21
- CURRICULUM_INSTRUCTION,
22
- MODEL,
23
- BASE_URL,
24
- API_KEY,
25
- API_PORT
26
- )
27
-
28
- app = FastAPI(title="AI Language Tutor API")
29
- config = Config(CONFIG_PATH)
30
-
31
- # Initialize config with default values if not exists
32
- if not config.data:
33
- config.set("curriculum_instruction", CURRICULUM_INSTRUCTION)
34
- config.set("model", MODEL)
35
- config.set("base_url", BASE_URL)
36
- config.set("api_key", API_KEY)
37
- config.save()
38
-
39
- @app.post("/curriculum")
40
- async def create_curriculum(request: CurriculumRequest):
41
- try:
42
- return generate_curriculum(request.prompt)
43
- except Exception as e:
44
- raise HTTPException(status_code=500, detail=str(e))
45
-
46
- @app.post("/lesson")
47
- async def create_lesson(request: LessonRequest):
48
- try:
49
- # Simulate args object for compatibility
50
- class Args:
51
- def __init__(self, week):
52
- self.week = week
53
-
54
- args = Args(request.week)
55
- from backend.main import setup_lesson_instruction
56
-
57
- setup_lesson_instruction(args)
58
- return generate_lesson(config.get("lesson_prompt"))
59
- except FileNotFoundError:
60
- raise HTTPException(status_code=404, detail="Curriculum not found")
61
- except ValueError as e:
62
- raise HTTPException(status_code=400, detail=str(e))
63
-
64
- @app.post("/daily-lesson")
65
- async def create_daily_lesson(request: DailyLessonRequest):
66
- try:
67
- class Args:
68
- def __init__(self, week, day):
69
- self.week = week
70
- self.day = day
71
-
72
- args = Args(request.week, request.day)
73
- from backend.main import setup_daily_lesson
74
-
75
- return setup_daily_lesson(args)
76
- except FileNotFoundError:
77
- raise HTTPException(status_code=404, detail="Lesson plan not found")
78
- except ValueError as e:
79
- raise HTTPException(status_code=400, detail=str(e))
80
-
81
- # Add Args class at module level
82
- class Args:
83
- def __init__(self, week=0, day=0):
84
- self.week = week
85
- self.day = day
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/api/models.py DELETED
@@ -1,11 +0,0 @@
1
- from pydantic import BaseModel
2
-
3
- class CurriculumRequest(BaseModel):
4
- prompt: str
5
-
6
- class LessonRequest(BaseModel):
7
- week: int = 0
8
-
9
- class DailyLessonRequest(BaseModel):
10
- week: int = 0
11
- day: int = 0
 
 
 
 
 
 
 
 
 
 
 
 
backend/config.json DELETED
@@ -1,12 +0,0 @@
1
- {
2
- "curriculum_instruction": "\nYou are an expert language learning curriculum designer. Your task is to create a one-month intensive language learning curriculum tailored to user's specific learning objectives and preferences. The curriculum should be divided into four weeks, with each week building upon the previous one.\n\n**Curriculum Design Principles:**\n\n1. **Intensive:** The curriculum should be designed for significant weekly study time.\n2. **Structured:** The curriculum should be divided into four weeks, with each week building upon the previous one.\n3. **Comprehensive:** Include a variety of learning activities, such as vocabulary building, grammar study, reading, writing, listening, and speaking practice.\n4. **Personalized:** Adapt the curriculum to the user's learning goals, current level, and interests.\n5. **Measurable:** Suggest ways the user can track their progress.\n6. **Output Format:** Provide the curriculum in a valid JSON format.\n7. **Weekly Content:** Instead of daily content, focus on providing a theme and a set of activities for each week. Include the approximate time the user should invest in that week.\n\n**Output JSON Format:**\n\n```json\n{\n \"language\": \"target_language\",\n \"learning_goal\": \"user_provided_goal\",\n \"current_level\": \"user_provided_level\",\n \"weeks\": [\n {\n \"week\": 1,\n \"theme\": \"week_theme\",\n \"estimated_duration\": \"estimated_weekly_time\",\n \"activities\": [\n {\n \"type\": \"activity_type\",\n \"description\": \"activity_description\",\n \"resources\": [\"resource1\", \"resource2\", ...]\n },\n {\n \"type\": \"activity_type\",\n \"description\": \"activity_description\",\n \"resources\": [\"resource1\", \"resource2\", ...]\n },\n ...\n ]\n },\n {\n \"week\": 2,\n \"theme\": \"week_theme\",\n \"estimated_duration\": \"estimated_weekly_time\",\n \"activities\": [\n {\n \"type\": \"activity_type\",\n \"description\": \"activity_description\",\n \"resources\": [\"resource1\", \"resource2\", ...]\n },\n ...\n ]\n },\n ...\n ]\n}\n",
3
- "model": "gemini-1.5-flash-8b",
4
- "base_url": "https://generativelanguage.googleapis.com/v1beta/openai/",
5
- "api_key": "AIzaSyA5V1Pp8icIuj6vd5agdk9sYsEi4sUzWlU",
6
- "lesson_instruction": "\n You are an advanced AI language tutor specializing in personalized language instruction. Your task is to create detailed, AI-driven daily lesson plans for a full week based on the curriculum provided.\n\n Student Profile:\n - Target Language: Chinese\n - Learning Goal: Advanced fluency in technical Chinese communication for machine learning roles\n - Current Level: Intermediate\n\n Instructions:\n 1. Create engaging, AI-driven activities for each day of the week (7 days)\n 2. Focus on interactive, personalized learning experiences\n 3. Avoid suggesting external resources or tools\n 4. Ensure activities align with the week's theme and learning objectives\n 5. Include specific examples and practice scenarios for each day\n 6. Format your response as a valid JSON object\n\n Output Format:\n {\n \"week\": number,\n \"theme\": \"string\",\n \"estimated_duration\": \"string\",\n \"daily_lessons\": [\n {\n \"day\": number,\n \"focus\": \"string\",\n \"duration\": \"string\",\n \"activities\": [\n {\n \"type\": \"string\",\n \"description\": \"string\"\n }\n ]\n },\n // Repeat for all 7 days\n ]\n }\n\n Notes:\n - Create lessons for all 7 days of the week\n - Each day should have a specific focus while maintaining the week's theme\n - Weekend lessons (days 6-7) can be lighter but should maintain learning momentum\n - All activities should be completable through AI interaction\n ",
7
- "lesson_prompt": "\n Based on the curriculum week 4:\n {'week': 4, 'theme': 'Presentations and Debates', 'estimated_duration': '20-25 hours', 'activities': [{'type': 'Presentation Practice', 'description': 'Prepare and practice presenting a machine learning project or topic in Chinese. Record your presentation and seek feedback from a language partner or AI assistant.'}, {'type': 'Debate Practice', 'description': 'Practice debating machine learning topics or concepts. Structure arguments and counter-arguments, using formal and informal Chinese communication strategies.'}, {'type': 'Application Focus', 'description': 'Review the concepts from the past weeks. Apply the skills from previous weeks in a real-world context. This could be by joining a discussion, presenting a project, or initiating a conversation with a native speaker. '}, {'type': 'Progress Reflection', 'description': 'Summarize your achievements. Set realistic next steps for continued language development and technical communication.'}]}\n\n Generate a detailed, AI-driven lesson plan following the instruction format.\n ",
8
- "daily_lesson_instruction": "\n You are an AI assistant tasked with curating today's lesson to help the user improve their skills in the target language.\n\n Instructions:\n 1. Determine the target language based on the user's input.\n 2. Create a bilingual lesson (English and the target language) to enable the user to achieve their learning goal.\n 3. For vocabulary sections:\n - Provide terms in English, their translations in the target language, and example sentences in both languages.\n - For character-based languages (e.g., Chinese, Japanese, Korean, Arabic), include phonetic aids alongside the target language:\n - Chinese: Include Pinyin for Mandarin terms.\n - Japanese: Include Romaji for Japanese terms.\n - Korean: Include Romanized Korean (Revised Romanization).\n - Arabic: Include transliteration using the Latin alphabet.\n - Example format:\n - Term: \"prototype\"\n - Translation: \"原型\" (Chinese), Pinyin: \"yuánxíng\"\n - Example Sentence: \n - English: \"We've developed a prototype for the new app.\"\n - Target Language: \"我们为新应用开发了一个原型。\" (Chinese), Pinyin: \"Wǒmen wèi xīn yìngyòng kāifāle yígè yuánxíng.\"\n 4. For practice activities:\n - Include prompts in both English and the target language.\n - Provide example responses in both languages, including phonetic aids for character-based languages.\n 5. Provide feedback on the user's input, focusing on grammar, vocabulary, and fluency. If applicable, include corrections with phonetic aids.\n 6. Always remember to include both English and the target language for all cases, along with phonetic aids for character-based languages.\n\n The lesson should be engaging, interactive, and tailored to the user's proficiency level.\n ",
9
- "daily_lesson_prompt": "\n Theme: Foundational Technical Vocabulary\n\n Based on today's lesson plan, create a bilingual lesson (English and Chinese) with the following structure:\n\n Lesson Plan: {'day': 5, 'focus': 'Review and Consolidation', 'duration': '2 hours', 'activities': [{'type': 'Vocabulary Recall', 'description': 'The AI will present a list of machine learning terms. You will write the definition or appropriate synonym in Chinese for each.'}, {'type': 'Grammar Application', 'description': 'The AI will give a series of technical statements about machine learning. Reformulate each statement into a question using appropriate grammar structures for questioning. The AI will check your accuracy.'}]}\n ",
10
- "target_language": "Chinese",
11
- "current_week": 3
12
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/config.py CHANGED
@@ -1,96 +1,59 @@
1
- from dotenv import load_dotenv
2
- from backend.config_manager import Config
3
- from backend.utils import ensure_directory
4
- import os
5
-
6
- load_dotenv()
7
-
8
- # Set up base paths
9
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
10
- CONFIG_DIR = os.path.join(PROJECT_ROOT, "backend")
11
- OUTPUT_DIR = os.path.join(PROJECT_ROOT, "output")
12
-
13
- # Ensure directories exist
14
- ensure_directory(CONFIG_DIR)
15
- ensure_directory(OUTPUT_DIR)
16
-
17
- config_path = os.path.join(CONFIG_DIR, "config.json")
18
- config = Config(config_path)
19
-
20
- # Default values - update API key handling
21
- API_KEY = os.getenv('OPENAI_API_KEY') or os.getenv('GEMINI_API_KEY')
22
- if not API_KEY:
23
- raise ValueError("No API key found. Please set OPENAI_API_KEY or GEMINI_API_KEY environment variable")
24
-
25
- MODEL = "gemini-1.5-flash-8b"
26
- BASE_URL = "https://generativelanguage.googleapis.com/v1beta/openai/"
27
-
28
- # Add API port configuration
29
- API_PORT = int(os.getenv('API_PORT', 8000))
30
-
31
- CURRICULUM_INSTRUCTION = """
32
- You are an expert AI language learning curriculum designer. Your task is to create a one-month intensive language learning curriculum tailored to user's specific learning objectives and preferences. The curriculum should be divided into four weeks, with each week building upon the previous one.
33
 
34
  **Curriculum Design Principles:**
35
 
36
- 1. **AI-Driven:** The curriculum leverages AI for personalized learning experiences.
37
- 2. **Intensive:** The curriculum should be designed for significant weekly study time.
38
- 3. **Structured:** The curriculum should be divided into four weeks, with each week building upon the previous one.
39
- 4. **Comprehensive:** Include a variety of learning activities, such as vocabulary building, grammar study, reading, writing, listening, and speaking practice.
40
- 5. **Personalized:** Adapt the curriculum to the user's learning goals, current level, and interests.
41
- 6. **Measurable:** Suggest ways the user can track their progress.
42
- 7. **Output Format:** Provide the curriculum in a valid JSON format.
43
- 8. **Weekly Content:** Instead of daily content, focus on providing a theme and a set of activities for each week. Include the approximate time the user should invest in that week.
44
 
45
- **Output JSON Format:**
 
 
 
46
 
 
47
  ```json
48
- {
49
- "language": "target_language",
50
- "learning_goal": "user_provided_goal",
51
- "current_level": "user_provided_level",
52
- "weeks": [
53
- {
54
- "week": 1,
55
- "theme": "week_theme",
56
- "estimated_duration": "estimated_weekly_time",
57
- "activities": [
58
- {
59
- "type": "activity_type",
60
- "description": "activity_description"
61
- },
62
- {
63
- "type": "activity_type",
64
- "description": "activity_description"
65
- },
66
- ...
67
- ]
68
- },
69
- {
70
- "week": 2,
71
- "theme": "week_theme",
72
- "estimated_duration": "estimated_weekly_time",
73
- "activities": [
74
- {
75
- "type": "activity_type",
76
- "description": "activity_description"
77
- },
78
- ...
79
- ]
80
- },
81
- ...
82
- ]
83
  }
84
- """
85
-
86
- # Export CURRICULUM_INSTRUCTION
87
- __all__ = ['config', 'CURRICULUM_INSTRUCTION', 'API_PORT']
88
-
89
- # Initialize config with default values if not exists
90
- if not config.data:
91
- config.set("curriculum_instruction", CURRICULUM_INSTRUCTION)
92
- config.set("model", MODEL)
93
- config.set("base_url", BASE_URL)
94
- config.set("api_key", API_KEY)
95
- config.set("api_port", API_PORT)
96
- config.save()
 
1
+ CURRICULUM_INSTRUCTIONS = """
2
+ You are an expert AI language learning curriculum designer.
3
+ Your task is to create an intensive language learning curriculum tailored to the user's specific learning objectives and preferences.
4
+ By default, design a one-month curriculum (divided into four weeks), but note that the duration can be adjusted if the user desires a different length of study time.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
5
 
6
  **Curriculum Design Principles:**
7
 
8
+ 1. **AI-Driven:** Leverage AI to create personalized learning experiences.
9
+ 2. **Intensive:** Design the curriculum for significant weekly study time.
10
+ 3. **Structured:** Divide the curriculum into four weeks (or the user-specified duration), with each week building upon the previous one.
11
+ 4. **Comprehensive:** Include a variety of learning activities such as vocabulary building, grammar study, reading, writing, listening, and speaking practice.
12
+ 5. **Personalized:** Adapt the curriculum to the user's learning goals, current level, interests, and native language.
13
+ 6. **Measurable:** Suggest ways for the user to track their progress.
14
+ 7. **Output Format:** Provide the curriculum in a valid JSON format.
15
+ 8. **Weekly Content:** Focus on providing a theme and a set of activities for each week instead of daily content. For each week, include the approximate time the user should invest during that week (for example, "estimated_duration": "20 hours per week"). Adjust the duration if the user requests a different total timeframe.
16
 
17
+ **Important Notes:**
18
+ - The curriculum should be **bilingual** in the user's **native language** and the **target language**.
19
+ - Provide detailed instructions, explanations, and examples in the user's **native language** (for context and easier understanding).
20
+ - Activities and exercises should also include explanations in the user's **native language** where necessary, ensuring the learning experience is smooth and intuitive.
21
 
22
+ **Output JSON Format:**
23
  ```json
24
+ {
25
+ "language": "target_language",
26
+ "native_language": "user_native_language",
27
+ "learning_goal": "user_provided_goal",
28
+ "current_level": "user_provided_level",
29
+ "weeks": [
30
+ {
31
+ "week": 1,
32
+ "theme": "week_theme",
33
+ "estimated_duration": "estimated_weekly_time",
34
+ "activities": [
35
+ {
36
+ "type": "activity_type",
37
+ "description": "activity_description_in_native_language"
38
+ },
39
+ {
40
+ "type": "activity_type",
41
+ "description": "activity_description_in_native_language"
42
+ }, ...
43
+ ]
44
+ },
45
+ {
46
+ "week": 2,
47
+ "theme": "week_theme",
48
+ "estimated_duration": "estimated_weekly_time",
49
+ "activities": [
50
+ {
51
+ "type": "activity_type",
52
+ "description": "activity_description_in_native_language"
53
+ }, ...
54
+ ]
55
+ }, ... // repeat for the duration of the curriculum
56
+ ]
 
 
57
  }
58
+ ```
59
+ """
 
 
 
 
 
 
 
 
 
 
 
backend/config_manager.py DELETED
@@ -1,71 +0,0 @@
1
- import json
2
- import os
3
-
4
-
5
- class Config:
6
- def __init__(self, file_path="config.json"):
7
- self.file_path = file_path
8
- self.data = {}
9
- self.load()
10
-
11
- def load(self):
12
- """Loads the configuration data from the JSON file."""
13
- try:
14
- with open(self.file_path, "r", encoding="utf-8") as f:
15
- self.data = json.load(f)
16
- except FileNotFoundError:
17
- print(f"Config file not found at {self.file_path}. Creating a new one.")
18
- self.data = {} # Start with an empty config
19
- self.save()
20
- except json.JSONDecodeError:
21
- print(
22
- f"Error: Invalid JSON format in config file at {self.file_path}. The file will be reset."
23
- )
24
- self.data = {}
25
- self.save()
26
-
27
- def save(self):
28
- """Saves the configuration data to the JSON file."""
29
- with open(self.file_path, "w", encoding="utf-8") as f:
30
- json.dump(self.data, f, indent=4, ensure_ascii=False)
31
-
32
- def get(self, key, default=None):
33
- """Gets a configuration value by key.
34
-
35
- Args:
36
- key (str): The key to look up.
37
- default: The default value to return if the key is not found.
38
-
39
- Returns:
40
- The configuration value or the default.
41
- """
42
- return self.data.get(key, default)
43
-
44
- def set(self, key, value):
45
- """Sets a configuration value.
46
-
47
- Args:
48
- key (str): The key to set.
49
- value: The value to set.
50
- """
51
- self.data[key] = value
52
- self.save()
53
-
54
- def update(self, new_data):
55
- """Updates the config data with a new dict
56
-
57
- Args:
58
- new_data: The data to update
59
- """
60
- self.data.update(new_data)
61
- self.save()
62
-
63
- def delete(self, key):
64
- """Deletes a key from the config
65
-
66
- Args:
67
- key (str): the key to delete
68
- """
69
- if key in self.data:
70
- del self.data[key]
71
- self.save()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/main.py CHANGED
@@ -1,248 +1,20 @@
1
- import os
2
- import argparse
3
- import sys
4
- from backend.CurriculumManager.generate_curriculum import get_completion as generate_curriculum
5
- from backend.LessonManager.generate_lesson import get_completion as generate_lesson
6
- from backend.LessonManager.generate_daily_lesson import get_completion as generate_daily_lesson
7
- from backend.config_manager import Config
8
- from backend.utils import read_json_file, ensure_directory
9
-
10
- # Set up paths
11
- PROJECT_ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
12
- CONFIG_PATH = os.path.join(PROJECT_ROOT, "backend", "config.json")
13
- OUTPUT_DIR = os.path.join(PROJECT_ROOT, "output")
14
- CURRICULUM_PATH = os.path.join(OUTPUT_DIR, "curriculum.json")
15
- LESSON_PATH = os.path.join(OUTPUT_DIR, "lesson.json")
16
-
17
- # Ensure output directory exists
18
- ensure_directory(OUTPUT_DIR)
19
-
20
- config = Config(CONFIG_PATH)
21
-
22
- def parse_args():
23
- parser = argparse.ArgumentParser(description='AI Language Tutor')
24
- parser.add_argument('--mode', choices=['curriculum', 'lesson', 'daily'], required=True,
25
- help='Mode of operation: curriculum, weekly lesson, or daily micro-lessons')
26
- parser.add_argument('--prompt', type=str, required='curriculum' in sys.argv,
27
- help='User prompt for curriculum generation (required for curriculum mode)')
28
- parser.add_argument('--week', type=int, default=0, help='Week number (0-based index)')
29
- parser.add_argument('--day', type=int, default=0, help='Day number (0-based index)')
30
- return parser.parse_args()
31
-
32
- def setup_lesson_instruction(args):
33
- """Setup lesson instruction from curriculum data using specified week."""
34
- curriculum_data = read_json_file(CURRICULUM_PATH)
35
- if curriculum_data is None:
36
- raise FileNotFoundError("Curriculum not found. Please generate curriculum first.")
37
-
38
- if args.week >= len(curriculum_data["weeks"]):
39
- raise ValueError(f"Week {args.week} not found. Available weeks: 0-{len(curriculum_data['weeks'])-1}")
40
-
41
- language = curriculum_data["language"]
42
- learning_goal = curriculum_data["learning_goal"]
43
- current_level = curriculum_data["current_level"]
44
- week = curriculum_data["weeks"][args.week]
45
-
46
- lesson_instruction = """
47
- You are an advanced AI language tutor specializing in personalized language instruction. Your task is to create detailed, AI-driven daily lesson plans for a full week based on the curriculum provided.
48
-
49
- Student Profile:
50
- - Target Language: {language}
51
- - Learning Goal: {learning_goal}
52
- - Current Level: {current_level}
53
-
54
- Instructions:
55
- 1. Create engaging, AI-driven activities for each day of the week (7 days)
56
- 2. Focus on interactive, personalized learning experiences
57
- 3. Avoid suggesting external resources or tools
58
- 4. Ensure activities align with the week's theme and learning objectives
59
- 5. Include specific examples and practice scenarios for each day
60
- 6. Format your response as a valid JSON object
61
-
62
- Output Format:
63
- {{
64
- "week": number,
65
- "theme": "string",
66
- "estimated_duration": "string",
67
- "daily_lessons": [
68
- {{
69
- "day": number,
70
- "focus": "string",
71
- "duration": "string",
72
- "activities": [
73
- {{
74
- "type": "string",
75
- "description": "string"
76
- }}
77
- ]
78
- }},
79
- // Repeat for all 7 days
80
- ]
81
- }}
82
-
83
- Notes:
84
- - Create lessons for all 7 days of the week
85
- - Each day should have a specific focus while maintaining the week's theme
86
- - Weekend lessons (days 6-7) can be lighter but should maintain learning momentum
87
- - All activities should be completable through AI interaction
88
- """.format(
89
- language=language,
90
- learning_goal=learning_goal,
91
- current_level=current_level
92
- )
93
-
94
- lesson_prompt = """
95
- Based on the curriculum week {week_num}:
96
- {curriculum}
97
-
98
- Generate a detailed, AI-driven lesson plan following the instruction format.
99
- """.format(week_num=args.week + 1, curriculum=week)
100
-
101
- config.set("target_language", language)
102
- config.set("lesson_instruction", lesson_instruction)
103
- config.set("lesson_prompt", lesson_prompt)
104
-
105
- # Return the generated lesson directly instead of True
106
- return generate_lesson(lesson_prompt)
107
-
108
- def setup_daily_lesson(args):
109
- """Setup and generate daily lesson using specified day"""
110
- lesson_data = read_json_file(LESSON_PATH)
111
- theme = lesson_data["theme"]
112
- lessons = lesson_data["daily_lessons"]
113
-
114
- if args.day >= len(lessons):
115
- raise ValueError(f"Day {args.day} not found in lesson plan. Available days: 0-{len(lessons)-1}")
116
-
117
- daily_lesson_instruction = """
118
- You are an AI assistant tasked with curating today's lesson to help the user improve their skills in the target language.
119
-
120
- Instructions:
121
- 1. Determine the target language based on the user's input.
122
- 2. Create a bilingual lesson (English and the target language) to enable the user to achieve their learning goal.
123
- 3. For vocabulary sections:
124
- - Provide terms in English, their translations in the target language, and example sentences in both languages.
125
- - For character-based languages (e.g., Chinese, Japanese, Korean, Arabic), include phonetic aids alongside the target language:
126
- - Chinese: Include Pinyin for Mandarin terms.
127
- - Japanese: Include Romaji for Japanese terms.
128
- - Korean: Include Romanized Korean (Revised Romanization).
129
- - Arabic: Include transliteration using the Latin alphabet.
130
- - Example format:
131
- - Term: "prototype"
132
- - Translation: "原型" (Chinese), Pinyin: "yuánxíng"
133
- - Example Sentence:
134
- - English: "We've developed a prototype for the new app."
135
- - Target Language: "我们为新应用开发了一个原型。" (Chinese), Pinyin: "Wǒmen wèi xīn yìngyòng kāifāle yígè yuánxíng."
136
- 4. For practice activities:
137
- - Include prompts in both English and the target language.
138
- - Provide example responses in both languages, including phonetic aids for character-based languages.
139
- 5. Provide feedback on the user's input, focusing on grammar, vocabulary, and fluency. If applicable, include corrections with phonetic aids.
140
- 6. Always remember to include both English and the target language for all cases, along with phonetic aids for character-based languages.
141
-
142
- The lesson should be engaging, interactive, and tailored to the user's proficiency level.
143
- """
144
-
145
- lesson_prompt = """
146
- Theme: {theme}
147
-
148
- Based on today's lesson plan, create a bilingual lesson (English and {target_language}) with the following structure:
149
-
150
- Lesson Plan: {lesson_plan}
151
- """.format(
152
- theme=theme,
153
- target_language=config.get("target_language"),
154
- lesson_plan=lessons[args.day]
155
- )
156
-
157
- config.set("daily_lesson_instruction", daily_lesson_instruction)
158
- config.set("daily_lesson_prompt", lesson_prompt)
159
- return generate_daily_lesson(lesson_prompt)
160
-
161
- def main():
162
- args = parse_args()
163
-
164
- if args.mode == 'curriculum':
165
- if not args.prompt:
166
- raise ValueError("--prompt is required for curriculum mode")
167
- generate_curriculum(args.prompt)
168
- elif args.mode == 'lesson':
169
- setup_lesson_instruction(args) # Remove separate generate_lesson call
170
- elif args.mode == 'daily':
171
- setup_daily_lesson(args) # Already generates lesson using internal prompt
172
-
173
  if __name__ == "__main__":
174
- main()
175
-
176
- # curriculum_data = read_json_file(CURRICULUM_PATH)
177
- # if curriculum_data is None:
178
- # raise FileNotFoundError("Curriculum not found. Please generate curriculum first.")
179
-
180
- # if args.week >= len(curriculum_data["weeks"]):
181
- # raise ValueError(f"Week {args.week} not found. Available weeks: 0-{len(curriculum_data['weeks'])-1}")
182
-
183
- # language = curriculum_data["language"]
184
- # learning_goal = curriculum_data["learning_goal"]
185
- # current_level = curriculum_data["current_level"]
186
- # week = curriculum_data["weeks"][args.week]
187
-
188
- # lesson_instruction = """
189
- # You are an advanced AI language tutor specializing in personalized language instruction. Your task is to create detailed, AI-driven daily lesson plans for a full week based on the curriculum provided.
190
-
191
- # Student Profile:
192
- # - Target Language: {language}
193
- # - Learning Goal: {learning_goal}
194
- # - Current Level: {current_level}
195
-
196
- # Instructions:
197
- # 1. Create engaging, AI-driven activities for each day of the week (7 days)
198
- # 2. Focus on interactive, personalized learning experiences
199
- # 3. Avoid suggesting external resources or tools
200
- # 4. Ensure activities align with the week's theme and learning objectives
201
- # 5. Include specific examples and practice scenarios for each day
202
- # 6. Format your response as a valid JSON object
203
-
204
- # Output Format:
205
- # {{
206
- # "week": number,
207
- # "theme": "string",
208
- # "estimated_duration": "string",
209
- # "daily_lessons": [
210
- # {{
211
- # "day": number,
212
- # "focus": "string",
213
- # "duration": "string",
214
- # "activities": [
215
- # {{
216
- # "type": "string",
217
- # "description": "string"
218
- # }}
219
- # ]
220
- # }},
221
- # // Repeat for all 7 days
222
- # ]
223
- # }}
224
-
225
- # Notes:
226
- # - Create lessons for all 7 days of the week
227
- # - Each day should have a specific focus while maintaining the week's theme
228
- # - Weekend lessons (days 6-7) can be lighter but should maintain learning momentum
229
- # - All activities should be completable through AI interaction
230
- # """.format(
231
- # language=language,
232
- # learning_goal=learning_goal,
233
- # current_level=current_level
234
- # )
235
-
236
- # lesson_prompt = """
237
- # Based on the curriculum week {week_num}:
238
- # {curriculum}
239
-
240
- # Generate a detailed, AI-driven lesson plan following the instruction format.
241
- # """.format(week_num=args.week + 1, curriculum=week)
242
-
243
- # config.set("target_language", language)
244
- # config.set("lesson_instruction", lesson_instruction)
245
- # config.set("lesson_prompt", lesson_prompt)
246
-
247
- # # Return the generated lesson directly instead of True
248
- # generate_lesson(lesson_prompt)
 
1
+ import asyncio # <-- Import asyncio
2
+ from backend.utils import get_completion
3
+ from backend.config import CURRICULUM_INSTRUCTIONS
4
+
5
+ # Define an async function to hold the await call
6
+ async def main():
7
+ query = "need to improve my chinese so as to propose to my girlfriend"
8
+ print("Getting completion...") # Optional: Indicate progress
9
+ try:
10
+ response = await get_completion(prompt=query, instruction=CURRICULUM_INSTRUCTIONS)
11
+ print("\nResponse:")
12
+ print(response)
13
+ except Exception as e:
14
+ print(f"An error occurred: {e}") # Basic error handling
15
+
16
+ # Use asyncio.run() to execute the async main function
17
+ # The if __name__ == "__main__": block ensures this runs only when
18
+ # the script is executed directly (e.g., python -m backend.main)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
19
  if __name__ == "__main__":
20
+ asyncio.run(main())
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
backend/requirements.txt DELETED
@@ -1,6 +0,0 @@
1
- fastapi==0.68.0
2
- uvicorn==0.15.0
3
- python-dotenv==0.19.0
4
- pydantic==1.8.2
5
- openai==0.27.0
6
- python-multipart==0.0.5
 
 
 
 
 
 
 
backend/utils.py CHANGED
@@ -1,56 +1,22 @@
1
- import json
2
  import os
3
-
4
- def read_json_file(file_path: str) -> dict:
5
- """Reads and parses a JSON file.
6
-
7
- Args:
8
- file_path (str): Path to the JSON file
9
-
10
- Returns:
11
- dict: Parsed JSON data or None if there was an error
12
- """
13
- try:
14
- with open(file_path, "r", encoding="utf-8") as f:
15
- return json.load(f)
16
- except FileNotFoundError:
17
- print(f"Error: File not found at {file_path}")
18
- return None
19
- except json.JSONDecodeError:
20
- print(f"Error: Invalid JSON format in file at {file_path}")
21
- return None
22
-
23
- def write_json_file(file_path: str, data: dict, indent: int = 4) -> bool:
24
- """Writes data to a JSON file.
25
-
26
- Args:
27
- file_path (str): Path to save the JSON file
28
- data (dict): Data to write
29
- indent (int): Indentation level for pretty printing
30
-
31
- Returns:
32
- bool: True if successful, False otherwise
33
- """
34
- try:
35
- with open(file_path, "w", encoding="utf-8") as f:
36
- json.dump(data, f, indent=indent, ensure_ascii=False)
37
- return True
38
- except Exception as e:
39
- print(f"Error writing to file {file_path}: {str(e)}")
40
- return False
41
-
42
- def ensure_directory(directory_path: str) -> bool:
43
- """Ensures a directory exists, creates it if it doesn't.
44
-
45
- Args:
46
- directory_path (str): Path to the directory
47
-
48
- Returns:
49
- bool: True if directory exists or was created successfully
50
- """
51
- try:
52
- os.makedirs(directory_path, exist_ok=True)
53
- return True
54
- except Exception as e:
55
- print(f"Error creating directory {directory_path}: {str(e)}")
56
- return False
 
 
1
  import os
2
+ import asyncio
3
+ from openai import AsyncOpenAI
4
+ from dotenv import load_dotenv
5
+
6
+ load_dotenv()
7
+
8
+ client = AsyncOpenAI(
9
+ api_key=os.getenv("GEMINI_API_KEY"),
10
+ base_url=os.getenv("GEMINI_BASE_URL"),
11
+ )
12
+
13
+ async def get_completion(prompt: str, instruction: str) -> str:
14
+ response = await client.chat.completions.create(
15
+ model=os.getenv("MODEL"),
16
+ messages=[
17
+ {"role": "system", "content": instruction},
18
+ {"role": "user", "content": prompt}
19
+ ],
20
+ response_format={"type": "json_object"},
21
+ )
22
+ return response.choices[0].message.content