Skip to main content

funcvec_core/
models.rs

1use std::path::PathBuf;
2
3use serde::{Deserialize, Serialize};
4
5#[derive(Debug, Clone, Copy, PartialEq, Eq)]
6pub enum OutputFormat {
7    Table,
8    Json,
9    Markdown,
10}
11
12#[derive(Debug, Clone)]
13pub struct ReportConfig {
14    pub provider: crate::embeddings::ProviderKind,
15    pub model: Option<String>,
16    pub ollama_host: String,
17    pub allow_nonlocal_ollama_host: bool,
18    pub ollama_timeout_secs: u64,
19    pub ollama_keep_alive: Option<String>,
20    pub ollama_dimensions: Option<usize>,
21    pub ollama_truncate: bool,
22    pub model_cache_dir: Option<PathBuf>,
23    pub native_threads: Option<usize>,
24    pub threshold: f32,
25    pub top_k: usize,
26    pub min_lines: usize,
27    pub min_tokens: usize,
28    pub cache_dir: Option<PathBuf>,
29    pub allow_source_upload: bool,
30}
31
32impl Default for ReportConfig {
33    fn default() -> Self {
34        Self {
35            provider: crate::embeddings::ProviderKind::Lexical,
36            model: None,
37            ollama_host: default_ollama_host(),
38            allow_nonlocal_ollama_host: false,
39            ollama_timeout_secs: 120,
40            ollama_keep_alive: None,
41            ollama_dimensions: None,
42            ollama_truncate: true,
43            model_cache_dir: None,
44            native_threads: None,
45            threshold: 0.72,
46            top_k: 25,
47            min_lines: 3,
48            min_tokens: 12,
49            cache_dir: None,
50            allow_source_upload: false,
51        }
52    }
53}
54
55pub fn default_ollama_host() -> String {
56    std::env::var("OLLAMA_HOST").unwrap_or_else(|_| "http://127.0.0.1:11434".to_owned())
57}
58
59#[derive(Debug, Clone, Serialize, Deserialize)]
60pub struct FunctionRecord {
61    pub id: String,
62    pub name: String,
63    pub file: PathBuf,
64    pub start_line: usize,
65    pub end_line: usize,
66    pub source: String,
67    pub normalized: String,
68    pub token_count: usize,
69    pub line_count: usize,
70    pub content_hash: String,
71    pub expected_group: Option<String>,
72}
73
74#[derive(Debug, Clone, Serialize, Deserialize)]
75pub struct FunctionSummary {
76    pub id: String,
77    pub name: String,
78    pub file: PathBuf,
79    pub start_line: usize,
80    pub end_line: usize,
81    pub token_count: usize,
82    pub line_count: usize,
83    pub expected_group: Option<String>,
84}
85
86impl From<&FunctionRecord> for FunctionSummary {
87    fn from(function: &FunctionRecord) -> Self {
88        Self {
89            id: function.id.clone(),
90            name: function.name.clone(),
91            file: function.file.clone(),
92            start_line: function.start_line,
93            end_line: function.end_line,
94            token_count: function.token_count,
95            line_count: function.line_count,
96            expected_group: function.expected_group.clone(),
97        }
98    }
99}
100
101#[derive(Debug, Clone, Serialize, Deserialize)]
102pub struct ScoreBreakdown {
103    pub clone: f32,
104    pub semantic: Option<f32>,
105    pub hybrid: f32,
106    pub clone_flag: bool,
107    pub semantic_flag: bool,
108    pub hybrid_flag: bool,
109}
110
111#[derive(Debug, Clone, Serialize, Deserialize)]
112pub struct Candidate {
113    pub id: String,
114    pub left: FunctionRecord,
115    pub right: FunctionRecord,
116    pub scores: ScoreBreakdown,
117    pub reasons: Vec<String>,
118    pub expected_match: bool,
119}
120
121#[derive(Debug, Clone, Serialize, Deserialize)]
122pub struct Report {
123    pub project_root: PathBuf,
124    pub provider: String,
125    pub model: Option<String>,
126    pub functions_count: usize,
127    pub embedding_stats: EmbeddingStats,
128    pub candidates: Vec<Candidate>,
129}
130
131#[derive(Debug, Clone, Default, Serialize, Deserialize)]
132pub struct EmbeddingStats {
133    pub cache_hits: usize,
134    pub cache_misses: usize,
135    pub dimensions: Option<usize>,
136    pub elapsed_ms: u64,
137    pub model_digest: Option<String>,
138}
139
140#[derive(Debug, Clone, Serialize, Deserialize)]
141pub struct StrategyEval {
142    pub flagged: usize,
143    pub true_positives: usize,
144    pub false_positives: usize,
145    pub known_pairs: usize,
146    pub precision: f32,
147    pub recall: f32,
148    pub f1: f32,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
152pub struct EvalReport {
153    pub report: Report,
154    pub functions: Vec<FunctionSummary>,
155    pub clone: StrategyEval,
156    pub semantic: StrategyEval,
157    pub hybrid: StrategyEval,
158}
159
160#[derive(Debug, Clone, Serialize, Deserialize)]
161pub struct EvalMatrixReport {
162    pub project_root: PathBuf,
163    pub provider: String,
164    pub functions_count: usize,
165    pub known_pairs: usize,
166    pub threshold: f32,
167    pub top_k: usize,
168    pub functions: Vec<FunctionSummary>,
169    pub models: Vec<ModelEvalResult>,
170}
171
172#[derive(Debug, Clone, Serialize, Deserialize)]
173pub struct ModelEvalResult {
174    pub model: String,
175    pub status: ModelEvalStatus,
176    pub error_kind: Option<String>,
177    pub error: Option<String>,
178    pub report: Option<Report>,
179    pub clone: Option<StrategyEval>,
180    pub semantic: Option<StrategyEval>,
181    pub hybrid: Option<StrategyEval>,
182}
183
184#[derive(Debug, Clone, Serialize, Deserialize)]
185#[serde(rename_all = "snake_case")]
186pub enum ModelEvalStatus {
187    Success,
188    Failure,
189}