use crate::types::ProblemClass;
use crate::ReasonError;
pub async fn classify_problem(problem: &str) -> Result<ProblemClass, ReasonError> {
let result = classify_by_keywords(problem);
Ok(result)
}
pub fn classify_by_keywords(problem: &str) -> ProblemClass {
let lower = problem.to_lowercase();
let question_starters = [
"why ",
"why does",
"how does",
"what is",
"what are",
"what's the",
"can you explain",
"describe how",
"trade-off",
"tradeoff",
"pros and cons",
"compared to",
"versus",
"vs ",
];
let is_question = question_starters.iter().any(|q| lower.contains(q));
let is_how_would = lower.contains("how would")
|| lower.contains("how to add")
|| lower.contains("how can we")
|| lower.contains("how do you");
if is_question && !is_how_would {
let arch_terms = [
"architecture",
"design",
"trade-off",
"tradeoff",
"pattern",
"approach",
"decision",
"structure",
"versus",
"vs ",
];
if arch_terms.iter().any(|t| lower.contains(t)) {
return ProblemClass::Architecture;
}
return ProblemClass::Explanation;
}
let scores = [
(
ProblemClass::BugFix,
&[
"bug", "fix", "broken", "error", "crash", "wrong", "fail", "issue", "debug",
][..],
),
(
ProblemClass::Refactor,
&[
"refactor",
"clean",
"simplify",
"restructure",
"rename",
"extract",
],
),
(
ProblemClass::Performance,
&[
"slow",
"optimize",
"performance",
"latency",
"throughput",
"bottleneck",
],
),
(
ProblemClass::TestWriting,
&[
"test",
"coverage",
"assert",
"spec",
"unit test",
"integration test",
],
),
(
ProblemClass::Architecture,
&[
"architecture",
"design",
"pattern",
"structure",
"approach",
"trade-off",
],
),
(
ProblemClass::NewFeature,
&[
"implement",
"create",
"feature",
"endpoint",
"module",
"component",
],
),
(
ProblemClass::Explanation,
&["explain", "understand", "describe", "clarify", "meaning"],
),
];
let mut best = ProblemClass::Unknown;
let mut best_score = 0usize;
for (class, keywords) in &scores {
let score = keywords.iter().filter(|kw| lower.contains(*kw)).count();
if score > best_score {
best_score = score;
best = *class;
}
}
if best == ProblemClass::Unknown && is_how_would {
best = ProblemClass::NewFeature;
}
best
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn keyword_classification() {
assert_eq!(
classify_by_keywords("fix this broken test"),
ProblemClass::BugFix
);
assert_eq!(
classify_by_keywords("refactor the authentication module"),
ProblemClass::Refactor
);
assert_eq!(
classify_by_keywords("optimize the database query performance"),
ProblemClass::Performance
);
assert_eq!(
classify_by_keywords("implement a new endpoint for user profiles"),
ProblemClass::NewFeature
);
assert_eq!(
classify_by_keywords("explain how the routing works"),
ProblemClass::Explanation
);
assert_eq!(
classify_by_keywords("write unit tests for the parser"),
ProblemClass::TestWriting
);
assert_eq!(
classify_by_keywords("design the architecture for the new service"),
ProblemClass::Architecture
);
}
#[test]
fn ambiguous_defaults_to_strongest() {
assert_eq!(
classify_by_keywords("fix this error in the code"),
ProblemClass::BugFix
);
}
#[test]
fn question_patterns_classify_correctly() {
assert_eq!(
classify_by_keywords("Why does car-reason use memgine skills for reasoning actions instead of a hardcoded pipeline?"),
ProblemClass::Explanation,
);
assert_eq!(
classify_by_keywords("What are the trade-offs of this design?"),
ProblemClass::Architecture,
);
assert_eq!(
classify_by_keywords(
"How would you add action-aware routing so simple actions use small models?"
),
ProblemClass::NewFeature,
);
}
}