Spaces:
Running
Running
application version 0
Browse files- Dockerfile +21 -0
- backend/CurriculumManager/__init__.py +0 -0
- backend/CurriculumManager/__pycache__/__init__.cpython-312.pyc +0 -0
- backend/CurriculumManager/__pycache__/generate_curriculum.cpython-312.pyc +0 -0
- backend/CurriculumManager/config.json +1 -0
- backend/CurriculumManager/generate_curriculum.py +41 -0
- backend/LessonManager/__init__.py +0 -0
- backend/LessonManager/__pycache__/__init__.cpython-312.pyc +0 -0
- backend/LessonManager/__pycache__/generate_daily_lesson.cpython-312.pyc +0 -0
- backend/LessonManager/__pycache__/generate_lesson.cpython-312.pyc +0 -0
- backend/LessonManager/generate_daily_lesson.py +38 -0
- backend/LessonManager/generate_lesson.py +38 -0
- backend/__init__.py +0 -0
- backend/__pycache__/__init__.cpython-312.pyc +0 -0
- backend/__pycache__/config.cpython-312.pyc +0 -0
- backend/__pycache__/config_manager.cpython-312.pyc +0 -0
- backend/__pycache__/main.cpython-312.pyc +0 -0
- backend/__pycache__/utils.cpython-312.pyc +0 -0
- backend/api/__init__.py +1 -0
- backend/api/__pycache__/__init__.cpython-312.pyc +0 -0
- backend/api/__pycache__/app.cpython-312.pyc +0 -0
- backend/api/__pycache__/models.cpython-312.pyc +0 -0
- backend/api/app.py +85 -0
- backend/api/models.py +11 -0
- backend/config.json +12 -0
- backend/config.py +96 -0
- backend/config_manager.py +71 -0
- backend/main.py +248 -0
- backend/requirements.txt +6 -0
- backend/utils.py +56 -0
- requirements.txt +6 -0
Dockerfile
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FROM python:3.9
|
2 |
+
|
3 |
+
# Create a non-root user and set paths
|
4 |
+
RUN useradd -m -u 1000 user
|
5 |
+
USER user
|
6 |
+
ENV PATH="/home/user/.local/bin:$PATH"
|
7 |
+
|
8 |
+
WORKDIR /app
|
9 |
+
|
10 |
+
# Copy and install dependencies
|
11 |
+
COPY --chown=user ./requirements.txt requirements.txt
|
12 |
+
RUN pip install --no-cache-dir --upgrade -r requirements.txt
|
13 |
+
|
14 |
+
# Copy the rest of the application files
|
15 |
+
COPY --chown=user . /app
|
16 |
+
|
17 |
+
# Ensure .env file exists before copying
|
18 |
+
COPY --chown=user .env /app/.env
|
19 |
+
|
20 |
+
CMD ["uvicorn", "backend.api.app:app", "--host", "0.0.0.0", "--port", "7860"]
|
21 |
+
|
backend/CurriculumManager/__init__.py
ADDED
File without changes
|
backend/CurriculumManager/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (189 Bytes). View file
|
|
backend/CurriculumManager/__pycache__/generate_curriculum.cpython-312.pyc
ADDED
Binary file (2.4 kB). View file
|
|
backend/CurriculumManager/config.json
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
{}
|
backend/CurriculumManager/generate_curriculum.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
File without changes
|
backend/LessonManager/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (185 Bytes). View file
|
|
backend/LessonManager/__pycache__/generate_daily_lesson.cpython-312.pyc
ADDED
Binary file (2.23 kB). View file
|
|
backend/LessonManager/__pycache__/generate_lesson.cpython-312.pyc
ADDED
Binary file (2.21 kB). View file
|
|
backend/LessonManager/generate_daily_lesson.py
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,38 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
File without changes
|
backend/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (171 Bytes). View file
|
|
backend/__pycache__/config.cpython-312.pyc
ADDED
Binary file (3.84 kB). View file
|
|
backend/__pycache__/config_manager.cpython-312.pyc
ADDED
Binary file (3.57 kB). View file
|
|
backend/__pycache__/main.cpython-312.pyc
ADDED
Binary file (9.02 kB). View file
|
|
backend/__pycache__/utils.cpython-312.pyc
ADDED
Binary file (2.68 kB). View file
|
|
backend/api/__init__.py
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
# Empty init file
|
backend/api/__pycache__/__init__.cpython-312.pyc
ADDED
Binary file (175 Bytes). View file
|
|
backend/api/__pycache__/app.cpython-312.pyc
ADDED
Binary file (5.64 kB). View file
|
|
backend/api/__pycache__/models.cpython-312.pyc
ADDED
Binary file (903 Bytes). View file
|
|
backend/api/app.py
ADDED
@@ -0,0 +1,85 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,12 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,96 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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()
|
backend/config_manager.py
ADDED
@@ -0,0 +1,71 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,248 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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)
|
backend/requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
ADDED
@@ -0,0 +1,56 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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
|
requirements.txt
ADDED
@@ -0,0 +1,6 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
openai
|
2 |
+
fastapi
|
3 |
+
uvicorn[standard]
|
4 |
+
pydantic
|
5 |
+
ollama
|
6 |
+
python-dotenv
|