For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/llms-full.txt, and this page is available as Markdown at https://open-spaced-repetition.github.io/ts-fsrs/guide/model/fsrs-7.md.

FSRS-7

Migration guide

For steps that rebuild memory states without rescheduling existing cards, see the v6 and FSRS-7 migration guide.

FSRS-7 uses 34 weights and two stability components. Its state contains stability (slow component), stabilityFast (fast component), and difficulty. The two stability components produce the slow and fast recall components used by the forgetting curve.

Memory state and notation

Use the shared symbols, with SsS_s for stability and SfS_f for stabilityFast. Both are measured in days, but neither is the interval at which the mixed recall probability reaches 90%. Difficulty affects both the slow curve and its mixture weight.

The formulas use bounded pre-review state values: both stabilities are in [0.0001, 36500] and difficulty is in [1, 10]. Elapsed time tt is in fractional days; curve evaluation uses max⁡(t,0)\max(t,0). The fast and slow names identify model components, not a guaranteed ordering of their stability values.

Initial memory

For a new memory state, let CsC_s and CfC_f clamp to the slow and fast stability bounds respectively, and let CDC_D clamp to [1, 10].

Ss,0=Cs(wG−1),Sf,0=Cf(0.8Ss,0)S_{s,0}=C_s(w_{G-1}),\qquad S_{f,0}=C_f(0.8S_{s,0})
D0(G)=w4−ew5(G−1)+1,Dinitial=CD(D0(G))D_0(G)=w_4-e^{w_5(G-1)}+1,\qquad D_{initial}=C_D(D_0(G))

Dual-trace forgetting curve

Fast trace:

df=−clamp⁡(w23Sfw33−0.3,0.01,0.95)d_f=-\operatorname{clamp}(w_{23}S_f^{w_{33}-0.3},0.01,0.95)
Ff=exp⁡(min⁡(ln⁡w25df,60))−1F_f=\exp\left(\min\left(\frac{\ln w_{25}}{d_f},60\right)\right)-1
Rf(t)=(1+FftSf)dfR_f(t)=\left(1+F_f\frac{t}{S_f}\right)^{d_f}

Slow trace:

ds=−clamp⁡(w24,0.01,0.95)d_s=-\operatorname{clamp}(w_{24},0.01,0.95)
Fs=(w261/ds−1)e(D−5)(w32−0.3)F_s=(w_{26}^{1/d_s}-1)e^{(D-5)(w_{32}-0.3)}
Rs(t)=(1+FstSs)dsR_s(t)=\left(1+F_s\frac{t}{S_s}\right)^{d_s}

Mixture weights and recall

The weights are positive, unnormalised coefficients. They depend on the memory state, not elapsed time. A raw component recall is not its contribution to the mixture.

af=w27Sf−w29,as=w28Ssw30e(D−5)(w31−0.5)a_f=w_{27}S_f^{-w_{29}},\qquad  a_s=w_{28}S_s^{w_{30}}e^{(D-5)(w_{31}-0.5)}
R(t)=afRf(t)+asRs(t)af+as(1−2ε)+ε,ε=10−5R(t)=\frac{a_fR_f(t)+a_sR_s(t)}{a_f+a_s}(1-2\varepsilon)+\varepsilon,\qquad\varepsilon=10^{-5}

algorithm.curve(t, state) returns fast, slow, fastWeight, slowWeight, retrievability, and derivative. The fast and slow fields are the two component recall probabilities, while fastWeight and slowWeight are positive, unnormalised mixture coefficients. The retrievability value is their weighted average followed by the final epsilon adjustment, so R(0)=0.99999R(0)=0.99999.

Stability after review

For a trace stability xx, recall input qq, and parameter offset kk, define the lapse value and successful-recall update:

Lk(x,q)=min⁡(x,wk+3((x+1)wk+4−1)e(1−q)wk+5)L_k(x,q)=\min\left(x,w_{k+3}((x+1)^{w_{k+4}}-1)e^{(1-q)w_{k+5}}\right)
Hk,G={wk+6,G=21,G≠2,Ek,G={wk+7,G=41,G≠4H_{k,G}=\begin{cases}w_{k+6},&G=2\\1,&G\ne2\end{cases},\qquad E_{k,G}=\begin{cases}w_{k+7},&G=4\\1,&G\ne4\end{cases}
Uk(x,q,G)=x[1+ewk−1.5(11−D)x−wk+1(e(1−q)wk+2−1)Hk,GEk,G]U_k(x,q,G)=x\left[1+e^{w_k-1.5}(11-D)x^{-w_{k+1}}(e^{(1-q)w_{k+2}}-1)H_{k,G}E_{k,G}\right]
Tk(x,q,G)={Lk(x,q),G=1max⁡(Lk(x,q),Uk(x,q,G)),G∈{2,3,4}T_k(x,q,G)=\begin{cases}L_k(x,q),&G=1\\\max(L_k(x,q),U_k(x,q,G)),&G\in\{2,3,4\}\end{cases}

Use k=7k=7 and the mixed recall RR for the slow trace; use k=15k=15 and the raw fast recall RfR_f for the fast trace. All updates use pre-review difficulty. An explicit retrievability input replaces RR for the slow update and difficulty, but does not replace RfR_f for the fast update.

On Again, cap the new fast stability at 80% of the new slow stability before applying state bounds:

S~s=T7(Ss,R,G),S~f=T15(Sf,Rf,G)\widetilde S_s=T_7(S_s,R,G),\qquad \widetilde S_f=T_{15}(S_f,R_f,G)
Ss′=Cs(S~s),Sf′=Cf({min⁡(S~f,0.8S~s),G=1S~f,G≥2)S'_s=C_s(\widetilde S_s),\qquad S'_f=C_f\left(\begin{cases}\min(\widetilde S_f,0.8\widetilde S_s),&G=1\\\widetilde S_f,&G\ge2\end{cases}\right)

Difficulty after review

Again scales the difficulty change by the mixed recall. Mean reversion uses a fixed coefficient of 0.01:

ΔD=−w6(G−3){R+0.1,G=11,G≥2\Delta D=-w_6(G-3)\begin{cases}R+0.1,&G=1\\1,&G\ge2\end{cases}
D′=CD(0.01D0(4)+0.99(D+10−D9ΔD))D'=C_D\left(0.01D_0(4)+0.99\left(D+\frac{10-D}{9}\Delta D\right)\right)

The implementation rounds the three new state values to eight decimal places and clamps them to their bounds. FSRS-7 uses these updates at fractional elapsed times, including zero; it has no separate enableShortTerm same-day formula. Learning-step scheduling is still a middleware policy.

Interval calculation

nextInterval(state, r) numerically solves the mixed curve for elapsed time. It depends on all three state fields and returns fractional days.

R(I;Ss,Sf,D)=rR(I;S_s,S_f,D)=r

The implementation validates 0<r<10<r<1, clamps the target to [0.0001, 0.9999], and returns zero for a target at the upper bound. Otherwise it uses up to seven bounded Newton updates in log-time, with a bisection fallback when the recall error exceeds 0.001. The result is limited by sMax; extreme targets may therefore be unreachable.

Configuration and migration

FSRS-7 requires its own 34 weights. The parameter migration helper supplies defaults for empty input but requires exactly 34 weights for non-empty input. FSRS-3–6 weights and memory states cannot be directly converted to FSRS-7. To migrate card data, use reschedule with an FSRS-7 scheduler to replay review history and reconstruct the memory state, preserving fractional elapsed days. The 0.8 factor above applies to initialisation and Again updates.