> ## Documentation Index
> Fetch the complete documentation index at: https://ahvn.top/llms.txt
> Use this file to discover all available pages before exploring further.

# 随机

> 基于 StableRNG 的可复现随机数据辅助工具。

<Note>
  *只有当你已经知道结果如何，才应投出骰子。*
</Note>

当生成的行、样本或向量应在多次运行间保持稳定时，请使用 Random 工具。

`StableRNG` 提供六项稳定性保证：相同 seed → 相同输出；新增 pipeline 步骤彼此隔离；批量调用与循环调用一致；数据集增长不会打乱已有选中项；其他 RNG 库不受影响；采样结果取决于项内容，而非列表顺序。

<br />

## 1. 为何随机性需要稳定性

若没有专门设计稳定性，「可复现」的随机数据仍然脆弱。测试即使设置了 `seed=42`，也可能在 pipeline 更早处新增一次随机调用、数据集多一行、从批量调用改为循环，或输入顺序变化时失效。每种变化都可能改写其后所有值。

HeavenBase 的 `StableRNG` 保证六项彼此独立的稳定性。每一项都对应应用增长时你会遇到的典型失败模式。

### 1.1. 种子稳定性 (Seed Stability) — 相同 seed，相同输出

**含义：** 用相同 seed 执行相同抽取两次，得到相同值。

没有种子稳定性时，`seed=42` 可能在不同运行、版本或机器上产生不同字符串、浮点数或标签——失败的测试难以复现。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

with StableRNG(seed=42) as rng:
    a = rng.rnd_str(8)
with StableRNG(seed=42) as rng:
    b = rng.rnd_str(8)

assert a == b
# a and b are both '7dffoji5'
```

相同 seed 与相同抽取顺序总能复现相同序列。这是调试 fixture 与基准测试的基础。

<br />

### 1.2. 流程稳定性 (Process Stability) — 新步骤不会改写旧结果

**含义：** 在 pipeline 任意位置新增随机步骤；你已依赖的步骤输出保持不变。

没有流程稳定性时，在「生成行」与「生成样本」之间插入「生成指标」步骤会改变两者下游输出——尽管这两个步骤本身并未改动。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

# Original pipeline
rows = StableRNG(seed=42).step('rows').rnd_str(4)      # '5yqh'
samples = StableRNG(seed=42).step('samples').rnd_str(4) # '2qpl'

# After inserting a new step — existing values stay the same
rows2 = StableRNG(seed=42).step('rows').rnd_str(4)       # '5yqh'
metrics = StableRNG(seed=42).step('metrics').rnd_str(4)  # 'zkqs' (new)
samples2 = StableRNG(seed=42).step('samples').rnd_str(4) # '2qpl'

assert rows == rows2 and samples == samples2
```

`step(...)` 从基础 seed 派生命名子流，且不改变父生成器。两个不同步骤名永不共享状态。

<br />

### 1.3. 批量稳定性 (Batch Stability) — 一次批量调用等价于循环

**含义：** `rng.method(..., n=10)` 与循环调用十次 `rng.method(...)` 返回相同值。

没有批量稳定性时，在批量与增量写法之间重构会改变 fixture——即使 seed 与方法相同。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

with StableRNG(seed=42) as rng:
    batch = rng.rnd_float(0.0, 1.0, n=3)  # one call

with StableRNG(seed=42) as rng:
    seq = [rng.rnd_float(0.0, 1.0) for _ in range(3)]  # three calls

assert batch == seq
# Both: [0.086, 0.142, 0.270]
```

凡接受 `n=` 的生成方法均成立：`rnd_int`、`rnd_str`、`rnd_vec`、`choice` 等。你可选用最易读的写法，而不改变结果。

<br />

### 1.4. 数据稳定性 (Data Stability) — 新记录不会打乱已有选中项

**含义：** 今天采样或划分；明天加入更多项；池中已有项的判定保持不变（预期会有小幅变化，但不会剧烈变动）。

没有数据稳定性时，用 `seed=42` 从 `[p1, p2, p3, p4]` 抽 2 项可能得到 `[p3, p4]`，但加入 `p5` 后选中项可能变为 `[p2, p5]`。基准测试与评估划分因此变得脆弱。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

items = ['p1', 'p2', 'p3', 'p4']
sample1 = StableRNG(seed=42).hash_sample(items, k=2)
# sample1: ['p3', 'p4']

items2 = ['p1', 'p2', 'p3', 'p4', 'p5']  # one new item
sample2 = StableRNG(seed=42).hash_sample(items2, k=2)
# sample2: ['p3', 'p4'] — existing items not changed drastically

assert all(x in sample2 for x in sample1)
```

`hash_sample` 与 `hash_split` 基于各项自身摘要（由 `StableRNG` seed 加盐）决定是否选中，而非列表位置。新增项只影响新增项自身的判定。

实现数据稳定性的核心思路是用项的哈希决定选中与否，而非项在列表中的位置。向池中新增单项时，根据其哈希是否落在阈值内，该项会进入选中组或剩余组，最多只会将选中组中的一项挤出。

<br />

### 1.5. 生态稳定性 (Ecosystem Stability) — 其他 RNG 库不受影响

**含义：** 使用 `StableRNG` 不会 seed 或重置 Python `random`、NumPy 全局 RNG、PyTorch 或进程中任何其他 RNG。

没有生态稳定性时，大量使用 `StableRNG` 可能静默重设全局 RNG 状态，破坏代码库其他位置的可复现性。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
import random
from heavenbase.utils import StableRNG

random.seed(999)
expected = [random.random() for _ in range(5)]

random.seed(999)
with StableRNG(seed=42) as rng:
    _ = rng.rnd_str(1000)  # heavy use of StableRNG
actual = [random.random() for _ in range(5)]

assert expected == actual
# StableRNG never calls random.seed, numpy.random.seed, or torch.manual_seed
```

每个 `StableRNG` 创建独立的 NumPy `Generator` 实例。它从不触碰全局 `random` 模块、`numpy.random` 状态或任何其他 RNG 系统。

<br />

### 1.6. 哈希稳定性 (Hash Stability) — 由内容决定，而非列表顺序

**含义：** 将相同项以不同顺序排列；这些项的采样或划分结果保持不变。

没有哈希稳定性时，从 `['p1', 'p2', 'p3']` 采样可能得到 `['p3', 'p1']`，但将输入重排为 `['p3', 'p1', 'p2']` 可能得到 `['p1', 'p2']`。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

items_a = ['p1', 'p2', 'p3']
items_b = ['p3', 'p1', 'p2']  # same items, different order

s_a = StableRNG(seed=42).hash_sample(items_a, k=2)
s_b = StableRNG(seed=42).hash_sample(items_b, k=2)

assert sorted(s_a) == sorted(s_b)
# Both: ['p1', 'p3']
```

`hash_sample` 与 `hash_split` 使用生成器配置的哈希函数（默认 CRC32，也可选 `md5` 或 `sha256`）计算各项摘要，以 seed 加盐后再按摘要值选中。输入顺序从不参与判定。

<br />

<Note>
  这六项稳定性内建于 `StableRNG`。传入 seed 即可获得全部保证——无需额外标志或配置。
</Note>

<br />

## 2. 核心思想

`StableRNG` 面向测试、demo、基准测试与 LLM 应用 fixture——「随机」数据仍需可调试。若 seed `42` 下失败，你应能在之后再生相同的行、向量与样本。

<br />

## 3. 生成可复现序列

用 seed 创建生成器；多次抽取属于同一序列时将其作为上下文使用。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

with StableRNG(seed=42) as rng:
    row_id = rng.rnd_str(8)
    score = rng.rnd_float(0.0, 1.0)
    label = rng.choice(["open", "closed", "review"])
```

相同 seed 与抽取顺序产生相同序列：

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

with StableRNG(seed=7) as left:
    left_values = [left.rnd_str(6), left.rnd_int(0, 10)]

with StableRNG(seed=7) as right:
    right_values = [right.rnd_str(6), right.rnd_int(0, 10)]

assert left_values == right_values
```

在上下文外，单次方法调用对当前 seed 仍稳定。适合只需一个可复现值、又不想与先前抽取耦合的场景。

<br />

## 4. 派生子流

用 `step(...)` 将基础 seed 拆成命名流，而不改变父生成器。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

base = StableRNG(seed=42)
rows_rng = base.step("rows")
sample_rng = base.step("samples")

rows = rows_rng.rnd_str(6, n=3)
sample = sample_rng.choice(["p1", "p2", "p3", "p4"], k=2, replace=False)
```

这样某个测试在 workflow 中新增一次随机抽取时，不会牵连无关部分。

<br />

## 5. 生成批次与向量

多数生成器接受 `n` 表示数量或形状。需要一次性生成大量值时很有用。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

rng = StableRNG(seed=42)

ids = rng.rnd_str(4, n=5)
grid = rng.rnd_int(0, 10, n=(2, 3))
vecs = rng.rnd_vec(dim=8, n=3)
```

`rnd_vec(...)` 返回单位长度向量，适合在接入真实 embedding provider 之前需要向量形态的 LLM 与向量检索开发。

<br />

## 6. 采样而不打乱全局

稳定样本不应依赖输入顺序或无关新记录时，使用 `hash_sample(...)` 与 `hash_split(...)`。

```python theme={"theme":{"light":"github-light","dark":"github-dark"}}
from heavenbase.utils import StableRNG

items = ["p1", "p2", "p3", "p4"]

sample = StableRNG(seed=11).hash_sample(items, k=2)
selected, remaining = StableRNG(seed=11).hash_split(items, r=0.5)
wide_sample = StableRNG(seed=11, hash_function="sha256").hash_sample(items, k=2)
```

若之后加入 `"p5"`，`"p1"` 到 `"p4"` 的判定仍基于各项哈希与 seed，而非原始列表位置。

CRC32 是默认值，因为采样碰撞只会改变确定性样本选择或并列处理。默认值会从配置中的 `heavenbase.rng.hash_function` 与 `heavenbase.rng.hash_modulo` 读取，且每次 `hash_sample(...)` / `hash_split(...)` 调用都可覆盖哈希函数。

<Check>
  HeavenBase 基准测试使用带 seed 的生成，以便行内容、样本与向量可复现。
</Check>

<br />

## 进一步探索

<Tip>
  **相关资源：**

  * [哈希](/zh/features/utilities/hash) - 稳定采样使用的确定性哈希。
  * [文件系统](/zh/features/utilities/file-system) - 将生成 fixture 写入本地产物。
  * [查询](/zh/features/query) - 合成向量 fixture 的常见使用处。
</Tip>

<br />
