Added: Health check option

This commit is contained in:
Luc Mcgrady 2025-06-02 11:04:54 +01:00
parent ff56bb26e3
commit 382afc1105
No known key found for this signature in database
GPG key ID: 4F3D7A0B17CC3D9C
8 changed files with 42 additions and 17 deletions

View file

@ -193,6 +193,7 @@ message DeckConfig {
reserved 39; reserved 39;
float historical_retention = 40; float historical_retention = 40;
string param_search = 45; string param_search = 45;
bool health_check = 47;
bytes other = 255; bytes other = 255;
} }

View file

@ -354,6 +354,7 @@ message ComputeFsrsParamsRequest {
repeated float current_params = 2; repeated float current_params = 2;
int64 ignore_revlogs_before_ms = 3; int64 ignore_revlogs_before_ms = 3;
uint32 num_of_relearning_steps = 4; uint32 num_of_relearning_steps = 4;
bool health_check = 5;
} }
message ComputeFsrsParamsResponse { message ComputeFsrsParamsResponse {

View file

@ -78,6 +78,7 @@ const DEFAULT_DECK_CONFIG_INNER: DeckConfigInner = DeckConfigInner {
fsrs_params_5: vec![], fsrs_params_5: vec![],
fsrs_params_6: vec![], fsrs_params_6: vec![],
desired_retention: 0.9, desired_retention: 0.9,
health_check: false,
other: Vec::new(), other: Vec::new(),
historical_retention: 0.9, historical_retention: 0.9,
param_search: String::new(), param_search: String::new(),

View file

@ -400,6 +400,7 @@ impl From<DeckConfSchema11> for DeckConfig {
desired_retention: c.desired_retention, desired_retention: c.desired_retention,
historical_retention: c.sm2_retention, historical_retention: c.sm2_retention,
param_search: c.param_search, param_search: c.param_search,
health_check: false,
other: other_bytes, other: other_bytes,
}, },
} }

View file

@ -372,6 +372,7 @@ impl Collection {
config_len, config_len,
config.fsrs_params(), config.fsrs_params(),
num_of_relearning_steps, num_of_relearning_steps,
false,
) { ) {
Ok(params) => { Ok(params) => {
println!("{}: {:?}", config.name, params.params); println!("{}: {:?}", config.name, params.params);

View file

@ -55,6 +55,7 @@ impl Collection {
/// Note this does not return an error if there are less than 400 items - /// Note this does not return an error if there are less than 400 items -
/// the caller should instead check the fsrs_items count in the return /// the caller should instead check the fsrs_items count in the return
/// value. /// value.
#[allow(clippy::too_many_arguments)]
pub fn compute_params( pub fn compute_params(
&mut self, &mut self,
search: &str, search: &str,
@ -63,6 +64,7 @@ impl Collection {
total_presets: u32, total_presets: u32,
current_params: &Params, current_params: &Params,
num_of_relearning_steps: usize, num_of_relearning_steps: usize,
health_check: bool,
) -> Result<ComputeFsrsParamsResponse> { ) -> Result<ComputeFsrsParamsResponse> {
self.clear_progress(); self.clear_progress();
let timing = self.timing_today()?; let timing = self.timing_today()?;
@ -75,7 +77,7 @@ impl Collection {
return Ok(ComputeFsrsParamsResponse { return Ok(ComputeFsrsParamsResponse {
params: current_params.to_vec(), params: current_params.to_vec(),
fsrs_items, fsrs_items,
log_loss: None log_loss: None,
}); });
} }
// adapt the progress handler to our built-in progress handling // adapt the progress handler to our built-in progress handling
@ -148,9 +150,14 @@ impl Collection {
} }
} }
let fsrs = FSRS::new(None)?; let log_loss = if health_check && *current_params != params {
let log_loss = fsrs let fsrs = FSRS::new(None)?;
.evaluate_with_time_series_splits(input, |_| true).ok().map(|eval| eval.log_loss); fsrs.evaluate_with_time_series_splits(input, |_| true)
.ok()
.map(|eval| eval.log_loss)
} else {
None
};
Ok(ComputeFsrsParamsResponse { Ok(ComputeFsrsParamsResponse {
params, params,

View file

@ -271,6 +271,7 @@ impl crate::services::SchedulerService for Collection {
1, 1,
&input.current_params, &input.current_params,
input.num_of_relearning_steps as usize, input.num_of_relearning_steps as usize,
input.health_check,
) )
} }
@ -372,7 +373,11 @@ impl crate::services::BackendSchedulerService for Backend {
enable_short_term: true, enable_short_term: true,
num_relearning_steps: None, num_relearning_steps: None,
})?; })?;
Ok(ComputeFsrsParamsResponse { params, fsrs_items, log_loss: None }) Ok(ComputeFsrsParamsResponse {
params,
fsrs_items,
log_loss: None,
})
} }
fn fsrs_benchmark( fn fsrs_benchmark(

View file

@ -179,6 +179,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
ignoreRevlogsBeforeMs: getIgnoreRevlogsBeforeMs(), ignoreRevlogsBeforeMs: getIgnoreRevlogsBeforeMs(),
currentParams: params, currentParams: params,
numOfRelearningSteps: numOfRelearningStepsInDay, numOfRelearningSteps: numOfRelearningStepsInDay,
healthCheck: $config.healthCheck,
}); });
const already_optimal = const already_optimal =
@ -196,7 +197,7 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
} else { } else {
$config.fsrsParams6 = resp.params; $config.fsrsParams6 = resp.params;
optimized = true; optimized = true;
console.log(`FSRS-test-train-split-log-loss = ${resp.logLoss}`) console.log(`FSRS-test-train-split-log-loss = ${resp.logLoss}`);
if (resp.logLoss && resp.logLoss > logLossBadThreshold) { if (resp.logLoss && resp.logLoss > logLossBadThreshold) {
setTimeout(() => alert(tr.deckConfigFsrsBadFitWarning())); setTimeout(() => alert(tr.deckConfigFsrsBadFitWarning()));
} }
@ -328,17 +329,24 @@ License: GNU AGPL, version 3 or later; http://www.gnu.org/licenses/agpl.html
{tr.deckConfigOptimizeButton()} {tr.deckConfigOptimizeButton()}
{/if} {/if}
</button> </button>
<button <label>
class="btn {checkingParams ? 'btn-warning' : 'btn-primary'}" <input type="checkbox" bind:checked={$config.healthCheck} />
disabled={!checkingParams && computing} Health check (Slow)
on:click={() => checkParams()} </label>
> {#if false}
{#if checkingParams} <!-- Can be re-enabled by some method in the future -->
{tr.actionsCancel()} <button
{:else} class="btn {checkingParams ? 'btn-warning' : 'btn-primary'}"
{tr.deckConfigEvaluateButton()} disabled={!checkingParams && computing}
{/if} on:click={() => checkParams()}
</button> >
{#if checkingParams}
{tr.actionsCancel()}
{:else}
{tr.deckConfigEvaluateButton()}
{/if}
</button>
{/if}
<div> <div>
{#if computingParams || checkingParams} {#if computingParams || checkingParams}
{computeParamsProgressString} {computeParamsProgressString}