///|
pub enum CliFormat {
Text
Markdown
Json
Csv
JsonLines
} derive(Debug, Eq, ToJson)
///|
pub enum CliRequest {
Demo
Eval(
qrels_path~ : String,
run_path~ : String,
format~ : CliFormat,
cutoffs~ : Array[Int],
threshold~ : Int,
gain~ : GainScheme
)
Validate(qrels_path~ : String, run_path~ : String, format~ : CliFormat)
Compare(
qrels_path~ : String,
baseline_path~ : String,
candidate_path~ : String,
cutoff~ : Int
)
Inspect(qrels_path~ : String, run_path~ : String)
} derive(Debug, ToJson)
///|
fn cli_flag_value(args : Array[String], flag : String) -> String? {
for index in 1.. Result[Int, String] {
Ok(@strconv.from_str(value)) catch {
_ => Err("invalid integer for \{flag}: \{value}")
}
}
///|
fn cli_parse_cutoffs(value : String) -> Result[Array[Int], String] {
let values : Array[Int] = []
for piece in value.split(",") {
let trimmed = piece.trim(chars=" \t\r")
if trimmed.is_empty() {
continue
}
let parsed = match cli_parse_int(trimmed.to_owned(), "--cutoffs") {
Ok(number) => number
Err(error) => return Err(error)
}
values.push(parsed)
}
if values.is_empty() {
Err("--cutoffs must contain at least one integer")
} else {
Ok(normalize_cutoffs(values))
}
}
///|
fn cli_parse_format(value : String) -> Result[CliFormat, String] {
match value {
"text" => Ok(Text)
"markdown" => Ok(Markdown)
"json" => Ok(Json)
"csv" => Ok(Csv)
"jsonl" => Ok(JsonLines)
_ =>
Err(
"unsupported format: \{value} (expected text, markdown, json, csv, or jsonl)",
)
}
}
///|
fn cli_parse_gain(value : String) -> Result[GainScheme, String] {
match value {
"linear" => Ok(GainScheme::linear())
"exp2" => Ok(GainScheme::exp2())
_ => Err("unsupported gain: \{value} (expected linear or exp2)")
}
}
///|
fn cli_required(args : Array[String], flag : String) -> Result[String, String] {
match cli_flag_value(args, flag) {
Some(value) => Ok(value)
None => Err("missing required flag \{flag}")
}
}
///|
pub fn parse_cli_request(args : Array[String]) -> Result[CliRequest, String] {
if args.length() <= 1 {
return Ok(Demo)
}
let command = args[1]
match command {
"demo" => Ok(Demo)
"eval" => {
let qrels_path = match cli_required(args, "--qrels") {
Ok(value) => value
Err(error) => return Err(error)
}
let run_path = match cli_required(args, "--run") {
Ok(value) => value
Err(error) => return Err(error)
}
let format = match cli_flag_value(args, "--format") {
Some(value) =>
match cli_parse_format(value) {
Ok(parsed) => parsed
Err(error) => return Err(error)
}
None => Text
}
let cutoffs = match cli_flag_value(args, "--cutoffs") {
Some(value) =>
match cli_parse_cutoffs(value) {
Ok(parsed) => parsed
Err(error) => return Err(error)
}
None => default_cutoffs()
}
let threshold = match cli_flag_value(args, "--threshold") {
Some(value) =>
match cli_parse_int(value, "--threshold") {
Ok(parsed) => parsed
Err(error) => return Err(error)
}
None => 1
}
let gain = match cli_flag_value(args, "--gain") {
Some(value) =>
match cli_parse_gain(value) {
Ok(parsed) => parsed
Err(error) => return Err(error)
}
None => GainScheme::linear()
}
Ok(Eval(qrels_path~, run_path~, format~, cutoffs~, threshold~, gain~))
}
"validate" => {
let qrels_path = match cli_required(args, "--qrels") {
Ok(value) => value
Err(error) => return Err(error)
}
let run_path = match cli_required(args, "--run") {
Ok(value) => value
Err(error) => return Err(error)
}
let format = match cli_flag_value(args, "--format") {
Some(value) =>
match cli_parse_format(value) {
Ok(parsed) => parsed
Err(error) => return Err(error)
}
None => Markdown
}
Ok(Validate(qrels_path~, run_path~, format~))
}
"compare" => {
let qrels_path = match cli_required(args, "--qrels") {
Ok(value) => value
Err(error) => return Err(error)
}
let baseline_path = match cli_required(args, "--baseline") {
Ok(value) => value
Err(error) => return Err(error)
}
let candidate_path = match cli_required(args, "--candidate") {
Ok(value) => value
Err(error) => return Err(error)
}
let cutoff = match cli_flag_value(args, "--cutoff") {
Some(value) =>
match cli_parse_int(value, "--cutoff") {
Ok(parsed) => Int::max(parsed, 1)
Err(error) => return Err(error)
}
None => 10
}
Ok(Compare(qrels_path~, baseline_path~, candidate_path~, cutoff~))
}
"inspect" => {
let qrels_path = match cli_required(args, "--qrels") {
Ok(value) => value
Err(error) => return Err(error)
}
let run_path = match cli_required(args, "--run") {
Ok(value) => value
Err(error) => return Err(error)
}
Ok(Inspect(qrels_path~, run_path~))
}
_ => Err("unknown command '\{command}'")
}
}