muse-agent-example/数据库/迁移/V0061__场景切片索引.sql
zizi fea8f44327 feat(资料研究): 场景切片派生缓存与向量代次索引——参考书原文确定性切窗入检索池
- V0061:切片台账(窗计划哈希锁切窗方案、禁原地改写)、切片向量索引与代次台账,代次守卫仿 V0059
- 场景切片.py:段落聚合切窗纯函数(目标1800字符、末窗并邻)、确定性切片身份、全量重建命令与授权读取
- 只纳入 reference_reading 用途来源的导入者视角;用途撤回即退出候选,切片行保留
- 底座种子表登记切片代次单例;单元4例+集成3例全过
2026-09-19 23:43:51 +08:00

88 lines
4.4 KiB
PL/PgSQL
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

-- B03:场景切片派生缓存与向量代次索引——参考书原文的确定性切窗。
-- 原文以 muse_source_version 为权威;切片与索引是可全量重建的派生数据,禁原地改写。
DO $migration$
BEGIN
-- 切片台账:来源版本的定位窗;窗计划哈希锁定切窗方案,同版本只认一个窗计划。
CREATE TABLE public.muse_source_slice (
slice_id uuid PRIMARY KEY,
source_id uuid NOT NULL REFERENCES public.muse_source(source_id),
revision bigint NOT NULL CHECK (revision > 0),
起点 int NOT NULL CHECK (起点 >= 0),
终点 int NOT NULL CHECK (终点 > 起点),
窗计划哈希 text NOT NULL,
检索文本 text NOT NULL,
检索文本哈希 text NOT NULL CHECK (检索文本哈希 ~ '^[0-9a-f]{64}$'),
built_at timestamptz NOT NULL DEFAULT clock_timestamp()
);
-- 同版本同窗计划内起点唯一;不同窗计划可并存,重建时整计划替换。
CREATE UNIQUE INDEX muse_source_slice_window
ON public.muse_source_slice (source_id, revision, 窗计划哈希, 起点);
CREATE INDEX muse_source_slice_by_source ON public.muse_source_slice (source_id, revision);
-- 派生数据禁原地改写;删除仅允许全量重建事务成批进行。
CREATE FUNCTION public.muse_guard_source_slice() RETURNS trigger LANGUAGE plpgsql AS $guard$
BEGIN
RAISE EXCEPTION '场景切片是派生数据,禁止原地改写;重建请整批删除后重算';
END;
$guard$;
CREATE TRIGGER muse_source_slice_guard BEFORE UPDATE ON public.muse_source_slice
FOR EACH ROW EXECUTE FUNCTION public.muse_guard_source_slice();
-- 切片向量索引:与 muse_method_index 同构(哈希 bigram,内存余弦)。
CREATE TABLE public.muse_source_slice_index (
slice_id uuid PRIMARY KEY REFERENCES public.muse_source_slice(slice_id) ON DELETE CASCADE,
检索文本 text NOT NULL,
检索文本哈希 text NOT NULL,
vector double precision[] NOT NULL CHECK (array_length(vector, 1) > 0),
embedder text NOT NULL,
built_at timestamptz NOT NULL DEFAULT clock_timestamp()
);
-- 代次台账:当前有效索引身份;检索时对不上即拒绝为陈旧。
CREATE TABLE public.muse_source_slice_index_version (
ledger_id bigint PRIMARY KEY GENERATED ALWAYS AS IDENTITY,
索引身份 text NOT NULL,
embedder text NOT NULL,
slice_count int NOT NULL CHECK (slice_count >= 0),
built_at timestamptz NOT NULL DEFAULT clock_timestamp(),
active boolean NOT NULL DEFAULT false
);
CREATE UNIQUE INDEX muse_source_slice_index_active
ON public.muse_source_slice_index_version (active) WHERE active;
-- 代次守卫:切片与索引的事务变更递增代次,检索按代次判新鲜(仿 V0059)。
CREATE TABLE public.muse_source_slice_guard (
singleton boolean PRIMARY KEY DEFAULT true CHECK (singleton),
generation bigint NOT NULL DEFAULT 0 CHECK (generation >= 0)
);
INSERT INTO public.muse_source_slice_guard (singleton, generation) VALUES (true, 0);
CREATE FUNCTION public.muse_source_slice_changed() RETURNS trigger
LANGUAGE plpgsql SECURITY DEFINER SET search_path = pg_catalog AS $guard$
BEGIN
UPDATE public.muse_source_slice_guard
SET generation = generation + 1
WHERE singleton;
IF NOT FOUND THEN
RAISE EXCEPTION 'source slice mutation guard is missing';
END IF;
RETURN NULL;
END;
$guard$;
CREATE TRIGGER muse_source_slice_changed
AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON public.muse_source_slice
FOR EACH STATEMENT EXECUTE FUNCTION public.muse_source_slice_changed();
CREATE TRIGGER muse_source_slice_index_changed
AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON public.muse_source_slice_index
FOR EACH STATEMENT EXECUTE FUNCTION public.muse_source_slice_changed();
CREATE TRIGGER muse_source_slice_head_changed
AFTER INSERT OR UPDATE OR DELETE OR TRUNCATE ON public.muse_source_slice_index_version
FOR EACH STATEMENT EXECUTE FUNCTION public.muse_source_slice_changed();
REVOKE ALL ON public.muse_source_slice_guard FROM PUBLIC, muse_app, muse_eval;
GRANT SELECT ON public.muse_source_slice_guard TO muse_app, muse_eval;
REVOKE ALL ON FUNCTION public.muse_source_slice_changed() FROM PUBLIC;
END
$migration$;