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 {
23 feedback_history: Vec::new(),
24 }
25 }
26
27 pub fn process(&mut self, suggestion: &str, accepted: bool, context: &str) {
29 let entry = FeedbackEntry {
30 suggestion: suggestion.into(),
31 accepted,
32 context: context.into(),
33 timestamp: std::time::SystemTime::now(),
34 };
35
36 self.feedback_history.push(entry);
37
38 if self.feedback_history.len() > 1000 {
40 self.feedback_history.remove(0);
41 }
42 }
43
44 pub fn get_acceptance_rate(&self, pattern: &str) -> f64 {
46 use std::time::{Duration, SystemTime};
47
48 let now = SystemTime::now();
49 let mut weighted_sum = 0.0;
50 let mut total_weight = 0.0;
51
52 for entry in &self.feedback_history {
53 if !entry.suggestion.contains(pattern) {
54 continue;
55 }
56
57 let age_weight = now
58 .duration_since(entry.timestamp)
59 .map(|duration| {
60 let thirty_days = Duration::from_secs(60 * 60 * 24 * 30);
62 1.0 - (duration.as_secs_f64() / thirty_days.as_secs_f64()).min(0.9)
63 })
64 .unwrap_or(1.0);
65
66 let context_weight = if entry.context.is_empty() {
67 0.8
68 } else {
69 1.0
71 };
72
73 let weight = age_weight * context_weight;
74 total_weight += weight;
75 if entry.accepted {
76 weighted_sum += weight;
77 }
78 }
79
80 if total_weight == 0.0 {
81 return 0.5;
82 }
83
84 weighted_sum / total_weight
85 }
86}