// 段与优先级模型。
//
// 优先级为什么这样分(README 要解释):
// * `Pinned` —— system 提示、工具定义:一旦丢失语义就崩,永不被裁。
// * `Newest` —— 最近若干轮:对下一步生成影响最大,优先保留。
// * `Middle` —— 中间历史:第一批牺牲品之一。
// * `Oldest` —— 最早的历史:最先被丢。
///|
/// 段的丢弃权重,从「不可丢」到「最先牺牲」。
///
/// 典型用法:system 提示与工具定义用 `Pinned`,最近几轮用 `Newest`,
/// 中间历史用 `Middle`,最早的历史用 `Oldest`。
/// 权重相同时先丢原始下标更小的段(更早的历史),因此结果与输入顺序无关可复现。
pub(all) enum Priority {
Pinned
Newest
Middle
Oldest
} derive(Eq, Debug)
///|
/// 优先级权重;越大越不可丢。
pub fn Priority::weight(self : Priority) -> Int {
match self {
Pinned => 3
Newest => 2
Middle => 1
Oldest => 0
}
}
///|
/// 规范名称(用于可冻结的报告文本,不用 Debug 输出)。
pub fn Priority::name(self : Priority) -> String {
match self {
Pinned => "pinned"
Newest => "newest"
Middle => "middle"
Oldest => "oldest"
}
}
///|
/// 上下文里的一段。`role` 是自由标签(如 `system` / `user`),
/// `bytes` 是该段要送进窗口的内容。
///
/// 两个可选维度都只影响**取舍**,不影响编码:
/// * `pool` —— 配额池名(如 `tools` / `retrieval` / `history`)。同名段共享一份配额,
/// 池用不完的配额可按声明顺序借给超额的池,借用规则会写进报告。
/// 空串表示默认池,不参与配额。
/// * `score` —— 同优先级内的取舍分数,**越大越优先保留**(检索片段的相关性、
/// 工具定义的重要性都可以放这里)。分数只在同一 `Priority` 内比较,
/// 不会越过优先级。
pub(all) struct Segment {
role : String
priority : Priority
pool : String
score : Int64
bytes : Bytes
}
///|
pub fn Segment::new(role : String, priority : Priority, bytes : Bytes) -> Segment {
{ role, priority, pool: "", score: 0L, bytes }
}
///|
pub fn Segment::text(role : String, priority : Priority, text : String) -> Segment {
{ role, priority, pool: "", score: 0L, bytes: @utf8.encode(text) }
}
///|
/// 归入某个配额池(`name` 不得含空格或换行:它会直接进报告)。
pub fn Segment::with_pool(self : Segment, name : String) -> Segment {
{ ..self, pool: name }
}
///|
/// 设置同优先级内的取舍分数(越大越优先保留)。
pub fn Segment::with_score(self : Segment, score : Int64) -> Segment {
{ ..self, score }
}