///|
pub(all) struct BenchmarkCase {
name : String
description : String
documents : Array[String]
expected_findings : Int
} derive(Debug, Eq)
///|
pub fn benchmark_cases() -> Array[BenchmarkCase] {
[
{
name: "mixed-clinical",
description: "Chinese-English identifiers in one outpatient note",
documents: benchmark_fixture(),
expected_findings: 15,
},
{
name: "long-note",
description: "Repeated synthetic discharge-note paragraphs",
documents: [long_synthetic_note(4)],
expected_findings: 20,
},
{
name: "structured-fields",
description: "Key-value fields used by ETL pipelines",
documents: [
"姓名=张三\n电话=13800138000\n邮箱=zhang@example.com\n住院号=MRN-778899\n地址=北京市海淀区中关村1号",
],
expected_findings: 5,
},
]
}
///|
pub fn long_synthetic_note(repetitions : Int) -> String {
let paragraph = "患者:张三;身份证:110101199003071234;电话:13800138000;出生日期:1990-01-02;邮箱:zhang@example.com。\n"
let builder = StringBuilder()
let count = if repetitions < 0 { 0 } else { repetitions }
for _ in 0.. BenchmarkCase? {
for item in benchmark_cases() {
if item.name == name {
return Some(item)
}
}
None
}
///|
pub fn benchmark_case_names() -> Array[String] {
benchmark_cases().map(fn(item) { item.name })
}
///|
pub fn benchmark_case_summary(item : BenchmarkCase) -> String {
[
"name=\{item.name}",
"description=\{item.description}",
"documents=\{item.documents.length()}",
"characters=\{item.documents.fold(init=0, (sum, text) => sum + text.char_length())}",
"expected_findings=\{item.expected_findings}",
].join("\n")
}
///|
pub fn benchmark_catalog_summary() -> String {
benchmark_cases().map(benchmark_case_summary).join("\n\n")
}
///|
pub fn run_benchmark_case(
item : BenchmarkCase,
repetitions : Int,
config : RedactionConfig,
) -> BenchmarkResult raise DeidError {
benchmark_once(item.name, item.documents, repetitions, config)
}
///|
pub fn run_all_benchmarks(
repetitions : Int,
config : RedactionConfig,
) -> Array[BenchmarkResult] raise DeidError {
benchmark_cases().map(item => run_benchmark_case(item, repetitions, config))
}
///|
pub fn benchmark_results_text(results : Array[BenchmarkResult]) -> String {
results.map(benchmark_summary).join("\n\n")
}
///|
pub fn benchmark_results_json(results : Array[BenchmarkResult]) -> String {
"[" + results.map(benchmark_to_json).join(",") + "]"
}
///|
pub fn benchmark_findings_delta(
item : BenchmarkCase,
result : BenchmarkResult,
) -> Int {
result.findings - item.expected_findings * result.repetitions
}
///|
pub fn benchmark_catalog_valid() -> Bool {
benchmark_cases().all(fn(item) {
!item.name.is_empty() && !item.documents.is_empty()
})
}