> For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/llms-full.txt.

# 模型概览

FSRS 模型根据评分和经过时间计算新的记忆状态，通过遗忘曲线估算回忆概率，并根据记忆状态与目标保留率计算基础间隔。

本节的 FSRS-3 至 FSRS-6 术语与公式依据 [awesome-fsrs Wiki](https://github.com/open-spaced-repetition/awesome-fsrs/wiki) 校对，主要参考其中的 [The Algorithm](https://github.com/open-spaced-repetition/awesome-fsrs/wiki/The-Algorithm)。TypeScript API 与框架职责边界以 ts-fsrs 本身为准。

:::note 模型边界
模型只负责记忆状态更新、遗忘曲线计算和基础间隔计算。scheduler 负责组织复习流程，`chrono` 负责日期与经过时间，middleware 负责学习步骤、模糊处理、最大间隔限制和队列状态策略。
:::


For your Agent

实现或解释 SRS 模型

复制 Prompt

使用当前 ts-fsrs Model 契约完成以下任务：[描述任务]。

1. 阅读 https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/index.md 以及所选模型版本的页面。
2. 可按需对照 FSRS-6（https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-6.md）、FSRS-5（https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-5.md）、FSRS-4.5（https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-4dot5.md）、FSRS-4（https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-4.md）和 FSRS-3（https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-3.md）的公式与说明。 FSRS-7: https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-7.md.
3. 实现模型前先定义配置 schema 和记忆状态 schema。
4. 将模型限制为 step、nextInterval、forgettingCurve 和 forward 行为。
5. 向 nextInterval 显式传入目标保留率。
6. 由 scheduler 组织复习流程，由 chrono 处理时间，由 middleware 应用学习步骤、模糊处理、最大间隔限制和队列状态策略。
7. 仅在配置已经完成 migrate、clip 和 check 后使用 bypass。
8. 使用当前公共 API，并为每个实现的公式添加聚焦测试。

## 公共符号

| 符号                              | 含义                                                              |
| ------------------------------- | --------------------------------------------------------------- |
| `math:D`                        | 难度，范围为 1（最简单）至 10（最困难）。                                         |
| `math:S`                        | FSRS-3 至 FSRS-6 的稳定性，单位为天；当 `math:t = S` 时回忆概率为 90%。            |
| `math:R`                        | 经过 `math:t` 天后能够回忆的估计概率。                                        |
| `math:G`                        | 评分：1 为 Again、2 为 Hard、3 为 Good、4 为 Easy。                        |
| `math:t`                        | 距离上次复习经过的天数。                                                    |
| `math:r`                        | `nextInterval` 使用的目标保留率。                                        |
| `math:I(r, S)`                  | 根据稳定性 `math:S` 和目标保留率 `math:r` 计算的基础间隔，单位为天，尚未应用 middleware 策略。 |
| `math:S_{\min}`、`math:S_{\max}` | 模型允许的稳定性下限和上限。                                                  |
| `math:D_{\min}`、`math:D_{\max}` | 模型允许的难度下限和上限。                                                   |
| `math:w_i`                      | 训练得到的模型权重。                                                      |

[FSRS-7](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-7.md) 根据其实现快照单独说明：它增加快稳定性，使用混合曲线并返回小数天间隔。上表中稳定性的 90% 定义和 `I(r, S)` 记法适用于 FSRS-3 至 FSRS-6。

## 使用版本化模型

`DefaultScheduler` 默认使用 FSRS-7，可通过 `version` 选择任一支持的 FSRS 版本。也可以直接创建并调用各版本模型；下面以 FSRS-6 为例：

```ts twoslash file="../../../snippets/run-code/model.ts"
import { Rating } from 'ts-fsrs'
import { FSRS6_DEFAULT_WEIGHTS, FSRS6Model } from 'ts-fsrs/models/fsrs-6'

const model = FSRS6Model.create({
  config: {
    weights: FSRS6_DEFAULT_WEIGHTS,
    enableShortTerm: true,
    numRelearningSteps: 1, // Constrains weights; middleware runs the steps.
  },
})

const memoryState = model.step({
  memoryState: null,
  rating: Rating.Good,
  elapsedDays: 0,
})
const desiredRetention = 0.9
const interval = model.nextInterval(memoryState, desiredRetention)
const retrievabilityAtInterval = model.forgettingCurve(memoryState, interval)

console.log(
  JSON.stringify(
    {
      memoryState,
      desiredRetention,
      interval,
      retrievabilityAtInterval,
    },
    null,
    2
  )
)

```


▶ 运行代码

示例先根据 90% 的目标保留率计算复习间隔，再通过 `forgettingCurve` 估算到达该间隔时的回忆概率。由于 FSRS-6 的 `nextInterval` 返回整数天，结果可能与 90% 略有差异。

在 FSRS-6 配置中，`enableShortTerm` 控制模型的同日稳定性更新。`numRelearningSteps` 只参与权重裁剪与检查；重新学习步骤仍由 middleware 调度。

## 定义模型

`defineModel` 会保留具体的配置、记忆状态和算法类型，并把 schema、默认值与模型核心工厂组织为一个定义。它本身不会解析配置：

下面通过实现一个 [SM-2 变体](https://github.com/open-spaced-repetition/srs-benchmark/blob/main/models/sm2_trainable.py)，演示如何定义模型。

```ts twoslash fold height=420 file="../../../snippets/run-code/custom-model.ts"
import {
  clamp,
  defineModel,
  type ModelForwardInput,
  type ModelStepInput,
  Rating,
} from 'ts-fsrs'
import { z } from 'zod'

const configSchema = z.object({
  weights: z.tuple([
    z.number().min(0.01).max(100),
    z.number().min(0.01).max(100),
    z.number().min(1.3).max(10),
    z.number().nonnegative(),
    z.number().min(5),
    z.number(),
  ]),
})
const memoryStateSchema = z.object({
  interval: z.number().min(0).max(36500),
  easeFactor: z.number().min(1.3).max(10),
  repetitions: z.number().int().nonnegative(),
})
type MemoryState = z.output<typeof memoryStateSchema>

const SM2Model = defineModel({
  name: 'sm2',
  schema: { config: configSchema, memoryState: memoryStateSchema },
  defaultValue: {
    memoryState: ({ config }) => ({
      interval: 0,
      easeFactor: config.weights[2],
      repetitions: 0,
    }),
  },
  create({ config }) {
    const parsed = configSchema.parse(config)
    const w = parsed.weights
    const step = ({ memoryState, rating }: ModelStepInput<MemoryState>) => {
      const previous = memoryState ?? {
        interval: 0,
        easeFactor: parsed.weights[2],
        repetitions: 0,
      }
      // Again / Hard / Good / Easy -> SM-2 quality 2 / 3 / 4 / 5.
      const quality = rating + 1
      const repetitions = rating > Rating.Again ? previous.repetitions + 1 : 0
      const interval = clamp(
        repetitions <= 1
          ? w[0]
          : repetitions === 2
            ? w[1]
            : previous.interval * previous.easeFactor,
        0.01,
        36500
      )
      const easeFactor = clamp(
        previous.easeFactor - w[3] * (quality - w[4]) ** 2 + w[5],
        1.3,
        10
      )
      return { interval, easeFactor, repetitions }
    }
    const forward = ({
      history,
      initialState,
    }: ModelForwardInput<MemoryState>) => {
      const states: MemoryState[] = []
      let memoryState = initialState ?? null
      for (const review of history) {
        memoryState = step({
          memoryState,
          rating: review.rating,
          elapsedDays: review.deltaT,
        })
        states.push(memoryState)
      }
      return states
    }
    return {
      config: parsed,
      bounds: {
        iMin: 0.01,
        iMax: 36500,
        eMin: 1.3,
        eMax: 10,
        rMin: 0,
        rMax: Infinity,
      },
      algorithm: null,
      step,
      // Invert the benchmark curve to satisfy the Model interval contract.
      nextInterval: (state: Readonly<MemoryState>, desiredRetention: number) =>
        Math.max(
          1,
          Math.round(
            (state.interval * Math.log(desiredRetention)) / Math.log(0.9)
          )
        ),
      forgettingCurve: (state: Readonly<MemoryState>, elapsedDays: number) =>
        0.9 ** (elapsedDays / state.interval),
      forward,
    }
  },
})

const model = SM2Model.create({
  config: { weights: [1, 6, 2.5, 0.02, 7, 0.18] },
})
const states = model.forward({
  history: [
    { rating: Rating.Good, deltaT: 0 },
    { rating: Rating.Good, deltaT: 1 },
    { rating: Rating.Good, deltaT: 6 },
    { rating: Rating.Again, deltaT: 15 },
    { rating: Rating.Good, deltaT: 1 },
    { rating: Rating.Good, deltaT: 1 },
  ],
})
console.log(JSON.stringify(states, null, 2)) // Intervals: 1, 6, 15, 1, 1, 6 days.

```


▶ 运行代码

Schema 描述公共边界，并在 scheduler 组合 schema 时使用。直接调用 `create` 时，具体实现必须先完成所需的解析和规范化，再返回 `config`、`bounds`、`algorithm`、`step`、`nextInterval`、`forgettingCurve` 和 `forward`。该核心应保持确定性，且不包含调度策略。

:::warning bypass 仅用于已处理的配置
只有调用方已经明确完成该模型的 migrate、clip、schema 校验和范围检查后，才能使用 `FSRS6Model.create({ config, bypass: true })`。它会跳过这些 create 阶段的处理以及冻结。不要对来自用户、存储或网络的原始配置使用 `bypass`。
:::

## 模型版本

- [FSRS-7](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-7.md) — 双分量实现参考，34 个权重与数值求间隔。
- [FSRS-6](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-6.md) — 支持可训练衰减与同日更新。
- [FSRS-5](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-5.md) — 使用固定幂函数遗忘曲线，并支持同日更新。
- [FSRS-4.5](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-4dot5.md) — 使用固定幂函数曲线，不包含同日公式。
- [FSRS-4](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-4.md) — 本项目中首个使用幂函数曲线的版本。
- [FSRS-3](https://open-spaced-repetition.github.io/ts-fsrs/zh-CN/guide/model/fsrs-3.md) — 使用较早的指数遗忘曲线。
