TheDocumentation Index
Fetch the complete documentation index at: https://mintlify.com/vruizz22/innova-ai-engine/llms.txt
Use this file to discover all available pages before exploring further.
exerciseGenerator worker creates new math exercises on demand in response to teacher requests. When a teacher asks for additional practice material on a specific subdomain, the backend enqueues a GenerateExercisesMessage to the exercise-generate-queue. The worker receives it, resolves the subdomain and its parent topic from Postgres, fetches human-readable error descriptions for the requested error codes, and calls HaikuExerciseGenerator — a Claude Haiku (claude-haiku-4-5) adapter that uses forced generate_exercises tool_use to produce up to 10 fully structured exercises in a single LLM call. Each generated exercise is deduplicated against existing problems and persisted to Postgres with IRT parameters, solution steps, and target error codes. A cost event is recorded after every invocation.
Trigger & configuration
Queue
SQS exercise-generate queue
ARN from env
ARN from env
SQS_EXERCISE_GENERATE_ARNLambda settings
Timeout: 300 s · Memory: 512 MB
Handler:
Handler:
src.pipeline.exercise_generator.handler| Setting | Value |
|---|---|
batchSize | 1 |
functionResponseType | ReportBatchItemFailures |
Batch size is fixed at 1 because each message triggers a multi-call LLM job (one Haiku tool-use call) followed by per-exercise Postgres writes. Processing more than one request concurrently in the same Lambda invocation would conflate costs and make partial-failure tracking ambiguous.
SQS message body — GenerateExercisesMessage
The subdomain for which exercises should be generated (e.g.
ALG-LINEAR-EQ). The worker resolves this to a subdomain_id and its parent topic_id in Postgres.Target school grade level, between
1 and 12 inclusive. Passed to the generator so Claude can calibrate difficulty and vocabulary.One or more error codes from the taxonomy that the generated exercises should specifically address. At least one entry is required.
Number of exercises to generate, between
1 and 10 inclusive.Optional trace identifier for log correlation. Defaults to an empty string.
Execution flow
Resolve subdomain and topic
The service calls
repo.load_subdomain(subdomain_code) to retrieve the subdomain_id and description. If the subdomain is not found but target_error_codes is non-empty, a fallback lookup via repo.load_subdomain_for_error_code(first_code) is attempted and logged as a warning.If neither lookup succeeds, a terminal SubdomainNotFoundError is raised — the message is not retried.Similarly, repo.topic_id_for_subdomain(subdomain_id) must return a valid topic; if not, a terminal GeneratorError is raised.Fetch error descriptions
repo.load_error_descriptions(target_error_codes) retrieves human-readable descriptions for the requested error codes. These are passed alongside the codes so Claude’s prompt is semantically grounded rather than relying on opaque identifiers.Call HaikuExerciseGenerator
HaikuExerciseGenerator.generate(...) makes a single claude-haiku-4-5 call with:max_tokens: 4096temperature: 1.0(creative generation)cache_control: ephemeralon the static system prompttool_choice: {"type": "tool", "name": "generate_exercises"}to force structured output
GenerateExercisesTool payload containing up to count exercises.Deduplicate and persist
For each generated exercise,
repo.problem_exists(problem_latex, subdomain_id) checks for an exact duplicate before inserting. Duplicates are skipped and logged. Non-duplicate exercises are written to Postgres via repo.persist_exercise(...) with all IRT and metadata fields.Generated exercise schema — GeneratedExercise
The exercise problem rendered in LaTeX. Must be non-empty.
The canonical correct answer in LaTeX. Must be non-empty.
Ordered list of solution steps in LaTeX, suitable for display in a step-by-step walkthrough.
IRT 2PL discrimination parameter. Seeded by the model in
[0.5, 3.0]; recalibrated nightly by nightlyIrt once the exercise accumulates ≥50 attempts.IRT 2PL difficulty parameter. Seeded by the model in
[-3.0, 3.0]; recalibrated nightly.Error codes from the taxonomy that this exercise is designed to elicit or test.
Claude Haiku tool_use
The generator makes a single Anthropic API call per message using forcedtool_use:
cache_control: ephemeral annotation on the system prompt means all calls from the same warm Lambda container reuse the cached system block, reducing token billing for repeated teacher requests.
If the model returns a tool_use block but the payload fails Pydantic validation, the generator logs a warning and returns an empty exercise list — the message is completed successfully with zero persisted exercises.
Worker-level outcome — GenerateExercisesResult
Partial batch failure handling
The handler distinguishes between two failure modes:| Exception | Behaviour |
|---|---|
GeneratorError (terminal) | Message is not added to batchItemFailures. It is silently dropped — no retry. |
| Any other exception | {"itemIdentifier": message_id} is added to batchItemFailures. SQS redelivers the message. |