Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clear memory states during bulk action if item is None #3717

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

user1823
Copy link
Contributor

Prevents issues like https://forums.ankiweb.net/t/suggestion-copy-card-debug-info-button/54206/10 and #3634

If item is None, the previous code uses the card state to infer memory states, which leads to a vicious cycle that keeps changing the memory states at every reschedule if desired retention and historical retention are not the same.

@L-M-Sherlock, WDYT?

@user1823
Copy link
Contributor Author

user1823 commented Jan 11, 2025

I just noticed that the FSRS Helper add-on uses compute_memory_state for updating the memory states while Anki uses update_memory_state for bulk actions. So, my patch won't work when rescheduling cards using the add-on (by selecting cards in the browser and hitting Update memory states & reschedule). Any suggestions for that?

Basically, the goal is that the card should get memory state when item is None only during reviewing. In all other conditions, the memory state should not be calculated if item is None.

@L-M-Sherlock
Copy link
Contributor

Does the problem mentioned in https://forums.ankiweb.net/t/suggestion-copy-card-debug-info-button/54206/10 still exist after #3634? @Luc-Mcgrady, could you help me confirm it?

@Luc-Mcgrady
Copy link
Contributor

Luc-Mcgrady commented Jan 12, 2025

I'm not sure what fixed it, but it seems fixed now even on the main branch? Could have been fixed even earlier since I noticed revlogs don't update on reschedule.

Main branch + this branch:
image

Last release:
image

@user1823
Copy link
Contributor Author

What happens if you

  • use different values for desired retention and historical retention,
  • set the ignore cards reviewed before to a future date,
  • make a minor modification to the parameters,
  • enable Reschedule cards on change, and then
  • save the deck options?

With and without this change

@Luc-Mcgrady
Copy link
Contributor

Luc-Mcgrady commented Jan 13, 2025

Future ignore-reviews-before :

  • without (release) HR = 0.9 DR = 0.83:
    image
  • without (main branch) HR = 0.9 DR = 0.83:
    image
  • with:
    • HR = 0.9 DR = 0.83
      image
    • HR = 0.5 DR = 0.7 ( same memory state ✅ )
      image
  • without (main branch (again)) HR = 0.5 DR = 0.7 :
    image

I'm sorry if I missed the point of the PR and just checked if it fixed my card 😅
LGTM

@user1823
Copy link
Contributor Author

user1823 commented Jan 13, 2025

Something doesn't look right. With the changes in this PR, I expected the card to have no memory states and interval to be the same as that before rescheduling.

Just to confirm, did you use Anki's "Reschedule cards on change" and not the helper add-on's rescheduling feature?


In case you are wondering why the interval should not change after rescheduling, here is the reason:

The goal of this PR is not to fix the intervals. It is to prevent them from becoming too high or too low by repeated rescheduling in cases where item is None.

To simulate a case with item = None, I asked you to set a future ignore date.

To fix the intervals when they have already increased, we need to fix the root cause. In your case, it requires setting the ignore before date correctly.

@Luc-Mcgrady
Copy link
Contributor

Yes I did use reschedule cards on change changing the value slightly as you asked.
If ignore reviews before is in the future then I doubt having my specific card would matter for this?

@user1823
Copy link
Contributor Author

If ignore reviews before is in the future then I doubt having my specific card would matter for this?

You are right, it doesn't matter. But, I don't know how to build from source code. So, some help in testing would be appreciated.

Also see edits to my comment above.

@Luc-Mcgrady
Copy link
Contributor

Luc-Mcgrady commented Jan 13, 2025

[rslib/src/scheduler/fsrs/memory_state.rs:84:13] &items[0] = (
    CardId(
        1662864375170,
    ),
    Some(
        FsrsItemForMemoryState {
            item: FSRSItem {
                reviews: [
                    FSRSReview {
                        rating: 2,
                        delta_t: 0,
                    },
                    // ...
                    FSRSReview {
                        rating: 3,
                        delta_t: 63,
                    },
                ],
            },
            starting_state: Some(
                MemoryState {
                    stability: 0.9999996,
                    difficulty: 2.0842972,
                },
            ),
        },
    ),
)
[rslib/src/scheduler/fsrs/memory_state.rs:84:13] ignore_before = TimestampMillis(
    1741824000000,
)

ignore reviews before doesn't empty the revlogs while not re-training.

Is not being able to build from source something I can help with?
https://github.com/ankitects/anki/blob/main/docs/development.md#building-from-source

@user1823
Copy link
Contributor Author

ignore reviews before doesn't empty the revlogs while not re-training.

That seems to be a bug (provided that the ignore before date is in future).

Is not being able to build from source something I can help with?

I never really tried to set that up. Thanks for the offer, but let me try first.

@user1823
Copy link
Contributor Author

The latest changes try to fix the issue you highlighted (ignore reviews before doesn't empty the revlogs while not re-training if ignore before date is set to a future date.)

The test failure is not related to my changes.

Can you please test this again? I didn't succeed building Anki from source code. It was showing some network error. I will try again later.

@user1823

This comment was marked as outdated.

@Luc-Mcgrady
Copy link
Contributor

image
Seems to work now 👍

@user1823
Copy link
Contributor Author

user1823 commented Jan 13, 2025

The test failure is not related to my changes.

It actually might be, but I really don't understand why. In this test, how can my changes cause the item to be None? @L-M-Sherlock, sorry for disturbing but your help will be appreciated.

// cards with a single review-type entry also get memory states from revlog
// rather than card states
let item = fsrs_item_for_memory_state(
&fsrs,
vec![RevlogEntry {
ease_factor: 2500,
interval: 100,
..revlog(RevlogReviewKind::Review, 100)
}],
TimestampSecs::now(),
0.9,
0.into(),
)?
.unwrap();
assert!(item.item.reviews.is_empty());
card.set_memory_state(&fsrs, Some(item), 0.9)?;
assert_int_eq(
card.memory_state,
Some(FsrsMemoryState {
stability: 99.999954,
difficulty: 5.840841,
}),
);
Ok(())
}

@Luc-Mcgrady
Copy link
Contributor

Luc-Mcgrady commented Jan 13, 2025

[rslib/src/scheduler/fsrs/params.rs:279:9] entry.id.0 = 0
[rslib/src/scheduler/fsrs/params.rs:279:9] ignore_revlogs_before.0 = 0
[rslib/src/scheduler/fsrs/params.rs:282:9] user_graded = true
[rslib/src/scheduler/fsrs/params.rs:282:9] within_cutoff = false
thread 'scheduler::fsrs::memory_state::tests::bypassed_learning_is_handled' panicked at rslib/src/scheduler/fsrs/memory_state.rs:401:10:
called `Option::unwrap()` on a `None` value

its because the revlogs ID is 0

@user1823
Copy link
Contributor Author

user1823 commented Jan 13, 2025

because the revlogs ID is 0

But, how can that be? The following should set it to be 100 days before today.

revlog(RevlogReviewKind::Review, 100)

@Luc-Mcgrady
Copy link
Contributor

// params.rs line 432
    const NEXT_DAY_AT: TimestampSecs = TimestampSecs(86400 * 100);

the revlogs id's are based on 100 days in the future, just put an extra 0 on there

@user1823
Copy link
Contributor Author

Thanks Luc for all the help in debugging and testing.

@dae, this is ready for a final review now.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants