> For AI agents: the complete documentation index is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/llms.txt, the full documentation bundle is available at https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/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 模型

複製提示詞

使用目前 ts-fsrs Model 契約完成以下任務：[描述任務]。

1. 閱讀 https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/index.md 以及所選模型版本的頁面。
2. 可依需要對照 FSRS-6（https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-6.md）、FSRS-5（https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-5.md）、FSRS-4.5（https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-4dot5.md）、FSRS-4（https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-4.md）和 FSRS-3（https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-3.md）的公式與說明。 FSRS-7: https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/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-TW/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-TW/guide/model/fsrs-7.md) — 雙分量實作參考，34 個權重與數值求間隔。
- [FSRS-6](https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-6.md) — 支援可訓練衰減與同日更新。
- [FSRS-5](https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-5.md) — 使用固定冪函數遺忘曲線，並支援同日更新。
- [FSRS-4.5](https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-4dot5.md) — 使用固定冪函數曲線，不包含同日公式。
- [FSRS-4](https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-4.md) — 本專案中第一個使用冪函數曲線的版本。
- [FSRS-3](https://open-spaced-repetition.github.io/ts-fsrs/zh-TW/guide/model/fsrs-3.md) — 使用較早的指數遺忘曲線。
