vtcode_core/code/code_completion/learning/
feedback.rs1pub struct FeedbackProcessor {
3 feedback_history: Vec<FeedbackEntry>,
4}
5
6#[derive(Debug, Clone)]
7struct FeedbackEntry {
8 suggestion: String,
9 accepted: bool,
10 context: String,
11 timestamp: std::time::SystemTime,
12}
13
14impl Default for FeedbackProcessor {
15 fn default() -> Self {
16 Self::new()
17 }
18}
19
20impl FeedbackProcessor {
21 pub fn new() -> Self {
22 Self { feedback_history: Vec::new() }
23 }
24
25 pub fn process(&mut self, suggestion: &str, accepted: bool, context: &str) {
27 let entry = FeedbackEntry {
28 suggestion: suggestion.into(),
29 accepted,
30 context: context.into(),
31 timestamp: std::time::SystemTime::now(),
32 };
33
34 self.feedback_history.push(entry);
35
36 if self.feedback_history.len() > 1000 {
38 self.feedback_history.remove(0);
39 }
40 }
41
42 pub fn get_acceptance_rate(&self, pattern: &str) -> f64 {
44 use std::time::{Duration, SystemTime};
45
46 let now = SystemTime::now();
47 let mut weighted_sum = 0.0;
48 let mut total_weight = 0.0;
49
50 for entry in &self.feedback_history {
51 if !entry.suggestion.contains(pattern) {
52 continue;
53 }
54
55 let age_weight = now
56 .duration_since(entry.timestamp)
57 .map(|duration| {
58 let thirty_days = Duration::from_secs(60 * 60 * 24 * 30);
60 1.0 - (duration.as_secs_f64() / thirty_days.as_secs_f64()).min(0.9)
61 })
62 .unwrap_or(1.0);
63
64 let context_weight = if entry.context.is_empty() {
65 0.8
66 } else {
67 1.0
69 };
70
71 let weight = age_weight * context_weight;
72 total_weight += weight;
73 if entry.accepted {
74 weighted_sum += weight;
75 }
76 }
77
78 if total_weight == 0.0 {
79 return 0.5;
80 }
81
82 weighted_sum / total_weight
83 }
84}