a768fb8e04
Aggiunti tutti i file sorgente per la nuova applicazione desktop WPF "SynthData Pro" (namespace Dione) per la generazione dati tramite LLM locale/remoto. Inclusi: - Progetto .csproj, configurazione .NET 4.8.1, risorse e file di soluzione. - UI moderna con Material Design, sidebar, title bar custom, e navigazione tra Dashboard, Generazione Live, Impostazioni e Telemetria. - Modelli dati (AppSettings, DataProject, SchemaColumn, TelemetryLog) e layer dati SQLite con migrazione automatica. - ViewModel principali per dashboard KPI/grafici, generazione streaming, impostazioni, telemetria. - Tutte le View XAML e relativi code-behind. - Localizzazione italiana e attenzione all'usabilità. - Pronto per estensioni future (Data Designer, moduli placeholder).
303 lines
16 KiB
C#
303 lines
16 KiB
C#
using System;
|
|
using System.Windows;
|
|
using CommunityToolkit.Mvvm.ComponentModel;
|
|
using CommunityToolkit.Mvvm.Input;
|
|
using Dione.Data;
|
|
using Dione.Models;
|
|
using Microsoft.Win32;
|
|
|
|
namespace Dione.ViewModels
|
|
{
|
|
public class SettingsViewModel : ObservableObject
|
|
{
|
|
// ── API ──────────────────────────────────────────────────────────────────
|
|
|
|
private string _selectedEndpointPreset = "Custom";
|
|
public string SelectedEndpointPreset
|
|
{
|
|
get => _selectedEndpointPreset;
|
|
set { if (SetProperty(ref _selectedEndpointPreset, value) && value != "Custom") ApplyPreset(value); }
|
|
}
|
|
public string[] EndpointPresets { get; } = { "Custom", "OpenAI", "Anthropic", "Google AI", "Azure OpenAI", "LM Studio (Local)", "Ollama (Local)" };
|
|
|
|
private string _apiEndpoint = "http://127.0.0.1:1234/v1/chat/completions";
|
|
public string ApiEndpoint { get => _apiEndpoint; set => SetProperty(ref _apiEndpoint, value); }
|
|
|
|
private string _modelName = "";
|
|
public string ModelName { get => _modelName; set => SetProperty(ref _modelName, value); }
|
|
|
|
private string _apiKey = "";
|
|
public string ApiKey { get => _apiKey; set => SetProperty(ref _apiKey, value); }
|
|
|
|
private double _temperature = 0.7;
|
|
public double Temperature { get => _temperature; set => SetProperty(ref _temperature, value); }
|
|
|
|
private int _maxTokens = 2048;
|
|
public int MaxTokens { get => _maxTokens; set => SetProperty(ref _maxTokens, value); }
|
|
|
|
// ── Prompt ───────────────────────────────────────────────────────────────
|
|
|
|
private string _systemPrompt = "";
|
|
public string SystemPrompt { get => _systemPrompt; set => SetProperty(ref _systemPrompt, value); }
|
|
|
|
private string _userPrompt = "";
|
|
public string UserPrompt { get => _userPrompt; set => SetProperty(ref _userPrompt, value); }
|
|
|
|
// ── Output ───────────────────────────────────────────────────────────────
|
|
|
|
private string _outputDirectory = "";
|
|
public string OutputDirectory { get => _outputDirectory; set => SetProperty(ref _outputDirectory, value); }
|
|
|
|
private string _outputFilePrefix = "batch";
|
|
public string OutputFilePrefix { get => _outputFilePrefix; set => SetProperty(ref _outputFilePrefix, value); }
|
|
|
|
private int _maxFileSizeMb = 250;
|
|
public int MaxFileSizeMb { get => _maxFileSizeMb; set => SetProperty(ref _maxFileSizeMb, value); }
|
|
|
|
// ── Timeout ──────────────────────────────────────────────────────────────
|
|
|
|
private int _apiTimeoutSeconds = 120;
|
|
public int ApiTimeoutSeconds { get => _apiTimeoutSeconds; set => SetProperty(ref _apiTimeoutSeconds, value); }
|
|
|
|
private double _timeoutPerTokenRatio = 0.5;
|
|
public double TimeoutPerTokenRatio { get => _timeoutPerTokenRatio; set => SetProperty(ref _timeoutPerTokenRatio, value); }
|
|
|
|
// ── Verifica qualita ─────────────────────────────────────────────────────
|
|
|
|
private bool _enableQualityVerification = false;
|
|
public bool EnableQualityVerification { get => _enableQualityVerification; set => SetProperty(ref _enableQualityVerification, value); }
|
|
|
|
private bool _useSameModelForVerification = true;
|
|
public bool UseSameModelForVerification { get => _useSameModelForVerification; set => SetProperty(ref _useSameModelForVerification, value); }
|
|
|
|
private string _verificationApiEndpoint = "";
|
|
public string VerificationApiEndpoint { get => _verificationApiEndpoint; set => SetProperty(ref _verificationApiEndpoint, value); }
|
|
|
|
private string _verificationModelName = "";
|
|
public string VerificationModelName { get => _verificationModelName; set => SetProperty(ref _verificationModelName, value); }
|
|
|
|
private string _verificationApiKey = "";
|
|
public string VerificationApiKey { get => _verificationApiKey; set => SetProperty(ref _verificationApiKey, value); }
|
|
|
|
private double _revenuePerHighQualityRecord = 0.005;
|
|
public double RevenuePerHighQualityRecord { get => _revenuePerHighQualityRecord; set => SetProperty(ref _revenuePerHighQualityRecord, value); }
|
|
|
|
// ── Costi ────────────────────────────────────────────────────────────────
|
|
|
|
private double _electricityCostPerKwh = 0.25;
|
|
public double ElectricityCostPerKwh { get => _electricityCostPerKwh; set => SetProperty(ref _electricityCostPerKwh, value); }
|
|
|
|
private double _systemPowerWatt = 350;
|
|
public double SystemPowerWatt { get => _systemPowerWatt; set => SetProperty(ref _systemPowerWatt, value); }
|
|
|
|
private string _apiCostType = "Free";
|
|
public string ApiCostType { get => _apiCostType; set => SetProperty(ref _apiCostType, value); }
|
|
public string[] ApiCostTypes { get; } = { "Free", "PerCall", "PerBlock" };
|
|
|
|
private double _apiCostPerCall = 0;
|
|
public double ApiCostPerCall { get => _apiCostPerCall; set => SetProperty(ref _apiCostPerCall, value); }
|
|
|
|
private double _apiCostPerBlock = 0;
|
|
public double ApiCostPerBlock { get => _apiCostPerBlock; set => SetProperty(ref _apiCostPerBlock, value); }
|
|
|
|
private int _apiBlockSize = 1000;
|
|
public int ApiBlockSize { get => _apiBlockSize; set => SetProperty(ref _apiBlockSize, value); }
|
|
|
|
// ── Status ───────────────────────────────────────────────────────────────
|
|
|
|
private string _statusMessage = "";
|
|
public string StatusMessage { get => _statusMessage; set => SetProperty(ref _statusMessage, value); }
|
|
|
|
// ── Commands ─────────────────────────────────────────────────────────────
|
|
|
|
public RelayCommand SaveCommand { get; }
|
|
public RelayCommand BrowseOutputDirectoryCommand { get; }
|
|
public RelayCommand ResetTelemetryCommand { get; }
|
|
public RelayCommand ResetDatabaseCommand { get; }
|
|
public RelayCommand InsertDefaultBettingPromptCommand { get; }
|
|
|
|
// ── Constructor ──────────────────────────────────────────────────────────
|
|
|
|
public SettingsViewModel()
|
|
{
|
|
SaveCommand = new RelayCommand(Save);
|
|
BrowseOutputDirectoryCommand = new RelayCommand(BrowseOutputDirectory);
|
|
ResetTelemetryCommand = new RelayCommand(ResetTelemetry);
|
|
ResetDatabaseCommand = new RelayCommand(ResetDatabase);
|
|
InsertDefaultBettingPromptCommand = new RelayCommand(InsertDefaultBettingPrompt);
|
|
|
|
Load();
|
|
}
|
|
|
|
// ── Private methods ──────────────────────────────────────────────────────
|
|
|
|
public void Load()
|
|
{
|
|
try
|
|
{
|
|
var s = SynthDataDbContext.LoadSettings();
|
|
ApiEndpoint = s.ApiEndpoint;
|
|
ModelName = s.ModelName;
|
|
ApiKey = s.ApiKey;
|
|
Temperature = s.Temperature;
|
|
MaxTokens = s.MaxTokens;
|
|
SystemPrompt = s.SystemPrompt;
|
|
UserPrompt = s.UserPrompt;
|
|
OutputDirectory = s.OutputDirectory;
|
|
OutputFilePrefix = s.OutputFilePrefix;
|
|
MaxFileSizeMb = s.MaxFileSizeMb;
|
|
ApiTimeoutSeconds = s.ApiTimeoutSeconds;
|
|
TimeoutPerTokenRatio = s.TimeoutPerTokenRatio;
|
|
EnableQualityVerification = s.EnableQualityVerification;
|
|
UseSameModelForVerification = s.UseSameModelForVerification;
|
|
VerificationApiEndpoint = s.VerificationApiEndpoint;
|
|
VerificationModelName = s.VerificationModelName;
|
|
VerificationApiKey = s.VerificationApiKey;
|
|
RevenuePerHighQualityRecord = s.RevenuePerHighQualityRecord;
|
|
ElectricityCostPerKwh = s.ElectricityCostPerKwh;
|
|
SystemPowerWatt = s.SystemPowerWatt;
|
|
ApiCostType = s.ApiCostType;
|
|
ApiCostPerCall = s.ApiCostPerCall;
|
|
ApiCostPerBlock = s.ApiCostPerBlock;
|
|
ApiBlockSize = s.ApiBlockSize;
|
|
|
|
StatusMessage = "Impostazioni caricate.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StatusMessage = "Errore caricamento: " + ex.Message;
|
|
}
|
|
}
|
|
|
|
private void Save()
|
|
{
|
|
if (string.IsNullOrWhiteSpace(OutputDirectory))
|
|
{
|
|
StatusMessage = "Seleziona una cartella di output.";
|
|
return;
|
|
}
|
|
try
|
|
{
|
|
SynthDataDbContext.SaveSettings(new AppSettings
|
|
{
|
|
ApiEndpoint = ApiEndpoint,
|
|
ModelName = ModelName,
|
|
ApiKey = ApiKey,
|
|
Temperature = Temperature,
|
|
MaxTokens = MaxTokens,
|
|
SystemPrompt = SystemPrompt,
|
|
UserPrompt = UserPrompt,
|
|
OutputDirectory = OutputDirectory,
|
|
OutputFilePrefix = OutputFilePrefix,
|
|
MaxFileSizeMb = MaxFileSizeMb,
|
|
ApiTimeoutSeconds = ApiTimeoutSeconds,
|
|
TimeoutPerTokenRatio = TimeoutPerTokenRatio,
|
|
EnableQualityVerification = EnableQualityVerification,
|
|
UseSameModelForVerification = UseSameModelForVerification,
|
|
VerificationApiEndpoint = VerificationApiEndpoint,
|
|
VerificationModelName = VerificationModelName,
|
|
VerificationApiKey = VerificationApiKey,
|
|
RevenuePerHighQualityRecord = RevenuePerHighQualityRecord,
|
|
ElectricityCostPerKwh = ElectricityCostPerKwh,
|
|
SystemPowerWatt = SystemPowerWatt,
|
|
ApiCostType = ApiCostType,
|
|
ApiCostPerCall = ApiCostPerCall,
|
|
ApiCostPerBlock = ApiCostPerBlock,
|
|
ApiBlockSize = ApiBlockSize,
|
|
});
|
|
StatusMessage = "Impostazioni salvate.";
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
StatusMessage = "Errore salvataggio: " + ex.Message;
|
|
}
|
|
}
|
|
|
|
private void BrowseOutputDirectory()
|
|
{
|
|
var dlg = new System.Windows.Forms.FolderBrowserDialog
|
|
{
|
|
Description = "Seleziona la cartella di output",
|
|
SelectedPath = OutputDirectory
|
|
};
|
|
if (dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
|
|
OutputDirectory = dlg.SelectedPath;
|
|
}
|
|
|
|
private void ResetTelemetry()
|
|
{
|
|
if (MessageBox.Show("Eliminare TUTTA la telemetria?", "Conferma", MessageBoxButton.YesNo, MessageBoxImage.Warning) != MessageBoxResult.Yes)
|
|
return;
|
|
try { SynthDataDbContext.DeleteAllTelemetry(); StatusMessage = "Telemetria eliminata."; }
|
|
catch (Exception ex) { StatusMessage = "Errore: " + ex.Message; }
|
|
}
|
|
|
|
private void ResetDatabase()
|
|
{
|
|
if (MessageBox.Show("Resettare COMPLETAMENTE il database? Tutte le impostazioni e la telemetria verranno cancellate.",
|
|
"Conferma Reset", MessageBoxButton.YesNo, MessageBoxImage.Stop) != MessageBoxResult.Yes)
|
|
return;
|
|
try { SynthDataDbContext.ResetDatabase(); Load(); StatusMessage = "Database resettato."; }
|
|
catch (Exception ex) { StatusMessage = "Errore: " + ex.Message; }
|
|
}
|
|
|
|
private void InsertDefaultBettingPrompt()
|
|
{
|
|
SystemPrompt =
|
|
"Sei il nodo validatore di una blockchain per una piattaforma di scommesse decentralizzata. " +
|
|
"Il tuo compito e generare transazioni fittizie ma realistiche in formato JSON puro. " +
|
|
"Non includere testo introduttivo o conclusivo, restituisci solo un array di oggetti JSON.\n\n" +
|
|
"Regole per la generazione dei dati:\n" +
|
|
"- Ogni transazione deve avere un tx_hash esadecimale casuale di 64 caratteri e un timestamp ISO 8601.\n" +
|
|
"- bet_type puo essere solo 'singola' o 'multipla'.\n" +
|
|
"- Genera un bankroll_at_time casuale tra 100 e 5000.\n" +
|
|
"- Logica dello Stake: Se 'singola', stake_amount deve essere intero e multiplo di 5. " +
|
|
"Se 'multipla', genera confidence_level tra 0.0 e 1.0. Se confidenza tra 0.9 e 1.0, " +
|
|
"stake_amount fino al 10% del bankroll. Altrimenti sotto l'1%.\n" +
|
|
"- Includi smart_contract_log che spiega come lo smart contract ha processato i fondi.";
|
|
|
|
UserPrompt = "Genera un blocco di 5 nuove transazioni sequenziali rispettando rigorosamente le regole di business.";
|
|
|
|
StatusMessage = "Prompt blockchain betting inseriti. Ricorda di salvare.";
|
|
}
|
|
|
|
private void ApplyPreset(string preset)
|
|
{
|
|
switch (preset)
|
|
{
|
|
case "OpenAI":
|
|
ApiEndpoint = "https://api.openai.com/v1/chat/completions";
|
|
ModelName = "gpt-4o";
|
|
StatusMessage = "Preset OpenAI applicato. Inserisci la API Key.";
|
|
break;
|
|
case "Anthropic":
|
|
ApiEndpoint = "https://api.anthropic.com/v1/messages";
|
|
ModelName = "claude-3-5-sonnet-20241022";
|
|
StatusMessage = "Preset Anthropic applicato. Inserisci la API Key.";
|
|
break;
|
|
case "Google AI":
|
|
ApiEndpoint = "https://generativelanguage.googleapis.com/v1beta/openai/chat/completions";
|
|
ModelName = "gemini-2.0-flash-exp";
|
|
StatusMessage = "Preset Google AI applicato. Inserisci la API Key.";
|
|
break;
|
|
case "Azure OpenAI":
|
|
ApiEndpoint = "https://<resource>.openai.azure.com/openai/deployments/<deployment>/chat/completions?api-version=2024-02-15-preview";
|
|
ModelName = "gpt-4";
|
|
StatusMessage = "Sostituisci <resource> e <deployment>.";
|
|
break;
|
|
case "LM Studio (Local)":
|
|
ApiEndpoint = "http://127.0.0.1:1234/v1/chat/completions";
|
|
ModelName = "";
|
|
ApiKey = "";
|
|
StatusMessage = "Preset LM Studio applicato.";
|
|
break;
|
|
case "Ollama (Local)":
|
|
ApiEndpoint = "http://127.0.0.1:11434/v1/chat/completions";
|
|
ModelName = "llama3.3";
|
|
ApiKey = "";
|
|
StatusMessage = "Preset Ollama applicato.";
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
} |