Skip to main content

Alignmenter

PyPI version Downloads License

Persona-aligned evaluation for conversational AI

📚 Documentation • Quickstart • Quick Start Guide • CLI Reference • License


Overview

Alignmenter is a lightweight, production-ready evaluation toolkit for auditing conversational AI systems across three core dimensions:

  • 🎨 Authenticity: Does the assistant stay on-brand?
  • 🛡️ Safety: Does it avoid harmful or policy-violating outputs?
  • ⚖️ Stability: Are responses consistent across sessions?

Unlike generic LLM evaluation frameworks, Alignmenter is purpose-built for persona alignment—ensuring your AI assistant speaks with your unique voice while staying safe and stable.

Quickstart

Installation

# Clone the repository
git clone https://github.com/justinGrosvenor/alignmenter.git
cd alignmenter

# Create virtual environment
python -m venv env
source env/bin/activate  # On Windows: env\Scripts\activate

# Install with all optional extras for development
pip install -e "./alignmenter[dev]"

Install from PyPI

The core install is lightweight — no torch, no scikit-learn. It runs the default scoring path (hashed embeddings + keyword safety, optionally blended with an LLM judge) out of the box:

pip install alignmenter
alignmenter init
alignmenter run --config configs/run.yaml

Add optional extras only when you need them:

Extra Adds Use it for
alignmenter[ml] torch, sentence-transformers, transformers Local embeddings (--embedding sentence-transformer:...) and the offline safety classifier
alignmenter[calibrate] scikit-learn, numpy The persona calibration pipeline (calibrate* commands)
alignmenter[all] both of the above Everything
# Example: better local embeddings + offline safety classifier
pip install "alignmenter[ml]"
alignmenter run --config configs/run.yaml --embedding sentence-transformer:all-MiniLM-L6-v2

Offline safety classifier: [ml] includes transformers for the offline classifier (ProtectAI/distilled-safety-roberta). Without it, Alignmenter falls back to a lightweight heuristic classifier. See docs/offline_safety.md for details.

Run Your First Evaluation

# Set API key (for embedding and judge models)
export OPENAI_API_KEY="your-key-here"

# Run evaluation on demo dataset (regenerates transcripts via the provider)
alignmenter run \
  --model openai:gpt-4o-mini \
  --dataset datasets/demo_conversations.jsonl \
  --persona configs/persona/default.yaml

# Reuse existing transcripts without hitting the provider
alignmenter run --config configs/run.yaml

# View interactive HTML report
alignmenter report --last

# Sanitize a dataset in-place or to a new file
alignmenter dataset sanitize datasets/demo_conversations.jsonl --out datasets/demo_sanitized.jsonl

# Generate fresh transcripts (requires provider access)
alignmenter run --config configs/run.yaml --generate-transcripts

Output:

Loading dataset: 60 turns across 10 sessions
✓ Brand voice score: 0.82 (range: 0.78-0.86)
✓ Safety score: 0.97
✓ Consistency score: 0.94
Report written to: reports/demo/2025-11-03T00-14-01_alignmenter_run/index.html

Features

🎯 Three-Dimensional Scoring

Authenticity

  • Embedding similarity: Measures semantic alignment with persona examples
  • Trait model: Logistic regression on linguistic features (trained via calibration)
  • Lexicon matching: Enforces preferred/avoided vocabulary
  • Bootstrap CI: Statistical confidence intervals for reliability

Safety

  • Keyword classifier: Fast pattern matching for common violations
  • LLM judge: GPT-4 as a safety oracle with budget controls
  • Offline classifier: ProtectAI's distilled-safety-roberta (no API calls)
  • Fused scoring: Weighted ensemble of rule-based + model-based signals
  • Adversarial testing: Built-in safety traps in demo datasets

Stability

  • Cosine variance: Detects semantic drift across conversation turns
  • Session clustering: Identifies divergent response patterns
  • Temporal analysis: Tracks consistency over time

📊 Rich Reporting

  • Interactive HTML: Grade-based report cards with charts (Chart.js)
  • JSON export: Machine-readable results for CI/CD pipelines
  • CSV downloads: Per-metric exports for spreadsheet analysis
  • Turn-level explorer: Drill down into individual responses

🔧 Production-Ready

  • Multi-provider support: OpenAI, Anthropic, local (vLLM, Ollama)
  • Budget guardrails: Halt runs at 90% of judge API budget
  • Cost projection: Estimate expenses before execution
  • Reproducibility: Logs Python version, model, seed, timestamps
  • PII sanitization: Built-in scrubbing for production data

🚀 Developer Experience

  • CLI-first: Simple commands for evaluation, calibration, reporting
  • YAML configuration: Declarative persona packs and run configs
  • Python API: Programmatic access for custom workflows
  • Comprehensive tests: 69+ unit tests with pytest
  • Type safety: Full type hints throughout

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                        Alignmenter CLI                          │
│  alignmenter run / report / calibrate / bootstrap / sanitize    │
└─────────────────────────────────────────────────────────────────┘
                               │
                               ▼
┌─────────────────────────────────────────────────────────────────┐
│                          Runner                                 │
│  Orchestrates evaluation: load data → score → report            │
└─────────────────────────────────────────────────────────────────┘
                               │
           ┌───────────────────┼───────────────────┐
           ▼                   ▼                   ▼
   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
   │ Authenticity │    │    Safety    │    │  Stability   │
   │    Scorer    │    │    Scorer    │    │    Scorer    │
   └──────────────┘    └──────────────┘    └──────────────┘
           │                   │                   │
           │                   │                   │
   ┌──────────────┐    ┌──────────────┐    ┌──────────────┐
   │  Embeddings  │    │  LLM Judge   │    │   Cosine     │
   │  Trait Model │    │  Keywords    │    │  Variance    │
   │   Lexicon    │    │  Fusion      │    │  Clustering  │
   └──────────────┘    └──────────────┘    └──────────────┘
                               │
                               ▼
           ┌───────────────────────────────────────┐
           │         Reporting Layer               │
           │  HTML / JSON / CSV / Interactive UI   │
           └───────────────────────────────────────┘

Key Components

Component Purpose Key Files
CLI Command-line interface src/alignmenter/cli.py
Runner Orchestration engine src/alignmenter/runner.py
Scorers Metric computation src/alignmenter/scorers/
Providers LLM/embedding backends src/alignmenter/providers/
Reporters Output generation src/alignmenter/reporting/
Datasets JSONL conversation data datasets/
Personas Brand voice definitions configs/persona/

📚 Documentation

Full documentation available at docs.alignmenter.com

Quick links:


Case Studies

  • Wendy's Twitter Voice - End-to-end calibration example using the included case-study assets. (Available when running from the source repo; not included in the PyPI wheel.)

Usage Examples

Evaluate Multiple Models

# Compare GPT-4 vs Claude
alignmenter run \
  --model openai:gpt-4 \
  --compare anthropic:claude-3-5-sonnet-20241022 \
  --dataset datasets/demo_conversations.jsonl \
  --persona configs/persona/default.yaml

Custom Judge and Embeddings

# Use Claude as safety judge, local embeddings
alignmenter run \
  --model openai:gpt-4o-mini \
  --judge anthropic:claude-3-5-sonnet-20241022 \
  --embedding sentence-transformer:all-MiniLM-L6-v2 \
  --dataset datasets/demo_conversations.jsonl \
  --persona configs/persona/default.yaml

Bootstrap Synthetic Dataset

# Generate 50 conversations with adversarial traps
alignmenter bootstrap-dataset \
  --out datasets/my_test.jsonl \
  --sessions 50 \
  --safety-trap-ratio 0.15 \
  --brand-trap-ratio 0.20 \
  --seed 42

Calibrate Persona Traits

# Train trait model from labeled data
alignmenter calibrate-persona \
  --persona-path configs/persona/mybot.yaml \
  --dataset annotations.jsonl \
  --out configs/persona/mybot.traits.json \
  --epochs 300

Sanitize Production Data

# Remove PII before evaluation
alignmenter dataset sanitize prod_logs.jsonl \
  --out datasets/sanitized.jsonl \
  --no-use-hashing

Persona Configuration

Define your brand voice in YAML:

# configs/persona/mybot.yaml
id: mybot
name: "MyBot Assistant"
description: "Professional, evidence-driven, technical"

voice:
  tone: ["professional", "precise", "measured"]
  formality: "business_casual"

  # Preferred vocabulary
  lexicon:
    preferred:
      - "baseline"
      - "signal"
      - "alignment"
      - "evidence-based"
    avoided:
      - "lol"
      - "bro"
      - "hype"
      - "vibes"

# Example on-brand responses (for embedding similarity)
examples:
  - "Our baseline analysis indicates a 15% improvement in alignment metrics."
  - "The signal-to-noise ratio suggests this approach is viable."
  - "Let's establish a clear baseline before proceeding."

# Trait model weights (generated by calibration)
traits:
  weights: [0.12, -0.34, 0.08, ...]  # Learned from annotations
  vocabulary: ["baseline", "signal", ...]

API Usage

Runner coordinates transcript preparation, scoring, and report generation. It takes a RunConfig plus a list of scorers, and execute() returns the path to the timestamped report directory (JSON + HTML are written for you).

import json
from pathlib import Path

from alignmenter.runner import RunConfig, Runner
from alignmenter.scorers.authenticity import AuthenticityScorer
from alignmenter.scorers.safety import SafetyScorer
from alignmenter.scorers.stability import StabilityScorer

config = RunConfig(
    model="openai:gpt-4o-mini",
    dataset_path=Path("datasets/demo_conversations.jsonl"),
    persona_path=Path("configs/persona/default.yaml"),
)

# Pass a judge to AuthenticityScorer/SafetyScorer to blend LLM judgment in;
# omit it (as here) for a fully offline, deterministic run.
scorers = [
    AuthenticityScorer(persona_path=config.persona_path, embedding="hashed"),
    SafetyScorer(keyword_path=Path("configs/safety_keywords.yaml")),
    StabilityScorer(embedding="hashed"),
]

# generate_transcripts=False reuses recorded transcripts (no provider calls).
runner = Runner(config, scorers, generate_transcripts=False)
run_dir = runner.execute()  # -> Path to reports/<timestamp>_<run_id>/

results = json.loads((run_dir / "results.json").read_text())
primary = results["scores"]["primary"]
auth = primary["authenticity"]
print(f"Authenticity: {auth['mean']:.3f}  (basis: {auth['basis']})")
print(f"Safety:       {primary['safety']['score']:.3f}")
print(f"Stability:    {primary['stability']['stability']:.3f}")

CI/CD Integration

# .github/workflows/eval.yml
name: Persona Evaluation

on: [push, pull_request]

jobs:
  evaluate:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - uses: actions/setup-python@v4
        with:
          python-version: '3.11'

      - name: Install Alignmenter
        run: pip install alignmenter

      - name: Run Evaluation
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: |
          alignmenter run \
            --model openai:gpt-4o-mini \
            --dataset datasets/ci_test.jsonl \
            --persona configs/persona/default.yaml \
            --judge-budget 100

      - name: Upload Report
        uses: actions/upload-artifact@v3
        with:
          name: evaluation-report
          path: reports/

Development

Running Tests

# All tests
pytest

# With coverage
pytest --cov=src/alignmenter --cov-report=html

# Specific test file
pytest tests/test_scorers.py -v

Code Quality

# Type checking
mypy src/

# Linting
ruff check src/

# Formatting
black src/ tests/

Local Development

# Install in editable mode with dev dependencies
pip install -e .[dev]

# Run from source
python -m alignmenter.cli run --help

# Generate report from last run
make report-last

Roadmap

Completed ✅

  • Three-dimensional scoring (authenticity, safety, stability)
  • Multi-provider support (OpenAI, Anthropic, local models)
  • HTML report cards with interactive charts
  • Offline safety classifier (distilled-safety-roberta)
  • LLM judges for qualitative analysis
  • Budget guardrails and cost tracking
  • PII sanitization tools
  • Calibration workflow and diagnostics

In Progress 🚧

  • Multi-language support (non-English personas)
  • Batch processing optimizations
  • Additional embedding providers

Future Considerations 💭

  • Synthetic test case generation
  • Custom metric plugins
  • Advanced trait models (neural networks)

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Areas we'd love help with:

  • Additional persona packs (different brand voices)
  • Language support beyond English
  • Integration with other LLM providers
  • Performance optimizations for large datasets

License

Apache License 2.0 - see LICENSE for details.

Citation

If you use Alignmenter in research, please cite:

@software{alignmenter2024,
  title={Alignmenter: A Framework for Persona-Aligned Conversational AI Evaluation},
  author={Alignmenter Contributors},
  year={2025},
  url={https://github.com/justinGrosvenor/alignmenter},
  license={Apache-2.0}
}

Support


Made with ❤️ by the Alignmenter team

Release files for alignmenter 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for alignmenter 0.2.0
File Size Uploaded
alignmenter-0.2.0.tar.gz 127.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for alignmenter 0.2.0
File Interpreter ABI Platform
alignmenter-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 249.1 kB

Release files / alignmenter-0.2.0.tar.gz

Download URL alignmenter-0.2.0.tar.gz
Size 127.7 kB
Tags Source
SHA-256 checksum
How to use checksums
3bb7b55508de1a85b46a9a325e77335d8d03d2d9f7c6e5c6d4204c3c3dac89e2
BLAKE2b-256 checksum
How to use checksums
2e59908ad10245790239b6b7bde7f7881c5617a27c33d9ba077381edfae04c75
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release files / alignmenter-0.2.0-py3-none-any.whl

Download URL alignmenter-0.2.0-py3-none-any.whl
Size 121.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b13f71c4f96fd32592a5473b258b7c9f1d2d3e6d8aadffc477e04c3972f0260c
BLAKE2b-256 checksum
How to use checksums
c01e943f2bdb2583969782665e531d54f8a3931345120496cf4eb05a535aabd3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.15

Release history Release notifications | RSS feed

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

This release

0.2.0 This release

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

0.0.9

2 release files

0.0.8

2 release files

0.0.4

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page