# Bicorder Classifier Integration Guide ## Overview This guide explains how to integrate the cluster classification system into the Bicorder web application to provide: 1. **Real-time cluster prediction** as users fill out diagnostics 2. **Smart form selection** (short vs. long form based on classification confidence) 3. **Visual feedback** showing protocol family positioning ## Design Philosophy **Version-based compatibility**: The model includes a `bicorder_version` field. The classifier checks that versions match. When bicorder.json structure changes: 1. Increment the version number in bicorder.json 2. Retrain the model with `python3 export_model_for_js.py` 3. The new model will have the updated version This ensures the web app and model stay in sync without complex backward compatibility. ## Files - `bicorder_model.json` - Trained model parameters (5KB, embed in app) - `bicorder-classifier.js` - JavaScript implementation - `bicorder-classifier.d.ts` - TypeScript type definitions ## Quick Start ### 1. Copy Model File Copy `bicorder_model.json` to your web app's public/static assets: ```bash cp bicorder_model.json ../path/to/bicorder/public/ ``` ### 2. Install Classifier Copy the JavaScript module to your source directory: ```bash cp bicorder-classifier.js ../path/to/bicorder/src/lib/ cp bicorder-classifier.d.ts ../path/to/bicorder/src/lib/ ``` ### 3. Basic Usage ```javascript import { loadClassifier } from './lib/bicorder-classifier.js'; // Load model once at app startup const classifier = await loadClassifier('/bicorder_model.json'); // As user fills in diagnostic form function onDimensionChange(dimensionName, value) { const currentRatings = getCurrentFormValues(); // Your form state const result = classifier.predict(currentRatings); console.log(`Cluster: ${result.clusterName}`); console.log(`Confidence: ${result.confidence}%`); console.log(`Recommend: ${result.recommendedForm} form`); updateUI(result); } ``` ## Integration Patterns ### Pattern 1: Progressive Classification Display Show classification results as the user fills out the form: ```javascript // React/Svelte component example function DiagnosticForm() { const [ratings, setRatings] = useState({}); const [classification, setClassification] = useState(null); useEffect(() => { if (Object.keys(ratings).length > 0) { const result = classifier.predict(ratings); setClassification(result); } }, [ratings]); return (
{classification && ( )}
); } ``` ### Pattern 2: Smart Form Selection Automatically switch between short and long forms: ```javascript function DiagnosticWizard() { const [ratings, setRatings] = useState({}); function handleDimensionComplete(dimension, value) { const newRatings = { ...ratings, [dimension]: value }; setRatings(newRatings); // Check if we should switch forms const result = classifier.predict(newRatings); if (result.recommendedForm === 'long' && currentForm === 'short') { showFormSwitchPrompt( 'Your protocol shows characteristics of both families. ' + 'Would you like to use the detailed form for better classification?' ); } } return
; } ``` ### Pattern 3: Short Form Optimization Only ask the 8 most discriminative dimensions for quick classification: ```javascript const shortFormDimensions = classifier.getKeyDimensions(); // Returns: // [ // 'Design_elite_vs_vernacular', // 'Entanglement_flocking_vs_swarming', // 'Design_static_vs_malleable', // 'Entanglement_obligatory_vs_voluntary', // 'Entanglement_self-enforcing_vs_enforced', // 'Design_explicit_vs_implicit', // 'Entanglement_sovereign_vs_subsidiary', // 'Design_technical_vs_social', // ] function ShortForm() { return (

Quick Classification (8 questions)

{shortFormDimensions.map(dim => ( ))}
); } ``` ### Pattern 4: Readiness Check Check if user has provided enough data for reliable classification: ```javascript function ClassificationStatus() { const assessment = classifier.assessShortFormReadiness(ratings); if (!assessment.ready) { return (

Need {assessment.keyDimensionsTotal - assessment.keyDimensionsProvided} more key dimensions for reliable classification ({assessment.coverage}% complete)

); } return ; } ``` ## UI Components ### Classification Indicator Visual indicator showing cluster and confidence: ```javascript function ClassificationIndicator({ cluster, confidence, completeness }) { const color = cluster === 1 ? '#2E86AB' : '#A23B72'; return (
{cluster === 1 ? 'Relational/Cultural' : 'Institutional/Bureaucratic'}
{confidence}% confidence
{completeness}% of dimensions provided
); } ``` ### Spectrum Visualization Show protocol position on the relational ↔ institutional spectrum: ```javascript function SpectrumVisualization({ ldaScore, distanceToBoundary }) { // Scale LDA score to 0-100 for display // Typical range is -4 to +4 const position = ((ldaScore + 4) / 8) * 100; const boundaryZone = distanceToBoundary < 0.5; return (
Relational/Cultural
Institutional/Bureaucratic
{boundaryZone && (
Boundary
)}
); } ``` ## Form Selection Logic ### When to Use Short Form - Initial protocol scan - User wants quick classification - Protocol clearly fits one family (confidence > 60%, distance > 0.5) ### When to Use Long Form - Protocol near boundary (distance < 0.5) - Low confidence (< 60%) - User wants detailed analysis - Research/documentation purposes ### Recommended Flow ``` User starts diagnostic ↓ Show short form (8 key dimensions) ↓ Calculate partial classification ↓ Is confidence > 60% AND completeness > 75%? ↓ YES ↓ NO Show result Offer long form "For better accuracy, complete full diagnostic?" ``` ## API Reference ### `predict(ratings, options)` Main classification function. **Parameters:** - `ratings`: Object mapping dimension names to values (1-9) - `options.detailed`: Return detailed information (default: true) **Returns:** ```javascript { cluster: 1 | 2, clusterName: "Relational/Cultural" | "Institutional/Bureaucratic", confidence: 0-100, completeness: 0-100, recommendedForm: "short" | "long", // If detailed: true ldaScore: number, distanceToBoundary: number, dimensionsProvided: number, dimensionsTotal: 23, keyDimensionsProvided: number, keyDimensionsTotal: 8 } ``` ### `explainClassification(ratings)` Generate human-readable explanation. **Returns:** String with explanation text ### `getKeyDimensions()` Get the 8 most discriminative dimensions for short form. **Returns:** Array of dimension names ### `assessShortFormReadiness(ratings)` Check if enough key dimensions are provided. **Returns:** ```javascript { ready: boolean, keyDimensionsProvided: number, keyDimensionsTotal: 8, coverage: 0-100, missingKeyDimensions: string[] } ``` ## Testing Test the classifier with example protocols: ```javascript import { BicorderClassifier } from './bicorder-classifier.js'; import modelData from './bicorder_model.json'; const classifier = new BicorderClassifier(modelData); // Test 1: Clearly institutional const institutional = { 'Design_elite_vs_vernacular': 1, 'Entanglement_obligatory_vs_voluntary': 1, 'Entanglement_flocking_vs_swarming': 1, }; console.log(classifier.predict(institutional)); // Expected: Cluster 2, high confidence // Test 2: Clearly relational const relational = { 'Design_elite_vs_vernacular': 9, 'Entanglement_obligatory_vs_voluntary': 9, 'Entanglement_flocking_vs_swarming': 9, }; console.log(classifier.predict(relational)); // Expected: Cluster 1, high confidence // Test 3: Boundary case const boundary = { 'Design_elite_vs_vernacular': 5, 'Entanglement_obligatory_vs_voluntary': 5, }; console.log(classifier.predict(boundary)); // Expected: Recommend long form ``` ## Performance - Model size: ~5KB (negligible) - Classification time: < 1ms - No network calls needed (runs entirely client-side) - Works offline once model is loaded ## Next Steps 1. Integrate classifier into existing bicorder form 2. Design UI components for classification display 3. Add user preference for form selection 4. Consider adding classification to protocol browsing/search 5. Export classification data with completed diagnostics ## Questions? See the demo in `bicorder-classifier.js` for working examples, or test with: ```bash node bicorder-classifier.js ```