Skip to content

Replace placeholder quiz generation with AI service integration #3

Description

@DeFiVC

Description

The generateQuiz method in src/modules/quizzes/quiz.service.ts currently returns a hardcoded 3-question Stellar quiz regardless of courseId or module. This is the placeholder at lines 190-225:

private createPlaceholderQuestions(courseId: string, moduleId: string) {
    // Placeholder quiz generation — in production, call an LLM or content service
    return [
      { id: "q1", text: "What is the primary purpose of the Stellar network?", ... },
      { id: "q2", text: "What language are Soroban smart contracts written in?", ... },
      { id: "q3", text: "What is the minimum account balance on Stellar?", ... },
    ];
}

This should call the chainlearn-ai service's POST /generate-quiz endpoint.

What the AI service expects

Based on chainlearn-ai/src/routes/quizzes.py:

POST http://localhost:8000/generate-quiz

Request body:
{
  "user_id": "string",
  "course_id": "string",
  "module_id": "string",
  "difficulty": "beginner" | "intermediate" | "advanced",
  "num_questions": 5
}

Response body:
{
  "quiz_id": "string",
  "questions": [
    {
      "prompt": "string",
      "options": ["A", "B", "C", "D"],
      "correct_index": 2
    }
  ]
}

Implementation steps

1. Add AI_SERVICE_URL to config

In src/config/index.ts, add:

aiServiceUrl: z.string().url().default("http://localhost:8000"),

2. Create AI service client

Create src/modules/quizzes/ai-client.ts:

import { config } from "../../config/index.js";
import { logger } from "../../utils/logger.js";

interface AiQuizQuestion {
  prompt: string;
  options: string[];
  correct_index: number;
}

interface AiQuizResponse {
  quiz_id: string;
  questions: AiQuizQuestion[];
}

export async function generateQuizFromAI(params: {
  userId: string;
  courseId: string;
  moduleId: string;
  difficulty: string;
  numQuestions: number;
}): Promise<AiQuizQuestion[]> {
  const response = await fetch(`${config.aiServiceUrl}/generate-quiz`, {
    method: "POST",
    headers: { "Content-Type": "application/json" },
    body: JSON.stringify({
      user_id: params.userId,
      course_id: params.courseId,
      module_id: params.moduleId,
      difficulty: params.difficulty,
      num_questions: params.numQuestions,
    }),
  });

  if (!response.ok) {
    logger.error({ status: response.status }, "AI service quiz generation failed");
    throw new Error(`AI service returned ${response.status}`);
  }

  const data: AiQuizResponse = await response.json();
  return data.questions;
}

3. Replace placeholder in quiz.service.ts

Replace the generateQuiz method (lines 66-70):

// Before:
const generatedQuestions = this.createPlaceholderQuestions(data.courseId, data.moduleId);

// After:
let generatedQuestions;
try {
  const aiQuestions = await generateQuizFromAI({
    userId,
    courseId: data.courseId,
    moduleId: data.moduleId,
    difficulty: data.difficulty ?? "beginner",
    numQuestions: data.numQuestions ?? 5,
  });
  generatedQuestions = aiQuestions.map((q, i) => ({
    id: `q${i + 1}`,
    text: q.prompt,
    options: q.options,
    correctIndex: q.correct_index,
  }));
} catch (err) {
  logger.warn({ err }, "AI service unavailable, using placeholder questions");
  generatedQuestions = this.createPlaceholderQuestions(data.courseId, data.moduleId);
}

4. Update quiz types if needed

Check src/modules/quizzes/quiz.types.ts — the GenerateQuizBody may need difficulty and numQuestions fields.

Files to change

  • src/config/index.ts — add aiServiceUrl
  • New file: src/modules/quizzes/ai-client.ts
  • src/modules/quizzes/quiz.service.ts — replace placeholder call
  • src/modules/quizzes/quiz.types.ts — add optional fields if needed

How to test

  1. Start the AI service: cd chainlearn-ai && uvicorn src.main:app --reload
  2. Start the API: cd chainlearn-api && npm run dev
  3. Create a user and enroll in a course
  4. Call POST /api/quizzes/generate with courseId and moduleId
  5. Verify the response contains AI-generated questions, not the hardcoded Stellar questions
  6. Test fallback: stop the AI service, verify placeholder questions are returned

Metadata

Metadata

Assignees

Labels

GrantFox OSSIssue tracked in GrantFox OSSMaybe RewardedIssue may be eligible for a GrantFox rewardOfficial CampaignCampaign: Official CampaignenhancementNew feature or requestintermediateIntermediate difficultytypescriptTypeScript language

Type

No type

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions