ai_rubric_grader 0.1.1 copy "ai_rubric_grader: ^0.1.1" to clipboard
ai_rubric_grader: ^0.1.1 copied to clipboard

LLM-agnostic, rubric-based automatic grading for Dart. Feed it questions, rubrics and student answers; get back structured, clamped scores with per-rubric rationale. Bring your own LLM client.

🎯 ai_rubric_grader #

LLM-agnostic, rubric-based automatic grading for Dart #

Feed it questions, rubrics and student answers β€” get back structured, clamped scores with per-rubric rationale. Bring your own LLM.

pub package pub points likes CI license: MIT


It's a small, dependency-light, pure-Dart package β€” no Flutter, no HTTP client baked in β€” so you can run it server-side (a Cloud Function, a backend, a CLI), which is where your API key belongs.

Why not just ask the model for marks? #

Asking an LLM to "grade this and give me the score" and parsing the free text is fragile: a stray line or markdown fence silently becomes a 0, and the model can hand out more points than a rubric allows. ai_rubric_grader fixes that:

Naive approach ai_rubric_grader
Output Free text, hope it parses Strict JSON, schema-guided
Totals Trust the model's sums Recomputed from your rubrics
Over-awarding Possible Clamped to [0, points]
Missing item Crash / wrong total Treated as 0, never crashes
Provider lock-in Hardcoded Any LLM via one interface
Manual criteria β€” autoGraded: false leaves them for a human

Install #

dependencies:
  ai_rubric_grader: ^0.1.1

or dart pub add ai_rubric_grader.

Usage #

import 'package:ai_rubric_grader/ai_rubric_grader.dart';

final questions = [
  Question(
    id: 'q1',
    prompt: 'What is the derivative of xΒ²?',
    answer: '2x',                       // plain text, LaTeX, transcribed handwriting…
    rubrics: const [
      Rubric(id: 'r1', description: 'Correct derivative', requirement: 'equals 2x', points: 5),
      Rubric(id: 'r2', description: 'Shows working',      requirement: 'steps shown', points: 3,
             autoGraded: false),         // left for a human
    ],
  ),
];

final grader = RubricGrader(myLlmClient);
final result = await grader.grade(questions);

print('${result.awarded}/${result.possible} (${result.percentage}%)');
for (final g in result.questionGrades) {
  for (final s in g.rubricScores) {
    print('${s.rubricId}: ${s.awarded}/${s.possible} β€” ${s.rationale}');
  }
}

Bring your own LLM #

Implement the one-method LlmClient for any provider. Request deterministic output (temperature: 0) and JSON mode where available.

OpenAI adapter (click to expand)
import 'dart:convert';
import 'package:ai_rubric_grader/ai_rubric_grader.dart';
import 'package:http/http.dart' as http;

class OpenAiClient implements LlmClient {
  OpenAiClient(this.apiKey, {this.model = 'gpt-4o-mini'});
  final String apiKey;
  final String model;

  @override
  Future<String> complete({required String system, required String user}) async {
    final res = await http.post(
      Uri.parse('https://api.openai.com/v1/chat/completions'),
      headers: {
        'Content-Type': 'application/json',
        'Authorization': 'Bearer $apiKey',
      },
      body: jsonEncode({
        'model': model,
        'temperature': 0,
        'response_format': {'type': 'json_object'},
        'messages': [
          {'role': 'system', 'content': system},
          {'role': 'user', 'content': user},
        ],
      }),
    );
    return (jsonDecode(res.body)['choices'][0]['message']['content']) as String;
  }
}

πŸ”’ Security: never embed an LLM API key in a mobile/web client β€” it ships in the binary and can be extracted. Run the grader behind your backend.

API #

Type Purpose
Rubric A criterion: description, requirement, points, autoGraded.
Question prompt, answer, rubrics; exposes totalPoints / autoGradablePoints.
RubricGrader grade(List<Question>) β†’ Future<GradingResult>.
GradingResult awarded, possible, percentage, questionGrades.
RubricScore Per-rubric awarded (clamped), possible, rationale, isFullyMet.
LlmClient The one method you implement to plug in a provider.

All models are immutable and JSON-serializable (toJson / fromJson).

Part of the Flutter Grading Toolkit:

Contributing #

Issues and PRs welcome. Run dart test before submitting.

License #

MIT Β© 2026 Muhammad Ali

0
likes
150
points
38
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

LLM-agnostic, rubric-based automatic grading for Dart. Feed it questions, rubrics and student answers; get back structured, clamped scores with per-rubric rationale. Bring your own LLM client.

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

meta

More

Packages that depend on ai_rubric_grader