llmp 0.1.0

Measures how well a local LLM setup uses its model: a recording proxy and a prompt-reuse analysis
Documentation
mod findings;
mod hash;
mod measured;
mod normalize;
mod record;
mod report;
mod table;

#[cfg(feature = "net")]
pub mod proxy;
#[cfg(feature = "net")]
pub mod tokenize;

use serde::{Deserialize, Serialize};

pub use findings::{Confidence, Finding, FindingKind};
pub use measured::{Measured, Source};
pub use normalize::{Api, Counts};
pub use record::{
    BadLine, ExchangeError, MessageDigest, Output, Params, ReadResult, Record, RequestDigest,
    RequestRecord, ResponseDigest, ResponseRecord, StreamKind, TokenCounts, ToolCall, ToolDigest,
    read_jsonl, write_jsonl,
};
pub use report::{
    CauseTotal, CompositionTotals, CountField, Coverage, Report, ServerFields, SkippedCounts, Time,
    Window,
};
pub use table::{BreakCause, Cause, Client, Composition, Loss, Row, RowKind, Shape, ToolUsage};

pub const RECORD_VERSION: u32 = 1;
pub const REPORT_VERSION: u32 = 1;

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Config {
    pub session_gap_ms: u64,
    pub thresholds: Thresholds,
}

#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Thresholds {
    pub tool_schema_tokens: u32,
    pub system_tokens: u32,
}

impl Default for Config {
    fn default() -> Self {
        Config {
            session_gap_ms: 60_000,
            thresholds: Thresholds::default(),
        }
    }
}

impl Default for Thresholds {
    fn default() -> Self {
        Thresholds {
            tool_schema_tokens: 800,
            system_tokens: 800,
        }
    }
}

pub fn analyze(records: &[Record], config: &Config) -> Report {
    let normalized = normalize::normalize_all(records);
    let table = table::build(&normalized.exchanges, config);
    let findings = findings::find(&table, config);
    report::assemble(records, &normalized, table, findings)
}