- I meant “99% of what LSTM can do”, just in case you misunderstood. Like, relative to LSTM, not as some sort of absolute metric.
- There will be a “Better optimization (uses GPU)” toggle or something like that in deck options. At the moment I don’t know if it will require an Nvidia GPU or if AMD will work too.
Later I’m going to show a graph like these: Calibration of different FSRS versions - Album on Imgur. I’ll add FSRS-7 there. FSRS-7 should be very accurate, on average. Aka I can’t guarantee that it will be great for every single user, but on average, across thousands of users, it will be accurate. I mean, even FSRS-6 is pretty good. Just keep in mind that this graph doesn’t tell you about worst-case scenarios for the most unlucky users.
Ah yes, that makes sense. I did misunderstand this.
Could this not be GPU independent? E.g. my computer uses an intel graphics card and I’d love to have the full optimization available (if you need me for testing purposes, we can probably arrange that).
Regarding the graph: If I understand this correctly, your graph should essentially be like the FSRS Calibration graph from Search Stats Extended, except that yours is for the average of your data sample (multiple people) and mine is from my own data. Aside from the lower part of the prediction (stuff that isn’t around 95 %) the current FSRS-6 is already doing a great job for me:
But does the LSTM as a first step optimization potentially improve the lower predicted retention?
Could this not be GPU independent?
It will probably display a warning like “WARNING: GPU not detected” or “GPU isn’t suitable for optimization” or something. It can run on the CPU, but it will take dozens of minutes to several hours, depending on the number of reviews.
But does the LSTM as a first step optimization potentially improve the lower predicted retention?
We’ll see once I finish some more runs.
Not ideal. But if it’s just a few minutes and the results worth it, I’d be willing to do it.
That being said: I don’t know why it needs a specific GPU (or gpu manifacturer) but if there is something I can do to add support for intel based GPUs, feel free to ping me!
Because of Nvidia’s CUDA. Then again, we’ll see, maybe Jarrett can implement LSTM in Rust in a way that CUDA is not a strict requirement.
Also, remember, this whole toggle will be optional. It’s a “hey, do you want to throw more compute at the problem to get better parameters?” toggle.
Say, would Intel Arc Graphics make the cut
![]()
I have hundreds of thousands of reviews, that is assuming you have raised the number of reviews recognized per card from 64 to 1000+.
Uh…no idea, honestly. Again, we’ll see whether Jarrett can implement LSTM in Rust in a way that doesn’t rely on Nvidia’s CUDA. If it works, well, I guess you will be the guinea pig, lol.
Oh, and it will likely be slower and more buggy than using an Nvidia GPU or an AMD GPU.
One more thing. On top of using LSTM as a teacher, there will be another way of improving FSRS’s optimization: just run it for longer. More precisely, enabling the “Better optimization” feature will increase the number of epochs used to optimize FSRS. Number of epochs means roughly “how many times does FSRS see every review?”. 8 will be the standard, and better optimization will use 40. This will further improve the resulting parameters at the cost of time. “Better optimization” will take advantage of both ways of improving optimization.
@DerIshmaelite @Anon_0000
Some updates.
- FSRS-7 is done and will hopefully be merged into the fsrs-rs crate soon. Then it’s up to Anki devs to implement it. No LSTM-as-teacher as I mentioned above, but I’ve got much more exciting news anyway
- Remember Suggestion to Damien: Migrating to an NN (Neural Net) - #20 by Expertium?
I’m working on making this neural net more efficient so that it can be used in Anki without requiring a GPU or massive amounts of storage. As proof-of-concept it has been integrated into @sound’s fork: GitHub - JSchoreels/anki: Anki's shared backend and web components, and the Qt frontend · GitHub. The inefficient version, that is. The efficient version is under development.
RWKV can run into two modes: “forgetting curve” and “immediate”, the latter being more accurate. “Immediate” might as well be called “anarchy”: there is no interval-based scheduling. Probability of recall can go up or down as time goes on, and it’s calculated, well, immediately. So in that mode using Anki will be more like sorting all of your cards by p(recall) in ascending order and reviewing cards you are least likely to recall first. But you won’t know whether next time you see this card will be tomorrow or in 10 years.
Upsides of using RWKV:
- It’s much more accurate than FSRS-7 when it comes to predicting the probability of recall, and FSRS-7 is already more accurate than FSRS-6
- Parameters are frozen, so there won’t be any “Optimize” button. Which means one less thing for users to worry about. No regular optimization, no sync issues.
- No need to show parameters.
- No need for hand-written learning steps, granted I expect a lot of users to use learning steps anyway. Same goes for FSRS-7 btw.
- You can use the “forgetting curve” mode for more old school interval-based scheduling, or “immediate” mode for something more akin to shuffling literal cards in a literal deck, except shuffling is done by a neural net that is a genius at figuring out how likely you are to recall a card.
Downsides:
- No difficulty distribution graphs, but who cares
- We’ll have to either remove the simulator or make it vastly more complex
About the extra load on the Anki servers: extra numbers (RWKV counterparts to difficulty and stability) can be recalculated locally, I don’t think we need to sync them.
In Sound’s fork the inefficient version requires ~1.8 GB of extra storage for the average Anki user with 20k cards and 15k notes and ~109 GB for the biggest monster in the 10k dataset who has 1.2 million cards with almost 1 million notes. And these are active cards aka reviewed at least once. Don’t ask me how someone has 1.2M active cards, I have no freakin’ clue.
With my current version, it’s ~14 MB of extra storage for the average user and ~900 MB for the monster, and I can bring these numbers further down by 1.5x-2x more. And of course, I’ll make sure that the efficient version works fast on the CPU, no GPU required.
EDIT: ~6 MB for the average user and ~395 MB for the monster now. This is the limit for now. I may reduce storage requirements further in the future, but no guarantees.
EDIT 2: ~4 MB for the average user and ~200 ~256 MB for the monster now.
EDIT 3: ~3 MB for the average user and ~110 ~176 MB for the monster now. That’s it. I don’t think I can push it any lower without sacrificing too much accuracy.
EDIT 4: nvm, every time I say “This is the limit”, turns out I can push it further, lol. Currently at ~1.6 MB for the average user and ~103 for the monster, and I can likely push it further to 1.3 and 83, respectively. We’re getting close to FSRS-7: FSRS-7 needs three 32-bit floats for D, S_long ands S_short, so 96 bits per card. At 256 bits per card, RWKV is now getting comparable to FSRS-7 (well, granted RWKV’s note states are 3x larger than its card states, and FSRS doesn’t have note states), and 224 bits is in sight.
EDIT 5: 144 bits. Holy shit. I’m shocked that this is possible. We’re now looking at <1 MB for the average user and <50 MB for the monster. The storage problem has been solved.
Thank you for this update, those are exciting news!
You say one wouldn’t know when the card would be due. How does this work, though? Anki would need to decide if the card is being shown or not today based on some metric (like due date), no?
Unless: the entire deck is “due” every day and you start to review cards where p(recall) is lowest (so, essentially what can already be archieved somewhat using filtered decks, just with better scheduling).
Regarding the other things you mentioned, like reducing required storage and make it work via CPU: great work, I’m glad to see you found even more ways to make the scheduler more accurate!
In that case I’ll try this one with my current deck; would be interessting to see the results.
Yeah, pretty much. Every card is always due, you choose desired retention which acts as a threshold for which cards are shown. So DR is still a meaningful knob. And you can sort those cards (below DR = shown to you) by either ascending or descending R. Or random, I guess.
For example, maybe you have 10 cards below 90% DR. So you can review them either starting from the lowest p(recall) card first, or from the highest p(recall) card first, or random.
- Does FSRS-7 have automated learning steps?
- Is there any plan to include RWKV in Anki? Or will the initial support be through add-on/script?
- Yeah, with FSRS-7 you can leave learning steps blank and it will do the work. It’s the only version of FSRS-7 that has been designed with same-day reviews in mind
- It’s not up to me. Even if I make RWKV super mega turbo efficient, it’s up to Anki devs
Any chance of adding Apple Silicon GPU support as well? It would be great if the optimization could take advantage of M-series GPUs (e.g., via MLX or Metal), so Mac users can benefit from the GPU acceleration too.
FSRS will stay on the CPU, and optimization will hopefully be much faster (5-10x) in the next Anki release. We’ve optimized the optimizer, so now it’s up to Anki devs to merge the PR: chore: bump fsrs version by asukaminato0721 · Pull Request #4956 · ankitects/anki · GitHub
Given that it’s taking more than a month to merge a PR with minimal changes on the Anki side, I would not expect FSRS-7 this year. Don’t even think about the neural net, that is 100% in the “make your own fork of Anki” territory unless you bribe Anki devs.
EDIT: that PR just got merged.
Okay, just tried it in a VM with my collection. I cloned the current main from JSchoreels fork. git log shows this:
commit 612e15ee80f9405a0318dc577ecdc25efb99ded0 (HEAD → main, origin/main)
Optimize button
With params from current anki
The “optimize” button takes ages. The terminal is printing this string non-stop:
DEBUG:aqt.mediasrv: POST /_anki/latestProgress
And the button shows this:
Checking for improvement…
After almost 5 Minutes it errors out:
Traceback (most recent call last):
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1120, in wrapped
data = handler()
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1101, in <lambda>
return lambda: getattr(aqt.mw.col._backend, f"{endpoint}_raw")(request.data)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/out/pylib/anki/_backend_generated.py", line 1186, in evaluate_params_legacy_raw
return self._run_command(13, 39, message)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/pylib/anki/_backend.py", line 175, in _run_command
raise backend_exception_to_pylib(err)
anki.errors.InvalidInput: The provided FSRS parameters are invalid. Leave them blank to use the default values.
JS error /_app/immutable/chunks/ySVTmg-t.mjs:2 Uncaught (in promise) Error: 500: The provided FSRS parameters are invalid. Leave them blank to use the default values.
The parameters work just fine with current, official anki (26.05 (e64c6b1a)).
With blank params
Anyways, I removed the parameters in the advanced settings section and tried again. It took almost 5 minutes this time, again. Then it errors out just like above:
Traceback (most recent call last):
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1120, in wrapped
data = handler()
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1101, in <lambda>
return lambda: getattr(aqt.mw.col._backend, f"{endpoint}_raw")(request.data)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/out/pylib/anki/_backend_generated.py", line 1186, in evaluate_params_legacy_raw
return self._run_command(13, 39, message)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/pylib/anki/_backend.py", line 175, in _run_command
raise backend_exception_to_pylib(err)
anki.errors.InvalidInput: The provided FSRS parameters are invalid. Leave them blank to use the default values.
The above happens with ./run --safemode and with ./run (some addons active).
The percentage is also always different, e.g. it also ended like this:
Optimize with Dynamic DR and Clamp unsupported dynamic DR active
If I have those options active, it optimizes again like before, but this time it also computes ADR values (up until 100%). But then it crashes after almost 6 minutes with the same error as above:
Traceback (most recent call last):
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1120, in wrapped
data = handler()
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/mediasrv.py", line 1101, in <lambda>
return lambda: getattr(aqt.mw.col._backend, f"{endpoint}_raw")(request.data)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/out/pylib/anki/_backend_generated.py", line 1186, in evaluate_params_legacy_raw
return self._run_command(13, 39, message)
~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^
File "/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/pylib/anki/_backend.py", line 175, in _run_command
raise backend_exception_to_pylib(err)
anki.errors.InvalidInput: The provided FSRS parameters are invalid. Leave them blank to use the default values.
RWKV
Not sure yet if this one is going to work. But it apparently needs an hour to do its job, which is far too long:
Edit: This one worked.
terminal output
2026-07-02 15:49:56,720:DEBUG:aqt.rwkv_scheduler: RWKV scheduler backend configure started: benchmark_path=False model_path=/media/anon/separateDownload/anki/Source_Code/anki-fsrs7-test/anki/qt/aqt/rwkv_inference/RWKV_trained_on_5000_10000.bin device=cpu dtype=float
2026-07-02 15:49:56,829:DEBUG:aqt.rwkv_scheduler: RWKV scheduler backend configured: backend=EmbeddedRwkvReviewerBackend elapsed_ms=109.4
2026-07-02 15:49:56,830:DEBUG:aqt.rwkv_scheduler: RWKV historical warm-up started
2026-07-02 15:49:56,830:DEBUG:aqt.rwkv_scheduler: RWKV historical review rows query started: after_review_id=None
2026-07-02 15:49:56,929:DEBUG:aqt.rwkv_scheduler: RWKV historical review rows query finished: rows=42652 elapsed_ms=99.1
2026-07-02 15:49:57,145:DEBUG:aqt.rwkv_scheduler: RWKV historical review inputs built: rows=42652 reviews=42652 dynamic_preset_replay=False historical_preset_rules=0 historical_preset_rule_matches=0 rows_elapsed_ms=99.3 historical_preset_rules_elapsed_ms=0.0 preset_elapsed_ms=13.3 count_elapsed_ms=4.2 elapsed_ms=314.5
2026-07-02 15:49:57,146:DEBUG:aqt.rwkv_scheduler: RWKV historical warm-up inputs prepared: reviews=42652 review_count=42652 last_review_id=1782906820493 elapsed_ms=316.0
2026-07-02 17:00:35,069:DEBUG:aqt.rwkv_scheduler: saved RWKV state cache snapshot: reviews=42652 last_review_id=1782906820493 bytes=186841217
2026-07-02 17:00:35,070:DEBUG:aqt.rwkv_scheduler: warmed RWKV reviewer state: reviews=42652 restore_elapsed_ms=0.2 history_elapsed_ms=316.0 warm_up_elapsed_ms=4236707.5 save_elapsed_ms=1216.6 elapsed_ms=4238240.8
2026-07-02 17:00:35,106:DEBUG:aqt.rwkv_scheduler: RWKV state cache build finished: elapsed_ms=4238387.5
2026-07-02 17:00:35,166:DEBUG:aqt.rwkv_scheduler: RWKV review input backend rows loaded: deck_review_queue_cards=1720 rows=1720 eligible=1720 elapsed_ms=57.8
2026-07-02 17:00:35,188:DEBUG:aqt.rwkv_scheduler: RWKV review input runtime batch started: missing_offset=0 size=1720 batch_size=2048 configured_batch_size=512 cache_hits=0
2026-07-02 17:00:35,194:DEBUG:aqt.rwkv_srs_benchmark: RWKV embedded Rust retrievability batch bridge started: requests=1720 packed=False build_elapsed_ms=5.4
2026-07-02 17:01:18,332:DEBUG:aqt.rwkv_srs_benchmark: RWKV embedded Rust retrievability batch predicted: requests=1720 packed=False build_elapsed_ms=5.4 bridge_elapsed_ms=43138.3 elapsed_ms=43143.7
2026-07-02 17:01:18,333:DEBUG:aqt.rwkv_scheduler: RWKV stateful request batch predict_retrievability_many predicted: requests=1720 runtime=_RustRwkvRuntime elapsed_ms=43144.8
2026-07-02 17:01:18,338:DEBUG:aqt.rwkv_scheduler: RWKV review input runtime batch processed: missing_offset=0 size=1720 batch_size=2048 configured_batch_size=512 predict_elapsed_ms=43149.6 elapsed_ms=43149.6
2026-07-02 17:01:18,342:DEBUG:aqt.rwkv_scheduler: RWKV review inputs scored: inputs=1720 cache_hits=0 runtime_requests=1720 scored=1720 batch_size=2048 predict_elapsed_ms=43153.3 elapsed_ms=43175.0
2026-07-02 17:01:18,343:DEBUG:aqt.rwkv_scheduler: RWKV review queue deck inputs scored: deck_id=1734806907276 searched=1720 loaded=1720 with_state=1720 enabled=1720 inputs=1720 scored=1720 deck_configs=1 batch_size=512 load_elapsed_ms=57.8 candidate_elapsed_ms=57.8 prediction_elapsed_ms=43176.1 elapsed_ms=43234.3
2026-07-02 17:01:18,343:DEBUG:aqt.rwkv_scheduler: RWKV score prewarm scored: reason=state cache build deck_ids=[1734806907276] candidates=1720 scored=1720 elapsed_ms=43235.5
2026-07-02 17:01:18,363:DEBUG:aqt.rwkv_scheduler: RWKV score prewarm finished: reason=state cache build deck_ids=[1734806907276] elapsed_ms=43255.7
Pressing “Reschedule & update RWKV memory state” had no effect on my collection.
@sound @Anon_0000 discuss this in DMs or on Discord, please
A lot of improvement are still made daily, don’t worry about it too much for now, but all those infos are ofc welcome.
Better go on discord here since it’s actively being implemented !
Yes I’m making some Metal version, and for CPU I use SIMD/Neon for macos. But it’s still work in progress !
Update: I’m working on my own Anki fork, here are some previews. RWKV will be ready by the end of October optimistically, in November or December pessimistically. I wish I had a cluster of 20 GPUs to run experiments faster, but alas ![]()
Card editor, Simple vs Advanced UI mode:
Advanced only: record audio (microphone), “Cards…”, Superscript, Subscript, Highlight color, Bullet list, Numbered list, Alignment, MathJax/LaTeX. Add-on buttons (such as HyperTTS) are visible in both modes.
Two-button mode with colored button borders is the default (you can re-enable four-button mode and disable colored button borders in Preferences):

Deck options, Simple vs Advanced UI mode (stitched via Photoshop, Easy Days is collapsed so the right one, Advanced mode, is actually even longer in reality):
Algorithm selection in Advanced mode:
In Stats, most graphs will be Advanced-only. Don’t worry about it, switching is instantaneous, you don’t have to restart Anki or anything.
Idk when I will release the fork, but certainly no sooner than finishing RWKV, since it will be in my fork. Right now I’m still using the old RWKV.










