Skip to content

Instantly share code, notes, and snippets.

@Ddhuet
Last active June 15, 2025 13:06
Show Gist options
  • Save Ddhuet/100a885758cbb224322ee6e0168e0d56 to your computer and use it in GitHub Desktop.
Save Ddhuet/100a885758cbb224322ee6e0168e0d56 to your computer and use it in GitHub Desktop.
/**
* Claude Index Normalization Function
*
* This module provides functions to normalize rating data, particularly useful for:
* - Teacher/evaluator ratings that suffer from central tendency bias
* - Ratings where evaluators use different parts of the scale
* - Compressed or shifted rating distributions
*
* The core function blends original ratings with normalized scores based on
* a configurable alpha parameter, with automatic adjustment for compression.
*/
/**
* Calculate the mean of an array of numbers
* @param {number[]} arr - Array of numeric values
* @return {number} - The arithmetic mean
*/
function mean(arr) {
return arr.reduce((sum, val) => sum + val, 0) / arr.length;
}
/**
* Calculate the standard deviation of an array of numbers
* @param {number[]} arr - Array of numeric values
* @return {number} - The standard deviation
*/
function stdDev(arr) {
const avg = mean(arr);
const squareDiffs = arr.map(value => Math.pow(value - avg, 2));
return Math.sqrt(squareDiffs.reduce((sum, val) => sum + val, 0) / arr.length);
}
/**
* Calculate z-scores for an array of values
* @param {number[]} arr - Array of numeric values
* @return {number[]} - Array of z-scores
*/
function zScores(arr) {
const avg = mean(arr);
const sd = stdDev(arr);
return sd !== 0
? arr.map(val => (val - avg) / sd)
: arr.map(() => 0); // Handle case where all values are the same
}
/**
* The Claude Index Normalization Function
*
* Normalizes ratings using a blended approach that respects both
* the absolute values and relative rankings within the distribution.
*
* @param {number[]} ratings - Original ratings array
* @param {number} targetMean - Desired mean for normalized distribution (default: 5.5)
* @param {number} targetStdDev - Desired standard deviation (default: 1.5)
* @param {number} alpha - Blending factor between original and normalized scores (default: 0.3)
* 0 = completely normalized, 1 = original scores
* @param {number} compressionThreshold - SD threshold for detecting compressed ratings (default: 0.5)
* @return {number[]} - Array of normalized scores
*/
function claudeIndexNormalize(
ratings,
targetMean = 5.5,
targetStdDev = 1.5,
alpha = 0.3,
compressionThreshold = 0.5
) {
// Calculate original distribution statistics
const originalMean = mean(ratings);
const originalStdDev = stdDev(ratings);
// Calculate z-scores (how many standard deviations from the mean)
const zScoreValues = zScores(ratings);
// Detect compression in the ratings distribution
// If ratings are tightly compressed, we want to rely more on the normalized distribution
const compressionFactor = Math.min(1, originalStdDev / compressionThreshold);
// Adjust alpha based on compression (compressed ratings get lower effective alpha)
const effectiveAlpha = alpha * compressionFactor;
// Generate normalized values using blended approach
return ratings.map((rating, i) => {
// Transform to target distribution
const normalizedScore = targetMean + (zScoreValues[i] * targetStdDev);
// Blend between original and normalized score based on effective alpha
return (effectiveAlpha * rating) + ((1 - effectiveAlpha) * normalizedScore);
});
}
/**
* Batch normalize multiple evaluators' ratings
*
* @param {Object[]} evaluators - Array of evaluator objects
* @param {string} evaluators[].id - Unique identifier for the evaluator
* @param {number[]} evaluators[].ratings - Array of ratings from this evaluator
* @param {Object} options - Normalization options
* @return {Object[]} - Array of evaluator objects with normalized ratings added
*/
function batchNormalize(evaluators, options = {}) {
const {
targetMean = 5.5,
targetStdDev = 1.5,
alpha = 0.3,
compressionThreshold = 0.5
} = options;
return evaluators.map(evaluator => {
const normalizedRatings = claudeIndexNormalize(
evaluator.ratings,
targetMean,
targetStdDev,
alpha,
compressionThreshold
);
return {
...evaluator,
normalizedRatings,
stats: {
originalMean: mean(evaluator.ratings),
originalStdDev: stdDev(evaluator.ratings),
normalizedMean: mean(normalizedRatings),
normalizedStdDev: stdDev(normalizedRatings)
}
};
});
}
// Export the functions
module.exports = {
claudeIndexNormalize,
batchNormalize,
mean,
stdDev,
zScores
};
/* Example import and usage
const { claudeIndexNormalize } = require('./claude-index');
// Example teacher ratings
const teacherRatings = [7, 7.5, 8, 8.5, 9];
// Apply normalization
const normalizedScores = claudeIndexNormalize(teacherRatings);
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment