Skip to main content

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.

Three 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 + a provider — ANTHROPIC_API_KEY by default, or a local Ollama via ASSESSMENT_LENS_PROVIDER=ollama).
  • 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.
  • serve — opt-in HTTP API ([serve] extra) so a desktop shell / UI can drive the lens: same /health + /manifest contract as the analysers, role: lens. Binds to 127.0.0.1; set ASSESSMENT_LENS_AUTH_TOKEN to require a bearer token on the assessment routes.

Install

# from PyPI
pip install assessment-lens

# 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

Submissions are analysed sequentially (one bundle-analyser run each), so budget accordingly for large cohorts — e.g. 300 submissions × 30 s ≈ 2.5 h. A submission that fails to analyse is recorded as an error row in the cohort sheet and never aborts the run; re-run just that one with --only <id> once fixed.

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.5. Working today:

  • ✅ Rubric load/validate; deliverable reconciliation; submission discovery
  • assess orchestration + evidence-bound observations + threshold coverage; per-submission fault isolation (one failure never aborts the cohort)
  • ✅ cohort sheet (CSV, spreadsheet-injection-safe) + 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
  • ✅ multi-provider LLM — Anthropic by default; local Ollama or any OpenAI-compatible endpoint via ASSESSMENT_LENS_PROVIDER
  • draft-rubric — proposes a rubric from a free-form spec (always review before use)
  • ✅ cohort-relative distinctiveness ([distinctiveness] extra) — three comparison spaces; neutral, never a verdict
  • serve ([serve] extra) — HTTP face for the desktop shell, optional bearer-token auth via ASSESSMENT_LENS_AUTH_TOKEN
  • 📋 Runtime signal selection when signals_of_interest is blank — deferred

Development

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

License

MIT — see LICENSE.

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.5.2.tar.gz (188.2 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.5.2-py3-none-any.whl (34.5 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: assessment_lens-0.5.2.tar.gz
  • Upload date:
  • Size: 188.2 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.5.2.tar.gz
Algorithm Hash digest
SHA256 902638f3a93edb6a2f44a52aa2eb663f7ee004254f80c5d5e80a16d468b638c3
MD5 6647126fd3f27d8930c6212eec5d09ca
BLAKE2b-256 14835e800a7aa05f0d0bca43726b6db852de9ca3fc927c5de46c700f557d2169

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for assessment_lens-0.5.2-py3-none-any.whl
Algorithm Hash digest
SHA256 b9b1744b8e2e303ad2e8db1eb8a4a4a42fbd0a0c10d9078f8d1b6e3c4cb72937
MD5 cbfed3e705ea2e2ba075a990798c8569
BLAKE2b-256 b505768501e0d3e8cd07d96e1f0ceffe586931ae545526a75b95f56fc0d080eb

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.5.2 This release

2 files

0.5.1

2 files

0.5.0

2 files

0.4.0

2 files

0.3.0

2 files

0.2.0

2 files

Supported by

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