Skip to main content

Signals-based assessment — map analyser signals to a rubric as observations, never grades. A human assigns every mark.

Project description

assessment-lens

Part of the lens family.

Python 3.11+ License: MIT

Signals-based assessment. Analysers generate signals about student submissions; this lens maps those signals to a rubric as observations, not grades. A lecturer reads the observations, weighs them, and assigns the mark. The AI narrates and cites; it never scores. A human stays in the loop.

assessment-lens is a lens (an assessment-aware product), not an -analyser. Analysers are assessment-agnostic signal generators; lenses sit above them. It consumes analysers (via bundle-analyser); it never generates signals. See ADR-0001.

Why "observations, not grades"

LLMs are inconsistent at the precise act of marking. So the lens keeps them off it. The deterministic signals (from analysers) are the anchor; an Observation maps a signal or two to a rubric Criterion with cited evidence, a short narration bound to that evidence, and a coverage (present / partial / absent) — which is "is the evidence there?", derived from thresholds, not a mark. There is deliberately no score/mark/weight field anywhere in the model.

Pipeline

Specification ──draft-rubric (LLM, reviewed)──▶ Rubric (criteria + mapping) + deliverables  [YAML]
Submissions root ──discover──▶ one Submission per subfolder
each Submission folder ──bundle-analyser──▶ Signals
Signals + Criteria + Deliverables ──alignment-check──▶ Observations
                                                         └─▶ cohort triage sheet + per-student reports
lecturer reads observations → assigns marks → writes feedback

assess is folder-dumb: one rubric + one folder of submission subfolders. Group/individual splits and mark-combining are handled outside (pre/post) or by running assess per folder.

Two commands

  • assess — structured rubric + a submissions folder → observations (cohort sheet + per-student reports). Add --llm for evidence-bound narration on each observation (opt-in; needs the [llm] extra + ANTHROPIC_API_KEY).
  • draft-rubric — free-form specification → a proposed structured rubric for the lecturer to review/edit before use. LLM-assisted; reads text/markdown directly and .pdf/.docx/.pptx via the [documents] extra.

Install

# from source (family layout)
uv venv && source .venv/bin/activate
uv pip install -e ".[dev]"

# pull the whole analyser stack into the same env (for `assess` to run for real):
uv pip install -e ".[dev,analysers]"

# opt-in LLM features (narration + draft-rubric):
uv pip install -e ".[llm]"     # + export ANTHROPIC_API_KEY=...

assess shells out to the bundle-analyser CLI (it must be on PATH). The [analysers] extra installs it; or point assessment-lens at an environment where it is already installed.

Quick start

# 1. author a structured rubric (or start from the example)
cp examples/data-viz-rubric.yaml my-rubric.yaml

# 2. lay out submissions: one subfolder per student/group
#    submissions/alice/{report.pdf,demo.mp4}  submissions/bob/...

# 3. assess (add --llm for narrated observations)
assessment-lens assess my-rubric.yaml submissions/ -o out/
#    -> out/cohort-sheet.csv         (row per submission × criterion, sortable)
#    -> out/reports/<id>.md          (per-student observation sheet, no marks)

# or draft a rubric from a free-form spec, then review/edit it
assessment-lens draft-rubric assignment-brief.md -o my-rubric.yaml

Rubric schema (the central contract)

assignment: "Data-Viz Project"
component: individual                 # plain label; assess ignores it
expected_deliverables:
  - id: report
    description: "Written report (~2000 words)"
    accepts: [document]               # content kinds that satisfy it
  - id: demo
    description: "≤5-min recorded demo"
    accepts: [video]
rubric:
  - id: critical-thinking
    description: "Evidence of critical engagement / analysis"
    signals_of_interest: [conversation.critical_thinking, reflection.depth]  # OPTIONAL mapping

signals_of_interest is the signal→criterion mapping, and it's optional. Pinned → deterministic coverage. Blank → alignment-check selects signals at runtime and shows its choice (near-term).

Status

v0.2. Working today:

  • ✅ Rubric load/validate; deliverable reconciliation; submission discovery
  • assess orchestration + evidence-bound observations + threshold coverage
  • ✅ cohort sheet (CSV) + per-student reports (Markdown)
  • bundle-analyser integration — verified against the real CLI output schema
  • ✅ LLM narration (assess --llm) — narrate-and-cite, bound to evidence; degrades to empty notes when the [llm] extra/key is missing
  • draft-rubric — proposes a rubric from a free-form spec (always review before use)
  • 📋 Runtime signal selection when signals_of_interest is blank — deferred

Development

ruff format . && ruff check . && pytest -v

License

MIT — see LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

assessment_lens-0.4.0.tar.gz (181.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

assessment_lens-0.4.0-py3-none-any.whl (32.5 kB view details)

Uploaded Python 3

File details

Details for the file assessment_lens-0.4.0.tar.gz.

File metadata

  • Download URL: assessment_lens-0.4.0.tar.gz
  • Upload date:
  • Size: 181.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.0

File hashes

Hashes for assessment_lens-0.4.0.tar.gz
Algorithm Hash digest
SHA256 f026505223d3bd31d1af3d9a0eb39eacc70d8fe575964d693e2d59d4d98b01ab
MD5 435ca83291f0c51f0ee7dd92d7cd1e7f
BLAKE2b-256 32bd3930314247f1ff3da06ed80bee5294c75fe0c2b749162efb8a00dd624e3b

See more details on using hashes here.

File details

Details for the file assessment_lens-0.4.0-py3-none-any.whl.

File metadata

File hashes

Hashes for assessment_lens-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 53bd625de9c81d9e2becb653f8efc122f9eab8a197f5729b7c1608e6a08c6032
MD5 140a878a7f78b533f6ded2fbe6c06a4c
BLAKE2b-256 9aa7f1b6915a4216d3f05ff3f431d4b03191e1fa5d9a0a19281505e7e078c295

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page