Files
encoach_frontend_new_v2/docs/ODOO_MIGRATION_SRS_v2.md
Yamen Ahmad 11a7265460 feat(v3): restructure project + add complete frontend
- Restructure: move backend from new_project/ to backend/
- Add full React/TypeScript frontend (37 pages, 17 services, 16 type defs, 11 query hooks)
- Add docs/ with SRS specs, user stories, and workflow documentation
- Update .gitignore for new directory layout

Workflows implemented:
  WF1 User Signup, WF2 Placement Test, WF3 Exam Configuration,
  WF4 General English Exam, WF5 Course Generation,
  WF6 Entity Student Onboarding, AI Course Generation,
  Adaptive Learning Engine UI, White-Label Branding, Score Release

Made-with: Cursor
2026-04-10 17:26:42 +04:00

48 KiB

EnCoach Platform -- Odoo 19 Full Migration SRS (v2)

SUPERSEDED -- This document has been replaced by ENCOACH_ODOO19_BACKEND_SRS.md (v3.0) and ENCOACH_UNIFIED_SRS.md (v2.0). All content below is historical. The migration is complete and the system is deployed at http://5.189.151.117:8069.

Software Requirements Specification

Version: 2.0 Date: March 11, 2026 Status: Draft SUPERSEDED Supersedes: ODOO_MIGRATION_SRS.md (v1) Key change from v1: The ielts-be (FastAPI) microservice is fully eliminated. All AI/ML functionality is absorbed into custom Odoo modules.


Table of Contents

  1. Executive Summary
  2. Odoo Module Plan
  3. Data Models
  4. REST API Specification
  5. Authentication & Authorization
  6. AI/ML Services Integration
  7. Payment Integration
  8. Business Rules & Workflows
  9. Data Migration Plan
  10. Non-Functional Requirements

1. Executive Summary

1.1 Platform Overview

EnCoach is an IELTS preparation and English proficiency testing platform serving students, teachers, corporate clients, and administrators. The platform provides:

  • Full IELTS exam simulation (Reading, Listening, Writing, Speaking, Level)
  • AI-powered grading of writing and speaking responses (OpenAI GPT-4o)
  • AI-powered exam content generation (OpenAI GPT-4o)
  • AI-generated audio for listening exams (AWS Polly)
  • AI-generated video for speaking exams (ELAI)
  • Speech-to-text transcription (OpenAI Whisper)
  • AI plagiarism/detection for writing (GPTZero)
  • Personalized training recommendations (FAISS + sentence-transformers + GPT)
  • Multi-tenant entity (organization) management
  • Classroom and assignment management
  • Subscription-based access with multiple payment providers
  • Support ticket system

1.2 Migration Scope

Everything moves to Odoo 19. Both backend systems are replaced:

  1. ielts-ui API routes (Node.js, MongoDB, iron-session, Firebase Auth) -- 108 API route files, 22 MongoDB collections
  2. ielts-be (Python, FastAPI, OpenAI, Whisper, AWS Polly, ELAI, GPTZero, FAISS) -- all AI/ML workloads

What stays unchanged:

  • ielts-ui browser/frontend code (React components, Zustand stores, pages)
  • Strapi CMS (encoachcms)
  • Landing page (encoach-landing-page)

1.3 Target Architecture

ielts-ui (Next.js 14)
  └── Browser UI (unchanged)
        │
        ▼
Odoo 19 (Python + PostgreSQL)
  ├── REST API Controllers (JSON)
  ├── Business Logic (custom modules)
  ├── AI/ML Modules
  │     ├── OpenAI GPT-4o (grading + content generation)
  │     ├── OpenAI Whisper (speech-to-text, local model)
  │     ├── AWS Polly (text-to-speech for listening)
  │     ├── ELAI (AI video for speaking)
  │     ├── GPTZero (AI detection for writing)
  │     └── FAISS + sentence-transformers (training search)
  ├── PostgreSQL (all data)
  ├── Odoo Attachments (file storage)
  └── Payment Providers (Stripe, PayPal, Paymob)

There is no separate microservice. Odoo is the sole backend.


2. Odoo Module Plan

2.1 Standard Odoo Modules to Leverage

Odoo Module Usage
base / res.users / res.partner User accounts, extended with EnCoach-specific fields
payment Payment provider framework for Stripe, PayPal, Paymob
product Subscription packages as products
mail Email notifications (password reset, verification, invites)
queue_job (OCA) or ir.cron Background task processing for async AI grading

2.2 Custom Modules to Develop

Module Depends On Complexity Description
encoach_core base, mail Medium User type extensions, entity management, roles, permissions, codes, invites
encoach_exam encoach_core High Exam models for 5 modules with complex nested exercise structures
encoach_classroom encoach_core Low Group/classroom management with participant tracking
encoach_assignment encoach_core, encoach_exam Medium Assignment lifecycle (create, start, release, archive)
encoach_stats encoach_core, encoach_exam Medium Exam sessions, per-exercise statistics, score tracking
encoach_evaluation encoach_core, encoach_exam, encoach_ai Medium Async grading records for writing/speaking
encoach_training encoach_core, encoach_ai Medium Training content, walkthrough, FAISS semantic search
encoach_subscription encoach_core, product, payment Medium Packages, discounts, subscription management, Stripe/PayPal/Paymob
encoach_registration encoach_core Medium Multi-path registration (individual, corporate), codes, invites
encoach_ticket encoach_core Low Support tickets
encoach_ai base Very High Core AI services: OpenAI client, Whisper, AWS Polly, ELAI, GPTZero, FAISS
encoach_ai_grading encoach_ai, encoach_exam High Writing/speaking grading logic, rubrics, prompt templates
encoach_ai_generation encoach_ai, encoach_exam High Exam content generation for all 5 modules
encoach_ai_media encoach_ai High Audio (Polly TTS), video (ELAI), transcription (Whisper)
encoach_api All above High All REST JSON controllers for frontend consumption (~60 endpoints)

2.3 Module Dependency Graph

encoach_api
  ├── encoach_core
  │     ├── base / res.users / res.partner
  │     └── mail
  ├── encoach_exam
  │     └── encoach_core
  ├── encoach_classroom
  │     └── encoach_core
  ├── encoach_assignment
  │     ├── encoach_core
  │     └── encoach_exam
  ├── encoach_stats
  │     ├── encoach_core
  │     └── encoach_exam
  ├── encoach_evaluation
  │     ├── encoach_core
  │     ├── encoach_exam
  │     └── encoach_ai
  ├── encoach_training
  │     ├── encoach_core
  │     └── encoach_ai
  ├── encoach_subscription
  │     ├── encoach_core
  │     ├── product
  │     └── payment
  ├── encoach_registration
  │     └── encoach_core
  ├── encoach_ticket
  │     └── encoach_core
  ├── encoach_ai (core AI services)
  │     └── base
  ├── encoach_ai_grading
  │     ├── encoach_ai
  │     └── encoach_exam
  ├── encoach_ai_generation
  │     ├── encoach_ai
  │     └── encoach_exam
  └── encoach_ai_media
        └── encoach_ai

3. Data Models (Odoo Models)

All models from v1 remain unchanged. This section adds the AI/ML-related models that were previously managed by ielts-be.

Note: For the full specification of the following models, refer to Section 3 of the v1 document (ODOO_MIGRATION_SRS.md). They are identical: encoach.user, encoach.user.entity.rel, encoach.entity, encoach.role, encoach.group, encoach.exam, encoach.assignment, encoach.session, encoach.stat, encoach.evaluation, encoach.package, encoach.payment, encoach.subscription.payment, encoach.ticket, encoach.code, encoach.invite, encoach.permission, encoach.discount, encoach.walkthrough, encoach.approval.workflow

The following models are new or significantly expanded in v2:

3.1 encoach.training (expanded)

Source: MongoDB training collection (previously managed by ielts-be)

Field Type Required Description
user_id Many2one(res.users) Yes Student
created_at Datetime Yes Training generation date
exams Text (JSON) No JSON array of exam performance summaries: [{ "id", "date", "performance_comment", "detailed_summary" }]
tips Text (JSON) No JSON object with categorized tips from FAISS search
weak_areas Text (JSON) No JSON array: [{ "area": "...", "comment": "..." }]
legacy_id Char No Original MongoDB ID

3.2 encoach.training.tip (new)

Source: ielts-be pathways_2_rw_with_ids.json tips data

Field Type Required Description
tip_id Char Yes Original tip identifier
category Selection Yes ct_focus, language_for_writing, reading_skill, strategy, writing_skill, word_link, word_partners
content Text Yes Tip text content
embedding Binary No Pre-computed embedding vector (float32 array)

3.3 encoach.ai.job (new)

Tracks async AI jobs (grading, video generation).

Field Type Required Description
job_type Selection Yes writing_grading, speaking_grading, video_generation
status Selection Yes pending, in_progress, completed, error. Default: pending
user_id Many2one(res.users) No Requesting user
evaluation_id Many2one(encoach.evaluation) No Related evaluation record
input_data Text (JSON) No Serialized input for the AI task
result_data Text (JSON) No Serialized result from the AI task
error_message Text No Error details if failed
created_at Datetime Yes Job creation time
completed_at Datetime No Job completion time
retry_count Integer No Number of retries. Default: 0

3.4 encoach.elai.avatar (new)

Field Type Required Description
name Char Yes Avatar display name
avatar_code Char Yes ELAI avatar code
avatar_url Char No Avatar preview image URL
gender Selection No male, female
canvas Char No ELAI canvas ID
voice_id Char No ELAI voice ID
voice_provider Char No Voice provider name

3.5 Exam parts JSON Structure

Identical to v1. See v1 document Section 3.6.1 for the full JSON schema for Reading, Listening, Writing, Speaking, and Level exam parts.

3.6 Evaluation result JSON Structure

Identical to v1. See v1 document Section 3.10.1 for the writing and speaking grading result schemas.


4. REST API Specification

All endpoints from v1 remain unchanged in path and request/response format. The key difference is that endpoints previously marked as "proxy to ielts-be" are now handled directly by Odoo.

Note: For the full specification of all non-AI endpoints, refer to Section 4 of the v1 document. They are identical: Auth (4.1), Users (4.2), Registration/Codes (4.3), Entities (4.12), Groups (4.11), Roles (4.13), Permissions (4.14), Invites (4.7), Codes (4.8), Assignments (4.10), Sessions (4.11), Stats (4.12), Payments (4.15), Packages (4.16), Discounts (4.17), Tickets (4.18), Storage (4.19), Approval Workflows (4.21).

The following endpoints were previously "proxy to ielts-be" and are now handled directly by Odoo:

4.1 Exam Generation Endpoints

GET /api/exam/reading/{passage}

Generate a reading passage using AI.

Path params: passage = 1 | 2 | 3

Query params: topic (optional), word_count (optional, default ~500)

Response (200):

{
  "title": "The Impact of Urbanization",
  "text": "Full passage text..."
}

Implementation: Call OpenAI GPT-4o with passage-specific prompt (see Section 6.3.1).

POST /api/exam/reading/

Generate reading exercises from a passage.

Request:

{
  "text": "passage text",
  "exercises": [
    { "type": "multipleChoice", "quantity": 5 },
    { "type": "trueFalse", "quantity": 4 },
    { "type": "fillBlanks", "quantity": 3, "num_random_words": 1, "max_words": 3 }
  ],
  "difficulty": ["B1", "B2"]
}

Response (200): { "exercises": [...] }

GET /api/exam/listening/{section}

Generate a listening dialog/monologue.

Path params: section = 1 | 2 | 3 | 4

Query params: topic (optional), difficulty (optional)

Response (200):

{
  "dialog": {
    "conversation": [
      { "name": "Sarah", "gender": "female", "text": "Hello..." },
      { "name": "James", "gender": "male", "text": "Hi..." }
    ]
  }
}

Sections 1 and 3 return conversation (dialog). Sections 2 and 4 return monologue.

POST /api/exam/listening/media

Generate MP3 audio from a dialog/monologue using AWS Polly TTS.

Request:

{
  "conversation": [
    { "name": "Sarah", "gender": "female", "text": "Hello...", "voice": "Ruth" }
  ]
}

Or for monologue:

{
  "monologue": "Full monologue text..."
}

Response: MP3 binary data (Content-Type: audio/mpeg)

Implementation: Call AWS Polly with neural engine (see Section 6.4).

POST /api/exam/listening/transcribe

Transcribe audio using Whisper.

Request: Multipart form with audio file

Response (200): Dialog object (conversation or monologue text)

Implementation: Run Whisper model locally, then use GPT-4o to clean overlapping segments (see Section 6.5).

POST /api/exam/listening/instructions

Generate MP3 for listening instructions text.

Request: { "text": "instructions text" }

Response: MP3 binary data

POST /api/exam/listening/

Generate listening exercises from a dialog.

Request:

{
  "text": "transcript text",
  "exercises": [
    { "type": "multipleChoice", "quantity": 3 },
    { "type": "writeBlanksFill", "quantity": 5 }
  ],
  "difficulty": ["B1"]
}

Response (200): { "exercises": [...] }

GET /api/exam/speaking/{task}

Generate a speaking task prompt.

Path params: task = 1 | 2 | 3

Query params: topic, first_topic, second_topic, difficulty

Response (200): Speaking part content (prompts array for Part 1/3, text block for Part 2)

POST /api/exam/speaking/media

Generate AI avatar video using ELAI.

Request:

{
  "text": "Question text to speak",
  "avatar": "avatar_code"
}

Response (200): { "status": "STARTED", "result": null } (async -- poll for completion)

GET /api/exam/speaking/media/{vid_id}

Poll for video generation status.

Response (200):

{
  "status": "COMPLETED",
  "result": "https://elai-video-url..."
}

Possible statuses: STARTED, IN_PROGRESS, COMPLETED, ERROR

GET /api/exam/speaking/avatars

List available ELAI avatars.

Response (200): [ { "name": "...", "avatar_code": "...", "avatar_url": "...", "gender": "..." } ]

GET /api/exam/writing/{task}

Generate a writing task prompt.

Path params: task = 1 | 2

Query params: topic, difficulty

Response (200): Writing task prompt text

POST /api/exam/writing/{task}/attachment

Generate an academic writing Task 1 with image attachment.

Request: Multipart form with file (chart/image) and optional difficulty

Response (200): Writing task prompt with image analysis

POST /api/exam/level/

Generate level test exercises.

Request:

{
  "exercises": [
    { "type": "multipleChoice", "quantity": 10, "difficulty": "B1" },
    { "type": "fillBlanks", "quantity": 5, "text_size": 200, "topic": "education" }
  ],
  "difficulty": ["A2", "B1", "B2"]
}

Response (200): Generated exercises

GET /api/exam/level/

Get a pre-built level exam.

GET /api/exam/level/utas

Get a UTAS-format level exam.

POST /api/exam/level/import/

Import a level exam from file.

Request: Multipart form with exercises and optional solutions files

Response (200): Parsed exam object

POST /api/exam/level/custom/

Generate a custom level exam from JSON specification.

POST /api/exam/reading/import

Import a reading exam from Word/Excel file.

Request: Multipart form with exercises and optional solutions files

Response (200): Parsed exam object

POST /api/exam/listening/import

Import a listening exam from file.

4.2 Grading Endpoints

POST /api/evaluate/writing

Submit a writing answer for AI grading.

Request:

{
  "userId": 1,
  "sessionId": 20,
  "exerciseId": "uuid",
  "question": "Write about...",
  "answer": "Student's essay text...",
  "task": 1,
  "attachment": "optional-image-url"
}

Response (200): { "ok": true } (grading happens asynchronously)

Implementation: Creates encoach.evaluation and encoach.ai.job, then runs grading in a background thread (see Section 6.2).

POST /api/evaluate/speaking

Submit speaking audio for AI grading.

Request: Multipart form with userId, sessionId, exerciseId, task, and audio files (audio_1, audio_2, etc.) with corresponding question_N fields.

Response (200): { "ok": true } (grading happens asynchronously)

Implementation: Whisper transcribes each audio, then GPT-4o grades the transcript (see Section 6.2).

POST /api/evaluate/interactiveSpeaking

Submit interactive speaking (multiple Q&A pairs) for grading.

Request: Same as speaking but with question_N and audio_N pairs.

GET /api/evaluate/{sessionId}/{exerciseId}

Poll for evaluation result.

Response (200):

{
  "status": "completed",
  "result": { "...grading result..." }
}

POST /api/grading/multiple

Grade multiple short-answer exercises.

Request:

{
  "text": "passage text",
  "questions": ["Q1", "Q2"],
  "answers": ["A1", "A2"]
}

Response (200): { "exercises": [{ "id": "...", "correct": true, "correct_answer": "..." }] }

Implementation: GPT-4o evaluates each answer against the passage.

POST /api/exam/grade/summary

Generate a grading summary for a full exam session.

Request:

{
  "sections": [
    { "code": "reading", "name": "Reading", "grade": 6.5 },
    { "code": "writing", "name": "Writing", "grade": 7.0 }
  ]
}

Response (200):

{
  "sections": [
    {
      "code": "reading",
      "name": "Reading",
      "grade": 6.5,
      "evaluation": "Detailed evaluation text...",
      "suggestions": "Improvement suggestions...",
      "bullet_points": ["Focus on skimming", "Practice time management"]
    }
  ]
}

4.3 Training Endpoints

POST /api/training

Generate personalized training content.

Request:

{
  "userID": 1,
  "stats": [{ "exam_id": "...", "date": 1710000000, "performance_comment": "...", "detailed_summary": "..." }]
}

Response (200): { "id": "training-record-id" }

Implementation: Uses FAISS to find relevant tips, GPT to generate personalized recommendations (see Section 6.6).

POST /api/training/tips

Fetch contextual tips.

Request:

{
  "context": "reading passage about climate change",
  "question": "What does the author suggest?",
  "answer": "student's wrong answer",
  "correct_answer": "the correct answer"
}

Response (200): { "tips": "Personalized tip text..." }

POST /api/transcribe

Transcribe audio file.

Request: Multipart form with audio file

Response (200): Transcript text or dialog object

POST /api/batch_users

Bulk import users.

Request: { "makerID": "admin-id", "users": [{ ...userDTO }] }

Response (200): { "ok": true }

Implementation: In v1 this was handled by ielts-be (which imported into Firebase Auth + MongoDB). In v2, Odoo creates users directly in res.users. No Firebase import needed.


5. Authentication & Authorization

Identical to v1 document Section 5. Summary:

  • Recommended: Odoo native auth with JWT tokens for API access
  • 7 user roles mapped to Odoo security groups with ir.rule record rules: student, teacher, corporate, admin, developer, agent, mastercorporate

6. AI/ML Services Integration

This is the new Section 6, replacing v1's "ielts-be Integration Specification." Odoo calls all external AI services directly.

6.1 External Service Overview

Service Purpose API Type Auth Odoo Module
OpenAI GPT-4o Grading, content generation, text correction REST API API Key (Authorization: Bearer) encoach_ai
OpenAI GPT-3.5-turbo Secondary tasks (fixed text, perfect answers, summaries) REST API Same key encoach_ai
OpenAI Whisper Speech-to-text transcription Local model (Python library) N/A encoach_ai_media
AWS Polly Text-to-speech for listening exams AWS SDK (boto3) AWS Access Key + Secret encoach_ai_media
ELAI AI avatar video generation for speaking REST API Bearer token encoach_ai_media
GPTZero AI-generated text detection for writing REST API API Key (x-api-key) encoach_ai_grading
FAISS Semantic search over training tips Local library (Python) N/A encoach_training
sentence-transformers Embedding generation for FAISS Local model (Python) N/A encoach_training

6.2 Background Task Architecture

AI grading operations (writing and speaking) take 10-60 seconds. They must run asynchronously.

Recommended approach: Use Python threading within Odoo or the OCA queue_job module.

Flow:

  1. Frontend calls POST /api/evaluate/writing (or speaking)
  2. Odoo controller creates encoach.evaluation record with status = 'pending'
  3. Odoo controller creates encoach.ai.job record and launches a background thread
  4. Controller returns 200 OK immediately to the frontend
  5. Background thread: a. Calls OpenAI GPT-4o for grading (and GPTZero for AI detection in parallel) b. Updates encoach.evaluation with status = 'completed' and result JSON c. Updates encoach.ai.job with status = 'completed'
  6. Frontend polls GET /api/evaluate/{sessionId}/{exerciseId} until status is completed

Threading pattern (Odoo-compatible):

import threading
from odoo import api, SUPERUSER_ID

def _run_grading_in_background(dbname, evaluation_id, input_data):
    with api.Environment.manage():
        registry = odoo.registry(dbname)
        with registry.cursor() as cr:
            env = api.Environment(cr, SUPERUSER_ID, {})
            service = env['encoach.ai.grading']
            service.execute_grading(evaluation_id, input_data)

# In the controller:
thread = threading.Thread(
    target=_run_grading_in_background,
    args=(request.env.cr.dbname, evaluation.id, input_data)
)
thread.start()

Alternative: Use OCA queue_job for production-grade async processing with retry, monitoring, and worker management.

6.3 OpenAI Integration

6.3.1 Client Configuration

Create a service class EncoachOpenAIService in encoach_ai:

Parameter Value
Library openai (Python package)
Client AsyncOpenAI(api_key=api_key) or synchronous OpenAI
API Key Odoo system parameter encoach.openai_api_key
Response format response_format={"type": "json_object"}

6.3.2 Models Used

Task Model Temperature
Writing grading gpt-4o 0.1
Speaking grading gpt-4o 0.1
Short answer grading gpt-4o 0.1
Fixed text / perfect answer gpt-3.5-turbo 0.1
Grading summary gpt-3.5-turbo 0.1
Reading passage generation gpt-4o 0.7
Listening dialog generation gpt-4o 0.7
Writing task generation gpt-4o 0.7
Speaking task generation gpt-4o 0.7
Level exercise generation gpt-4o 0.7
Training tips gpt-4o 0.2
Whisper overlap cleanup gpt-4o 0.1

6.3.3 Writing Grading Prompts

System message:

You are a helpful assistant designed to output JSON on this format: {template}

Where {template} is:

{
  "comment": "comment about student's response quality",
  "overall": 0.0,
  "task_response": {
    "Task Achievement": { "grade": 0.0, "comment": "..." },
    "Coherence and Cohesion": { "grade": 0.0, "comment": "..." },
    "Lexical Resource": { "grade": 0.0, "comment": "..." },
    "Grammatical Range and Accuracy": { "grade": 0.0, "comment": "..." }
  }
}

User message (Task 2):

Evaluate the given Writing Task {task} response based on the IELTS grading system, ensuring a strict assessment that penalizes errors. Deduct points for deviations from the task, and assign a score of 0 if the response fails to address the question. Additionally, provide a detailed commentary highlighting both strengths and weaknesses in the response.\nQuestion: "{question}"\nAnswer: "{answer}"

User message (Task 1 General):

Same as Task 2 plus: Refer to the parts of the letter as: "Greeting Opener", "bullet 1", "bullet 2", "bullet 3", "closer (restate the purpose of the letter)", "closing greeting"

User message (Task 1 Academic with image):

The image is sent as base64 in the message content using the vision API.

Additional parallel tasks for writing grading:

Task Model Prompt
Perfect answer gpt-3.5-turbo Write a perfect answer for this IELTS writing task: "{question}"
Fixed text gpt-3.5-turbo Fix the grammatical and spelling errors in this text, keeping the original meaning: "{answer}"
AI detection GPTZero API See Section 6.7

6.3.4 Speaking Grading Prompts

System message:

You are a helpful assistant designed to output JSON on this format: {template}

Where {template} is:

{
  "comment": "extensive comment about answer quality",
  "overall": 0.0,
  "task_response": {
    "Fluency and Coherence": { "grade": 0.0, "comment": "extensive comment..." },
    "Lexical Resource": { "grade": 0.0, "comment": "..." },
    "Grammatical Range and Accuracy": { "grade": 0.0, "comment": "..." },
    "Pronunciation": { "grade": 0.0, "comment": "..." }
  }
}

User message:

Evaluate the given Speaking Part {task} response based on the IELTS grading system, ensuring a strict assessment that penalizes errors. Deduct points for deviations from the task, and assign a score of 0 if the response fails to address the question. Additionally, provide detailed commentary highlighting both strengths and weaknesses in the response.

Followed by question/answer pairs from transcription.

Task-specific instructions:

  • Task 1: Address the student as "you". If the answers are not 2 or 3 sentences long, warn the student that they should be.
  • Task 2: Address the student as "you"
  • Task 3: Address the student as "you" and pay special attention to coherence between the answers.

Speaking grading flow:

  1. Whisper transcribes each audio file
  2. GPT-4o grades the full transcript against the rubric
  3. GPT-3.5-turbo generates fixed text and perfect answer (for Task 2)
  4. Results combined into the evaluation record

6.3.5 Reading Passage Generation Prompts

System message:

You are a helpful assistant designed to output JSON on this format: {"title": "title of the text", "text": "generated text"}

User message (Passage 1):

Generate an extensive text for IELTS Reading Passage 1, of at least {word_count} words, on the topic of "{topic}". The passage should offer a substantial amount of information relevant to the chosen subject matter. It should be fairly easy and consist of multiple paragraphs. Make sure that the generated text does not contain forbidden subjects in muslim countries.

User message (Passage 2):

Same structure but: fairly hard and consist of multiple paragraphs

User message (Passage 3):

Same structure but: very hard, present different points or theories, cite different sources, and consist of multiple paragraphs

6.3.6 Listening Dialog Generation Prompts

Section 1 (conversation, 2 people):

System: {"conversation": [{"name": "name", "gender": "gender", "text": "text"}]}

User: Compose an authentic conversation between two individuals on the topic of "{topic}". Please include random names and genders. Include misleading discourse (dates, colors, etc.) and spelling of names. Make sure that the generated conversation does not contain forbidden subjects in muslim countries.

Section 2 (monologue, social):

System: {"monologue": "monologue"}

User: Generate a comprehensive monologue set in the social context of "{topic}". Make sure that the generated monologue does not contain forbidden subjects in muslim countries.

Section 3 (conversation, up to 4 people):

User: Compose an authentic and elaborate conversation between up to four individuals on the topic of "{topic}". Please include random names and genders. Make sure that the generated conversation does not contain forbidden subjects in muslim countries.

Section 4 (monologue, academic):

User: Generate a comprehensive and complex monologue on the academic subject of "{topic}". Make sure that the generated monologue does not contain forbidden subjects in muslim countries.

6.3.7 Writing Task Generation Prompts

General Task 1:

Craft a prompt for an IELTS Writing Task 1 General Training exercise that instructs the student to compose a letter based on the topic of "{topic}" of {difficulty} CEFR level difficulty. The prompt should end with "In the letter you should" followed by 3 bullet points. Make sure it does not contain forbidden subjects in muslim countries.

General Task 2:

Craft a comprehensive question of {difficulty} CEFR level difficulty like the ones for IELTS Writing Task 2 General Training that directs the candidate to delve into an in-depth analysis of contrasting perspectives on the topic of "{topic}". The question should lead to an answer with either "theories", "complicated information" or be "very descriptive" on the topic.

Academic Task 1 (with image):

Analyze the uploaded image and create a detailed IELTS Writing Task 1 Academic prompt. Describe the visual type, context, and create a prompt at {difficulty} CEFR level.

6.3.8 Speaking Task Generation Prompts

Part 1:

Craft 5 simple and single questions of easy difficulty for IELTS Speaking Part 1 that encourages candidates to delve deeply into personal experiences, preferences, or insights on the topic of "{first_topic}" and the topic of "{second_topic}". The questions should lead to the usage of 4 verb tenses (present perfect, present, past and future). Make sure that the generated question does not contain forbidden subjects in muslim countries.

Part 2:

Create a question of medium difficulty for IELTS Speaking Part 2 that encourages candidates to narrate a personal experience or story related to the topic of "{topic}". Include 3 prompts that guide the candidate. The prompts must not be questions. Also include a suffix like the ones in the IELTS exams that start with "And explain why". Make sure that the generated question does not contain forbidden subjects in muslim countries.

Part 3:

Formulate a set of 5 single questions of hard difficulty for IELTS Speaking Part 3 that encourage candidates to engage in a meaningful discussion on the topic of "{topic}". They must be 1 single question each and not be double-barreled questions. Make sure that the generated question does not contain forbidden subjects in muslim countries.

6.3.9 Level Exercise Generation Prompts

Multiple Choice:

Generate {quantity} multiple choice questions of 4 options for an english level exam of {difficulty} CEFR level. Ensure that the questions cover a range of topics such as verb tense, subject-verb agreement, pronoun usage, sentence structure, and punctuation. Make sure every question only has 1 correct answer.

Fill Blanks:

Generate a text of at least {size} words about the topic {topic}. From the generated text choose exactly {quantity} words (cannot be sequential words), replace each with {{id}}, and generate a JSON object containing: the modified text, solutions array, words array with four options per blank.

6.3.10 Retry and Validation Logic

  • Retry up to 2 times if response contains blacklisted words or missing required fields
  • Blacklisted words include topics related to religion, politics, explicit content, and culturally sensitive subjects (stored in constants)
  • Token limit: 4097 - input_token_count - 300 for max_tokens
  • All responses expected in JSON format via response_format={"type": "json_object"}

6.4 AWS Polly Integration (TTS)

Implemented in encoach_ai_media module.

Parameter Value
Library boto3 / aioboto3
Service polly
Engine neural
Output format mp3
Auth AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY (Odoo system parameters)

Available voices:

Voice Gender Accent
Danielle Female US
Gregory Male US
Kevin Male US
Ruth Female US
Stephen Male US
Arthur Male GB
Olivia Female GB
Ayanda Female ZA
Aria Female NZ
Kajal Female IN
Niamh Female IE

Conversation audio generation:

  1. For each dialog line, call Polly synthesize_speech() with the assigned voice
  2. Chunk text at sentence boundaries if > 3000 characters
  3. Concatenate all MP3 segments
  4. Append final message: "This audio recording, for the listening exercise, has finished." (voice: Stephen)

Monologue audio generation:

  1. Select a random voice
  2. Chunk text at sentence boundaries if > 3000 characters
  3. Synthesize each chunk and concatenate

6.5 Whisper Integration (STT)

Implemented in encoach_ai_media module.

Parameter Value
Library openai-whisper (local Python package)
Model size base (~1 GB, or configurable)
Model instances 4 (for parallel transcription)
Thread pool ThreadPoolExecutor(max_workers=4)
Audio resampling 16 kHz, normalized
Chunk size 30 seconds (480,000 samples) with 1/4 overlap
Options fp16=False, language='English', verbose=False
Retries 3 attempts via tenacity

Long audio handling:

  1. Split audio into 30-second chunks with 25% overlap
  2. Transcribe each chunk independently
  3. Use GPT-4o to remove duplicated words at chunk boundaries
  4. Join cleaned segments into final transcript

Audio-to-dialog conversion:

After transcription, use GPT-4o to determine whether the transcript is a conversation or monologue and output structured JSON:

You are a helpful assistant designed to output JSON on either one of these formats:
1 - {"dialog": [{"name": "name", "gender": "gender", "text": "text"}]}
2 - {"dialog": "text"}

A transcription of an audio file will be provided to you. Based on that transcription you will need to determine whether the transcription is a conversation or a monologue. If it is a conversation, output format 1. If it is a monologue, output format 2.

6.6 ELAI Integration (AI Video)

Implemented in encoach_ai_media module.

Parameter Value
Base URL https://apis.elai.io/api/v1/videos
Auth Bearer token (Odoo system parameter encoach.elai_token)

Video generation flow:

  1. POST /api/v1/videos -- Create video with avatar, text, voice
  2. POST /api/v1/videos/render/{video_id} -- Start rendering
  3. Poll GET /api/v1/videos/{video_id} -- Check status (ready, failed, or in progress)
  4. Return video URL when ready

Avatar configuration: Stored in encoach.elai.avatar model (avatar codes, voice IDs, voice providers).

6.7 GPTZero Integration (AI Detection)

Implemented in encoach_ai_grading module.

Parameter Value
Endpoint https://api.gptzero.me/v2/predict/text
Auth x-api-key header (Odoo system parameter encoach.gptzero_api_key)

Request:

{
  "document": "student's writing text",
  "version": "",
  "multilingual": false
}

Response fields used:

  • class_probabilities -- probability scores for human/AI/mixed
  • predicted_class -- human, ai, or mixed
  • sentences[].highlight_sentence_for_ai -- boolean per sentence

Result stored in evaluation: "ai_detection": { "probability": 0.12, "predicted_class": "human" }

6.8 FAISS + Sentence-Transformers (Training)

Implemented in encoach_training module.

Parameter Value
Embeddings model sentence-transformers/all-MiniLM-L6-v2
Index type faiss.IndexFlatL2 (one per category)
Top-K results 5

Categories:

Category Description
ct_focus Critical thinking focus tips
language_for_writing Language for writing tips
reading_skill Reading skills tips
strategy Test strategy tips
writing_skill Writing skills tips
word_link Word linking tips
word_partners Word partner/collocation tips

Index files: Store as Odoo attachments or on disk:

  • {category}_tips_index.faiss -- FAISS index file per category
  • tips_metadata.pkl -- Metadata mapping index positions to tip content

Query flow:

  1. Encode user query using sentence-transformers: embedding = model.encode([query])
  2. Search FAISS index: distances, indices = index.search(embedding, top_k=5)
  3. Retrieve tip content from metadata
  4. Pass tips + user performance data to GPT for personalized recommendations

Training content generation flow:

  1. Receive user's exam stats (performance comments, detailed summaries)
  2. Use GPT to identify weak areas and generate training queries
  3. For each query, search FAISS index to find relevant tips
  4. Use GPT to generate personalized recommendations based on tips + performance
  5. Store result in encoach.training

6.9 Topic and Content Constants

Maintain in encoach_ai module as constants or configuration records:

Topics for content generation:

  • TOPICS -- General IELTS topics (education, technology, environment, health, etc.)
  • TWO_PEOPLE_SCENARIOS -- Listening Section 1 scenarios
  • SOCIAL_MONOLOGUE_CONTEXTS -- Listening Section 2 contexts
  • FOUR_PEOPLE_SCENARIOS -- Listening Section 3 scenarios
  • ACADEMIC_SUBJECTS -- Listening Section 4 subjects

Difficulty levels: ["A1", "A2", "B1", "B2", "C1", "C2"]

Blacklisted words: List of culturally sensitive terms that trigger retry if found in AI-generated content (religion, politics, explicit content, etc.)

6.10 Python Dependencies

Add to the Odoo server's Python environment:

Package Version Purpose
openai >= 1.50 OpenAI API client (GPT-4o, GPT-3.5)
openai-whisper latest Local Whisper model for STT
boto3 >= 1.34 AWS SDK for Polly TTS
faiss-cpu >= 1.7 FAISS vector search
sentence-transformers >= 3.0 Embeddings for FAISS
httpx >= 0.27 HTTP client for ELAI, GPTZero
tiktoken >= 0.7 Token counting for OpenAI
librosa >= 0.10 Audio processing for Whisper
soundfile >= 0.12 Audio file I/O
numpy >= 1.26 Numerical operations
tenacity >= 8.2 Retry logic for API calls
torch >= 2.0 Required by Whisper and sentence-transformers

Server requirements for Whisper: The Odoo server needs at least 4 GB RAM for the Whisper base model and sentence-transformers model. Consider running Whisper on a GPU for better performance, or use the OpenAI Whisper API instead of local inference.

6.11 Configuration (Odoo System Parameters)

Parameter Key Description Example
encoach.openai_api_key OpenAI API key sk-...
encoach.aws_access_key_id AWS access key AKIA...
encoach.aws_secret_access_key AWS secret key wJal...
encoach.elai_token ELAI API token Bearer ...
encoach.gptzero_api_key GPTZero API key ...
encoach.whisper_model_size Whisper model size base (or small, medium, large)
encoach.whisper_workers Number of Whisper worker threads 4
encoach.grading_temperature Temperature for grading prompts 0.1
encoach.generation_temperature Temperature for content generation 0.7
encoach.tips_temperature Temperature for training tips 0.2

7. Payment Integration

Identical to v1 document Section 7. Summary:

  • Stripe: Checkout session creation, webhook handling, subscription extension
  • PayPal: Order creation, capture, subscription update
  • Paymob: Intention creation, transaction webhook verification
  • Subscription logic: extend subscriptionExpirationDate on successful payment; propagate to entity members for corporate

8. Business Rules & Workflows

Identical to v1 document Section 8, with one addition:

8.1-8.7 (Unchanged from v1)

See v1 for: Registration flow, Subscription management, Entity licensing, Assignment lifecycle, Grading polling, Corporate payment activation, User change propagation.

8.8 AI Content Moderation (New)

All AI-generated content must be validated before being returned to the user:

  1. Blacklist check: Scan generated text against the blacklisted words list
  2. Retry logic: If blacklisted words are found, regenerate with the same prompt (up to 2 retries)
  3. JSON validation: Verify the AI response is valid JSON with all required fields
  4. Score validation: For grading, verify all scores are between 0.0 and 9.0
  5. Content length: For passages, verify minimum word count is met

8.9 Batch User Import (Updated)

In v1, batch import was proxied to ielts-be (which imported into Firebase Auth). In v2:

  1. Admin uploads CSV/Excel with user data
  2. Odoo parses the file and creates res.users records directly
  3. Generates temporary passwords and sends welcome emails
  4. Creates registration codes and group assignments
  5. No Firebase Auth involvement

9. Data Migration Plan

9.1 Migration Strategy

Perform a one-time data migration from both data sources:

  1. MongoDB (used by ielts-ui) -> PostgreSQL
  2. MongoDB (used by ielts-be) -> PostgreSQL (evaluation records, training data)
  3. Firebase Auth users -> Odoo res.users

9.2 Collection-to-Model Mapping

Identical to v1 Section 9.2, with additional ielts-be collections:

ielts-be MongoDB Collection Odoo Model Notes
evaluation encoach.evaluation Grading records with result JSON
training encoach.training Training content

9.3 Additional Migration: AI Assets

Asset Source Target
FAISS index files ielts-be ./faiss/ directory Odoo server filesystem or ir.attachment
Tips metadata tips_metadata.pkl encoach.training.tip model records
Tips source data pathways_2_rw_with_ids.json encoach.training.tip model records
Avatar config conf.json, avatars.json encoach.elai.avatar model records
Whisper model Downloaded at runtime Odoo server filesystem

9.4 Migration Script Requirements & Import Order

Identical to v1 Section 9.3 and 9.4, with the addition of:

  1. encoach.training.tip (from tips JSON)
  2. encoach.elai.avatar (from avatar config JSON)
  3. FAISS index rebuild (re-embed tips into FAISS after import)

10. Non-Functional Requirements

10.1-10.6 (Unchanged from v1)

See v1 for: API response format, CORS, file storage, performance targets, scalability, security.

10.7 AI/ML Performance Requirements (New)

Operation Target Response Time Notes
Reading passage generation < 15s Single GPT-4o call
Listening dialog generation < 15s Single GPT-4o call
Listening MP3 generation < 30s Multiple Polly calls + concatenation
Writing task generation < 10s Single GPT-4o call
Speaking task generation < 10s Single GPT-4o call
Level exercise generation < 20s Multiple GPT-4o calls
Writing grading (async) < 30s total Parallel: GPT-4o grading + GPTZero + perfect answer + fixed text
Speaking grading (async) < 60s total Sequential: Whisper transcription + GPT-4o grading
Short answer grading < 10s Single GPT-4o call
Transcription (1 min audio) < 15s Local Whisper
FAISS query < 1s Local computation
Video generation (async) 1-5 min ELAI rendering; poll for completion

10.8 AI/ML Scalability (New)

  • Whisper model requires ~1 GB RAM per instance (4 instances = 4 GB)
  • sentence-transformers model requires ~500 MB RAM
  • FAISS indices are small (< 100 MB total)
  • OpenAI API has rate limits -- implement request queuing if needed
  • AWS Polly has a 3000-character limit per request -- chunking is already handled
  • Consider GPU acceleration for Whisper if transcription volume is high

10.9 AI/ML Monitoring (New)

  • Log all OpenAI API calls with model, token usage, response time, and cost
  • Log all Polly synthesis calls with character count
  • Log all ELAI video generation requests with status and duration
  • Log all Whisper transcription jobs with audio duration and processing time
  • Alert on repeated grading failures (> 3 consecutive errors)
  • Track OpenAI API spend against budget thresholds

10.10 Logging, Testing (Unchanged from v1)

See v1 Sections 10.7 and 10.8.


Appendix A: Exercise Type Reference

Identical to v1 Appendix A.

Appendix B: Grading Rubric Details

Identical to v1 Appendix B.

Appendix C: Environment Variables

Updated to include all AI/ML service credentials:

Variable Description Example
ENCOACH_JWT_SECRET JWT signing secret Random 256-bit string
OPENAI_API_KEY OpenAI API key sk-...
AWS_ACCESS_KEY_ID AWS access key for Polly AKIA...
AWS_SECRET_ACCESS_KEY AWS secret key for Polly wJal...
ELAI_TOKEN ELAI API bearer token ...
GPT_ZERO_API_KEY GPTZero API key ...
WHISPER_MODEL_SIZE Whisper model size base
STRIPE_SECRET_KEY Stripe secret key sk_live_...
STRIPE_WEBHOOK_SECRET Stripe webhook signing secret whsec_...
PAYPAL_CLIENT_ID PayPal client ID AX...
PAYPAL_CLIENT_SECRET PayPal client secret EL...
PAYPAL_ACCESS_TOKEN_URL PayPal OAuth URL https://api.paypal.com/v1/oauth2/token
PAYMOB_API_KEY Paymob API key ZXlK...
PAYMOB_SECRET Paymob webhook secret ...

Appendix D: Glossary

Identical to v1 Appendix D, with additions:

Term Definition
Whisper OpenAI's speech-to-text model, run locally on the Odoo server
Polly AWS text-to-speech service for generating listening exam audio
ELAI AI video generation service for creating speaking exam avatar videos
GPTZero AI text detection service for identifying AI-generated writing submissions
FAISS Facebook AI Similarity Search -- vector search library for finding relevant training tips
sentence-transformers Python library for generating text embeddings used with FAISS

Appendix E: Custom Odoo Module Summary

Module Complexity Key Models Key Services External APIs
encoach_core Medium User extensions, Entity, Role, Permission, Code, Invite Registration, entity management --
encoach_exam High Exam (5 modules), Exercise structures Exam CRUD, import/export --
encoach_classroom Low Group Group management --
encoach_assignment Medium Assignment Assignment lifecycle --
encoach_stats Medium Session, Stat Stats tracking, PDF export --
encoach_evaluation Medium Evaluation, AI Job Async grading coordination --
encoach_training Medium Training, Training Tip FAISS search, tip generation --
encoach_subscription Medium Package, Payment, Subscription Payment, Discount Subscription management Stripe, PayPal, Paymob
encoach_registration Medium Code, Invite Multi-path registration --
encoach_ticket Low Ticket Ticket CRUD --
encoach_ai Very High -- OpenAI client, prompt management, retry logic OpenAI API
encoach_ai_grading High -- Writing grading, speaking grading, short answer grading OpenAI, GPTZero
encoach_ai_generation High -- Reading/listening/writing/speaking/level generation OpenAI
encoach_ai_media High ELAI Avatar Polly TTS, Whisper STT, ELAI video AWS Polly, ELAI, Whisper (local)
encoach_api High -- REST JSON controllers (~60 endpoints) --