RFCs

Artifact 插件框架

  • Proposal Name: artifact_plugin_framework
  • Start Date: 2026-10-20
  • RFC PR: #2175

概要

本提案让用户通过 Python 插件定义 Artifact 的内容结构、输入 Projection 和生成逻辑,无需为每种业务修改 PowerContext 核心。Server 管理 Artifact 插件声明与生命周期,已有 Supervisor 派发短生命周期 Worker,Worker 中的通用处理器 调用插件并原子保存结果、索引投影或构建变更记录及消费进度。应用通过统一接口读取、检索和定位精确证据,在应用层理解业务问题、 组合证据并计算答案。一个插件声明一个输出 family、一个输入契约和一个 binding(稳定的消费与调度登记), 可服务多个获授权 Scope。

本文规定提议的行为,不表示这些能力已在主线或发布版本中可用。主线基础以 0da4436d 为参照;接口名称、配置和 代码用于说明目标契约,最终语法随实现发布。可选检索能力只有在实现、后端验收及能力发现均支持时才对外开放。

动机

工单报告、案件摘要、具身记忆等业务需要不同的内容结构和生成算法。内置 Artifact family 无法穷尽这些需求, 而每个扩展都复制调度、版本、证据和检索基础设施,会产生不同的失败及恢复语义。插件作者应专注于如何从证据 生成内容,框架负责何时运行、如何验证、如何提交和如何读取。

Source 插件 RFC #2012解决外部资料如何进入 PowerContext: write 同步保存调用者提供的内容,collect 持续采集外部资料。Artifact 插件解决保存后的资料如何生成可复用结果。 生成失败不要求重新采集;Source 插件停止后仍可消费已经保存的输入。

例如,Source 插件保存工单快照及结构化 Projection,Artifact 插件生成 incident-report。应用检索报告,读取其 精确 revision,并沿 lineage 找到实际使用的快照。判断事故是否相关、统计次数或回答自然语言问题属于应用。

使用层说明

1. 组件与职责

flowchart TB
    Source["Source write / collect"] --> Saved["已保存 Source 与 Projection"]
    Admin["用户:可信代码与清单"] --> Manager["Artifact 插件管理(Server 内)"]
    Manager --> Registry["持久声明、状态与注册代次"]
    Manager --> Supervisor["已有 ArtifactProcessingSupervisor"]
    Supervisor --> Worker["短生命周期生成 Worker"]
    Saved --> Worker
    Worker --> Pipeline["插件 pipeline.generate"]
    Pipeline --> Drafts["待提交 drafts"]
    Drafts --> Commit["框架校验及原子提交"]
    Commit --> Store["Artifact / lineage / 索引 / cursor / ack"]
    Registry --> Read["统一读取与 Searcher"]
    Store --> Read
    Worker --> Read
    App["上层应用 / Agent"] --> Read
    Read --> Evidence["完整内容与精确引用"]
    Evidence --> App
参与者已有 / 新增职责
用户已有角色部署可信代码和兼容依赖,配置目录与后台身份,管理启停及升级
Artifact 插件管理(Server 内)新增发现入口,在子进程校验声明,持久注册并协调单 binding 的切换
Supervisor复用已有组件Scope 派发、Worker 预算、任期、超时、退避和完成确认
Artifact 插件通用处理器(Worker 内)新增,复用已有 Worker 执行机制加载工厂、读取窗口、提供受控资源、验证 drafts、提交结果和进度
Artifact 插件新增扩展契约声明输入、输出 family、内容 schema,以及可选索引和检索模式;提供工厂与生成逻辑,确定输出 ID 和实际使用的证据
框架读取与索引服务扩展已有服务增加自定义 family 的持久 schema 读取、声明式索引装配与重建,复用权限校验和统一检索接口
应用 / Agent已有调用方理解问题、选择证据、判断完整性、进行业务计算并组织答案

Artifact 插件框架是库,不新增 Source 插件管理服务式的常驻组件。 Supervisor 派发 Worker,由 Worker 在每次消费时创建并调用 Artifact pipeline。

Server 父进程不导入用户 Artifact 模块。声明校验和生成均在子进程执行,普通读取不导入插件,也不启动生成 Worker。 内置 family 保留各自领域处理器,与自定义插件共用调度及消费基础。

2. 部署、启用与 Artifact 生成示例

Server 使用 POWERCONTEXT_SERVER_ARTIFACT_PLUGINS_DIR 指定统一发现目录。每个直接子目录包含 plugin.yml, 目录项名称与 binding_name 一致。发现目录项可链接到预部署的不可变版本目录,历史包置于发现目录之外。

/opt/powercontext/artifact-plugins/
└── example-incident-report/
    ├── plugin.yml
    └── plugin.py
id: example-incident-report            # 插件标识,用于登记插件归属
version: "1"                           # 插件代码版本,独立于内容 schema_version
entry: ./plugin.py:create_pipeline     # 工厂入口,文件路径相对插件目录解析
binding_name: example-incident-report  # 稳定的消费与调度标识,与发现目录项名称一致
scope_ids: [team-a]                    # 处理的已有 Scope 名单;省略时动态发现积压,不授予权限
max_sources: 20                        # 每次消费扫描的 Source 条目上限,过滤后输入可能更少
processing:                            # Supervisor 的调度与 Worker 执行配置
  interval_seconds: 60                 # 自动检查待处理工作的间隔(秒),按检查开始时间计算
  max_workers: 1                       # 该 binding 的并发 Worker 数量上限
  timeout_seconds: 300                 # 单次 Worker 执行的总超时(秒)
config:                                # 由插件 Config 模型校验的业务配置
  title_prefix: 工单报告               # 示例插件用于生成报告标题的配置值

scope_ids 显式填写时必须是非空的已有 Scope 名单。清单不保存 enabled 状态,不携带 Server 提交凭据; 秘密通过部署资源引用管理。

以下插件为每个精确工单快照创建一份报告。Source 必须已经按 Definition 保存 powercontext.text-evidence@1; Artifact 插件不重新访问工单系统。

import hashlib
import json

from pydantic import BaseModel, ConfigDict
from powercontext.artifact_plugins import (
    ArtifactDraft, ArtifactFamily, GenerationBatch, GenerationContext, InputContract,
)
from powercontext.sources import SourceProjectionKey, TextEvidence

plugin_api_version = "1"


class Config(BaseModel):
    model_config = ConfigDict(extra="forbid", frozen=True)
    title_prefix: str = "工单报告"


class IncidentReport(BaseModel):
    model_config = ConfigDict(extra="forbid", frozen=True)
    title: str
    evidence_text: str


families = (
    ArtifactFamily(
        family="incident-report", schema_version="1", content_model=IncidentReport,
    ),
)
inputs = InputContract(
    projections={
        "example-ticket": SourceProjectionKey(
            name="powercontext.text-evidence", version="1",
        ),
    },
)


class Pipeline:
    def __init__(self, config: Config) -> None:
        self.config = config

    async def generate(self, batch: GenerationBatch) -> list[ArtifactDraft]:
        drafts = []
        for source in batch.sources:
            evidence = TextEvidence.model_validate(source.value)
            identity = json.dumps(
                source.ref.model_dump(mode="json"),
                ensure_ascii=False, sort_keys=True, separators=(",", ":"),
            )
            drafts.append(ArtifactDraft(
                family="incident-report",
                schema_version="1",
                artifact_id=hashlib.sha256(identity.encode("utf-8")).hexdigest(),
                expected_revision=0,
                content=IncidentReport(
                    title=self.config.title_prefix, evidence_text=evidence.content,
                ).model_dump(mode="json"),
                source_refs=(source.ref,),
                artifact_refs=(),
            ))
        return drafts


async def create_pipeline(ctx: GenerationContext, config: Config) -> Pipeline:
    return Pipeline(config)

首次加载(启动扫描或显式 reload)完成后为 disabled;已登记插件的 reload 遵守第 6 节状态规则。 用户调用以下接口启用本次请求开始时已加载且 disabled 的插件, 再通过状态查询确认结果:

POST /v1/admin/artifact-plugins/enable-all
GET /v1/admin/artifact-plugins

首次启用从仍保留且允许读取的 journal 起点消费;再次启用从持久 cursor 接续积压。示例 ID 在同一 Scope 内 由精确 Source 身份确定,不依赖 Worker ID 或重试次数。模型调用失败应抛出异常,不能以空 drafts 表示失败。 无需输出时才返回 [],允许框架推进该窗口。

LLM 插件使用相同接口,在工厂中自行创建模型或网络客户端,通过 ctx.enter_async_context(...) 登记清理, 在 generate 中按执行预算调用模型并校验输出。模型不生成身份或 lineage;这些由插件根据实际证据构造。 结构验证不能证明生成内容事实正确。

3. 消费与查询分开

默认注册只开放 get / list。应用通过以下既有形状的公共接口访问自定义 family:

用途接口
浏览当前集合GET /v1/scopes/{scope_id}/artifacts/{family}
当前内容GET /v1/scopes/{scope_id}/artifacts/{family}/{artifact_id}
精确版本GET /v1/scopes/{scope_id}/artifacts/{family}/{artifact_id}/revisions/{revision}
声明式检索POST /v1/scopes/{scope_id}/artifacts/{family}/search
部署能力GET /v1/capabilities

需要全文检索时,插件须在首次注册前为输出 family 增加声明,不实现查询回调:

from powercontext.artifact_plugins import ArtifactSearchDeclaration, TextIndex

search = ArtifactSearchDeclaration(
    version="1",
    indexes=(
        TextIndex(
            name="lexical", fields=("title", "evidence_text"),
            projection_version="1",
        ),
    ),
    modes=("text",),
    default_mode="text",
    defaults={"text": {"text": ("lexical",)}},
)
# 将 search 传给上例 ArtifactFamily 的 search 参数。

应用调用 /search,请求 {"query":"timeout","mode":"text","limit":10},获得完整报告及精确引用。 检索只提供有界候选,不能用 top-k 证明全部事故数或历史中不存在某对象;完整枚举使用分页 list 或领域发布清单。 停用或卸载生成插件不撤销已经保存的报告、历史证据及持久检索声明;索引重建期间的可用性遵循第 8 节。

参考层说明

4. 输入、身份与证据

身份契约
plugin id / version插件归属和代码版本,不是进程身份
family输出类型;本版一个自定义 family 归属一个 binding,不覆盖内置 family
binding_name稳定消费身份;cursor 按 (scope_id, binding_name) 隔离
schema_version不可变内容结构的版本,独立于插件代码版本
Artifact revision同一 Scope / family / artifact_id 下的精确内容版本
binding_generation单调递增的注册代次,使旧配置下的 assignment 失效
Supervisor 任期、请求代次沿用既有执行所有权和完成确认语义,不与注册代次合并

插件作者提供以下契约;加载时校验声明和身份冲突,不调用工厂。

插件入口或声明职责
plugin_api_version / Config声明框架支持的 API 版本,定义并校验插件业务配置
families恰好一个输出 family,声明 schema_version 和 JSON object 内容模型
inputs非空 Source type 到 Projection 名称 / 版本的映射;可声明额外允许读取的 Artifact family,不授予权限
factory接收 GenerationContext 和已校验配置,在 Worker 中为本次调用创建 pipeline 与业务资源
pipeline.generate(batch)根据输入返回待提交 drafts;框架负责验证、保存及推进进度
可选 search声明输出 family 的索引、模式及默认选择,由框架提供检索,不是业务查询回调

内容模型必须能形成可持久验证的 JSON Schema;无法在插件卸载后解码和验证的格式在接受前拒绝。 相同 (family, schema_version) 不允许更换内容 schema。

每个 Source type 选择一个明确的 Projection 名称和版本,可同时接受工单与聊天等不同类型。每条 GenerationSource 包含精确 ref、projection 和保留原始结构的 JSON value。读取已保存的自定义 Projection 不要求 Server 或 Artifact Worker 重新加载 Source 插件,不强制转换为 TextEvidence。批次不保证所有类型齐备,不做隐式配对或等待。

GenerationContext 固定当前 Scope,以部署的后台身份执行授权检查。默认可读输出 family, inputs.artifact_families 可声明额外 family;声明仅限制范围,不授予访问权限,也不建立 Artifact 依赖触发链。

  • read_latest 返回当前内容和精确引用,缺失按 SDK 契约返回空;read_revision 读取指定版本,缺失明确失败, 不回退到 latest。各次读取检查当前权限。
  • list_artifacts 和 search_artifacts 用于选择候选。即使搜索已经返回完整内容,生成器仍须显式精确读取所选 Artifact,以登记可用于 lineage 和更新依据的证据。
  • ArtifactDraft 包含 family、schema_version、artifact_id、expected_revision、JSON object content、 source_refs 和 artifact_refs。同一窗口不得重复输出同一 Artifact 身份。
  • 创建使用 expected_revision=0;更新必须先读取已有版本并提供其 revision。使用旧内容时须把精确引用写入 artifact_refs;仅用其版本作更新条件不强制记录为内容证据。
  • 框架拒绝未实际读取、跨 Scope 或无权访问的证据,最终提交再次校验权限与资格。插件选择实际使用的证据子集, 框架不能从业务代码中推断语义依赖是否完整。

例如读取 revision=3 后计算新内容,仅当提交时 head 仍为 3 才写 revision=4,否则整个窗口失败并重新读取、计算。 读取期间不保持贯穿模型调用的长事务。连续 latest 或多次分页不形成跨 family 快照;需要历史一致性时,应用先固定 持久发布根的精确引用,再沿其中的精确版本清单读取。后续发布不会改写已经固定的证据。

5. Artifact 生成、提交与失败

Supervisor assignment 指定 Scope 和执行资格,不携带 Source 列表。通用处理器在 Worker 内读取 journal, 并根据持久 cursor 选择有界窗口。合法 lineage-only Source 及未接受的类型可过滤, 成功后仍推进完整窗口;已接受类型缺少指定 Projection、版本不符或读取权限不足时整窗失败,不换投影或静默跳过。

sequenceDiagram
    participant S as Supervisor
    participant W as Artifact 插件通用处理器(Worker 内)
    participant P as 插件 pipeline
    participant D as 持久存储
    S->>W: Scope assignment 与注册代次
    W->>D: 读取 cursor、窗口及已保存 Projection
    W->>P: generate(batch),事务外执行
    P-->>W: drafts
    W->>W: 校验;索引 ready 时准备投影 / embedding
    W->>D: 开始短事务;复核代次、权限、head、cursor
    W->>D: 原子写 revisions、lineage、投影或变更记录、cursor、ack
    D-->>W: 提交结果
    W-->>S: 清理资源、退出
    S->>D: 验证持久完成确认

每次消费新建 pipeline,不跨窗口、Scope 或重试复用。无窗口或过滤后无输入时不调用 generate,完成相应确认; 非空输入最多调用一次 generate。成功事务包含全部 drafts、精确 lineage、cursor CAS 和 ack, 以及 ready 时的受影响投影或构建期间的变更记录;提交时按当前索引状态协调,见第 8.3 节。 新到达的 Source 留给后续窗口,确认不能吞掉更晚的请求代次。输出、证据、head 或 cursor 冲突均整窗回滚。

失败位置结果与恢复
加载、资源初始化、读取、生成或 ready 索引投影准备不提交、不推进;清理已登记资源,按既有退避重试
提交前验证或写入整个事务回滚,重新读取并生成
提交结果未知后续受保护调用检查持久 cursor 和 ack;不假定回滚后换 ID 补写
提交后清理或退出报告失败已提交结果有效,不能因此重复消费已确认窗口
Worker 超时且可回收确认退出后释放额度、按策略重试
无法确认 Worker 退出或失去 Supervisor 任期触发既有任期撤销与回收保护,可能暂停其他 binding

进程正常退出不能代替持久 ack。持续坏输入需修复或停用 binding,不因重试次数自动跳过。 生成可能重复计算,不承诺模型调用、计费或外部副作用恰好一次。强制终止不能保证清理回调执行或远端请求被撤回。

一次调用受 Worker 总超时、每 binding 的并发额度、窗口条目数及有限的输入字节、输出条数、输出字节预算约束。 输入按完整 Projection JSON 序列化字节计算,生成前检查;输出提交前检查。超限明确失败,不能截断证据或部分保存。 具体默认值和配置面在实现 PR 中确定;返回值限制不是内存沙箱。

6. 热管理、恢复与升级

启动只自动发现新目录项,独立校验成功后注册为 disabled;单项失败不阻止其他合法插件。已登记插件恢复持久配置 和管理状态,不通过扫描隐式更新或重新启用。运行中新增及升级显式 reload,不监听文件变化,不自动安装依赖。 代码与依赖预部署;保存解析后的版本目录和代码指纹,Worker 加载时重新核验。指纹不代替依赖锁定或代码信任。

状态含义
disabled有有效定义,暂停生成
enabled已装配且允许派发和提交
unloaded无执行装配或配置快照;保留身份、代次、schema、内容与 cursor
failed已接受的管理转换失败,暂停生成,需修复后 reload 或停用 / 卸载
activating / stopping / unloading管理目标已受理但尚未完成,不代表已经启用或退出

持久保存 desired_state 和 phase;只有 phase=enabled 可派发和提交。同一 binding 的转换串行,转换中重复变更冲突。 候选校验在限时子进程中完成,不调用工厂或创建模型连接;校验失败保留原定义和状态,首次校验失败不建立有效注册。

一期在首次注册时固定 family 检索声明的 version、完整 indexes 定义和 schema 身份。声明 version 变化及索引新增、删除、 改名、类型、projection_version、profile、字段或片段映射等定义变化,均在接受前返回冲突(HTTP 409),保留原声明和索引状态, 不中断原有搜索。空库同样适用,卸载或重启不解除限制。reload 可更新生成代码、普通配置、Scope,以及以下查询策略字段: ArtifactSearchDeclaration 的 modes、default_mode、defaults、candidate_limit、rrf_k、text_weight、vector_weight。 策略更新须通过原有声明校验,并沿用下述 reload 接受流程持久保存,不改变常规 Worker 生命周期;可用性和读取规则见第 8.2 节。 已有检索 family 新增此前未登记的 schema_version 也按上述规则拒绝,即使 search 完全相同。 无检索 family 可按内容版本规则新增 schema_version,但必须保持无检索;首次未声明检索不能后补。

允许的插件定义或配置变更通过校验后,按以下顺序执行: 检查 expected_generation 并接受变更、递增代次 → 停止目标派发并回收旧 Worker → 确认退出后装配新定义 → 恢复允许的调度并对账积压。进程回收在数据库事务外。接受后的装配或回收失败进入 failed, 不会自动恢复旧代次;旧 Worker 未退出不得报告卸载完成或启动替代执行。 管理切换不撤销已有检索的 ready 资格;期间暂停目标 binding 的生成, 完成切换后恢复生成调度不以索引构建完成为前提。

每次派发任务时,Supervisor 将插件当前的注册代次(binding_generation)写入任务; Worker 在启动和提交结果时检查该代次是否仍然有效。管理撤销与业务提交必须原子协调, 保护覆盖整个结果 / cursor / ack 事务:提交先完成则保留结果,撤销先完成则拒绝旧 Worker 的整个提交。 迟到事件不得改变新代次状态,正常单插件操作不撤销共享 Supervisor 任期。

管理接口均要求 server.admin,只使用统一目录下的 binding 名称,不接受代码上传、任意路径或请求内配置:

接口(前缀 /v1/admin/artifact-plugins)语义
GET /、GET /{binding_name}状态、代次、定义摘要和安全诊断,不返回秘密
POST /enable-all固定当前 disabled 集合及代次,逐个启用;不扫描目录,不回滚其他项的成功
POST /{binding_name}/reload重新校验目录项并登记;正常更新保留原启停目标
POST /{binding_name}/enable启用保存的有效定义;unloaded 必须先 reload
POST /{binding_name}/disable撤销旧执行,保留定义
POST /{binding_name}/unload撤销并回收执行,移除装配与配置快照,不删除代码或业务数据

单插件变更携带 expected_generation,新注册为 0,其他操作使用 GET 返回值;过时代次冲突。 相同定义与目标已稳定时可返回当前状态。异步受理返回 202 和查询位置,响应丢失先查询状态。enable-all 无需请求体, 跳过 enabled、unloaded、failed 及转换中项;并发变更逐项报告冲突,最终状态仍通过 GET 确认。

正常 reload 保留 enabled / disabled;首次、卸载后或 failed 修复后的 reload 均为 disabled。重启恢复持久目标并继续 未完成转换;恢复 enabled 时核验代码并更新代次,失败保持 failed,不能要求所有正常插件重新 enable-all。 卸载记录不被扫描复活;身份和 family 归属保留,不能借重装接管另一插件的数据。

动态发现覆盖注册前及未来新 Scope 的积压;显式名单通过 reload 修改,移出 Scope 保留其 cursor 与结果。 兼容代码更新仅影响未消费窗口,回滚不回退 schema、数据或 cursor。输入契约增加新类型不自动补算已越过的记录, 历史重放和身份迁移需要另行设计。普通生成失败不把管理 phase 改成 failed。

7. 持久化与接口兼容

数据安排
插件注册扩展 pc_artifact_processing_binding_states:归属、配置快照、binding_generation、desired_state、phase、last_error
内容声明新增 pc_artifact_family_schemas;持久保存不可变内容 schema、固定索引定义及可更新的查询策略
Artifact 内容复用 pc_artifacts、pc_artifact_heads、lineage 和公共写入层,每个 revision 保存 schema_version
消费与调度复用 pc_source_cursors、intent、lease 和完成确认,不新建执行历史或提交回执表
索引框架管理派生投影、单份目标配置和构建进度

通用 JSON codec 按该 revision 的持久 schema 读取,不依赖 Python 类仍可导入。同一 (family, schema_version) 的内容结构不可变。无检索 family 可通过新 schema_version 演进内容结构,已有检索 family 不允许新增未登记的内容版本。 历史按原版本解释,不为重建索引重写正文或 lineage;卸载后历史仍可读,旧 schema 不自动删除。 注册 family 不自动开放通用创建、tags、审核或 Recall;能力发现与已实现操作一致。

OpenAPI、SDK、运行时 family 注册与公共读取接口需支持插件注册的自定义 family。

自定义检索统一使用 /search 和公共 SDK 检索接口,返回 Artifact 内容与精确引用。持久检索声明必须能解析为 命名索引;不兼容的存储在接受写入前明确拒绝,转换及重建不得丢弃历史内容或重新解释其 schema。

8. 统一检索与可选索引

8.1 检索能力与请求

插件通过可选的 search 声明接入文本、向量或混合检索,无需实现查询回调。应用可选择命名索引,获得完整 Artifact、 精确版本引用和可选评分;未声明检索的 family 仍可通过 get / list 读取。检索面向当前有效内容,历史版本通过精确引用读取。

HTTP、SDK 和 GenerationContext 共用 ArtifactSearchService,由框架按声明装配通用 ArtifactSearcher; 内置 family 保留各自策略。检索与索引维护独立于生成 binding,生成停用、卸载或代码删除后仍可按持久声明运行。 编码资源由部署侧提供、框架管理,不依赖生成 factory;直接提供兼容查询向量时无需调用查询编码器。

字段自定义 family 的请求约定
modetext / vector / hybrid;省略使用声明的默认模式,不因故障切换
query普通文本,非空且最多 8192 字符;text / hybrid 必填
query_vector向量及完整 EmbeddingProfile;vector 在 query 和 query_vector 中恰选一个,hybrid 必须有 query,可另传兼容向量
indexes按 text / vector 选择命名索引,如 {"text":["lexical"],"vector":["semantic"]};省略使用声明的默认选择,歧义明确失败
limit / include_scoreslimit 默认 10、范围 1–200,按 Artifact 计数;include_scores 默认 false
其他参数fusion、min_score、filters、admission、rerank 仅接受声明且实现支持的组合

公共请求需支持纯向量输入,内置 family 的请求约束保持不变。响应复用 SearchArtifactsResponse.results,包含 family、 artifact_id、revision、完整 content、lineage 及可选 scores;schema_version 沿用公共内容表达。 retrieval 是有限的 [0,1] 分数,channels 保留原始度量和方向,评分不表示跨查询或 family 可比的概率。

未知 family 返回 404;非法输入、不支持的参数或不兼容空间返回 422;已声明能力未就绪或所需资源不可用返回 503。 鉴权和内部错误沿用 401 / 403 / 500。成功且无命中才返回空 results,hybrid 必需通道失败不降级。 /v1/capabilities 描述部署支持范围;某个 Scope 的索引是否可用,按第 8.3 节判断。 Recall 需要显式接入既有编排并保留权限、精确引用和候选/上下文预算,不随新 family 自动启用。

8.2 索引声明与结果选择

插件每次声明一个内容 schema_version,search 为该内容 schema 声明索引名称、提取规则、projection_version、 支持模式、默认选择和参数约束。索引名称在 family 内唯一;version、indexes 和 schema 身份固定,仅第 6 节列出的查询策略 字段可更新,一期不提供多 schema 提取规则配置。 搜索覆盖所选索引全部适用的 active head,不能跳过已声明但尚未构建完整的部分。

策略更新后,原 ready 索引继续可用,不触发重建、停搜或重新编码,也不改变未完成构建的进度。查询从持久声明读取 最新策略,构建期间、重启后和卸载后均遵循此规则;并发在途查询保持其一致读快照。构建 manifest 保留构建时快照、 索引身份和进度,不作为最新查询策略的来源;策略更新不遍历或更新所有 Scope,不新增配置接口。

能力插件声明或提供框架负责
文本检索必填顶层字符串字段及命名索引提取文本、按中英文分析规则索引,以关键词 OR 匹配普通查询文本
从文本生成向量持久文本字段或片段、向量空间及命名索引调用兼容编码器生成文档/查询向量,维护和重建索引
使用插件自带向量content 中的向量或片段数组、对应的模型/空间身份及命名索引校验、提取并索引持久向量,按兼容空间检索

例如,报告的标题和正文可建立 lexical 文本索引,正文另建 semantic 向量索引,由框架生成 embedding。 应用选择 text 时按关键词搜索,选择 hybrid 时合并两个索引的结果。已有图像特征的插件也可直接保存并声明向量, 不需要框架重新编码原始图像。分析和索引处理均不替换原始 content。

向量复用 EmbeddingProfile:profile_id、model、dimension、distance=l2、normalization=none / unit。 同维度不代表空间兼容;模型、模态和预处理语义须明确,不能推断旧记录未保存的信息。插件自带向量在对应正文 revision 中保存完整 EmbeddingProfile,由声明的 profile_field 提取;片段数组在各片段中保存对应 profile。框架按完整定义校验 空间一致性,历史向量的模型身份不随当前检索声明变化。同一请求所选向量索引须有兼容查询空间; 没有兼容文本编码器的图像空间只能使用查询向量。

PowerContext 的部分内置检索路径已使用原生 ANN。自定义 Artifact 当前采用 exact L2,尚未接入原生 ANN 索引与候选查询。

向量必须有限、维度正确,unit 按统一规则归一化或验证,零向量不能作为单位向量。 支持单向量和插件显式提供的片段数组,不自动切片;片段 ID 在 revision / 索引内唯一。空数组是合法的零片段结果, 缺失必填字段、重复 ID 或非法向量则明确失败。

命名索引用于选择检索范围,所选索引按 text / vector 归入评分通道,fusion 权重和 scores.channels 均以 text / vector 为键。 各索引先按 Scope、权限及有效状态筛选,再计算相关性、为每个 Artifact 取最佳片段;同一 Artifact revision 在同类索引中 保留最佳原分,合并后应用通道候选预算。仅 hybrid 使用两通道加权 RRF,计算与归一化公式参见 搜索融合策略;声明限定可调参数,同类索引重复命中不累加贡献。 min_score 应用于最终归一化分数,再按 Artifact limit 截取;并列按稳定身份排序,片段数量不增加候选名额或重复计分。

结果读取遵循检索投影契约:所有通道与正文补齐共享一致读视图, 仅使用选定索引和同一次构建,返回命中的精确 revision。查询编码在事务外完成,随后重新核验构建状态; 发生变化则返回不可用。OceanBase 召回不 JOIN 业务表,资格在投影或预先确定的条件中维护,再批量读取精确正文。

8.3 索引维护与可用性

框架的索引维护运行时负责构建和恢复,插件提供声明与内容。每个 Scope / family 只保存一份目标索引配置, 并持久保存索引定义与空间、构建进度、投影完成记录和构建期间的内容变更。投影完成记录标明已处理的精确 revision, 合法零片段也记录;正文、head 和 lineage 保留原有身份,派生索引可以重建。

状态搜索正文读取与写入
全部目标索引 ready,且请求所需资源可用按声明提供检索get / list / 精确历史读取正常;正文、受影响索引、完成记录与消费进度原子提交,投影失败则该次写入失败
首次构建、清理、重建或失败重试中整个 Scope / family 的合法检索返回 503,包括只请求已完成的文本索引读取继续;正文、消费进度与变更记录原子提交,不维护旧索引,也不因目标编码器或物理空间未就绪阻止正文写入

删除、恢复和检索资格变化遵守同样的更新规则。提交时复核当前索引状态,防止并发写入漏记变更或绕过刚恢复的索引维护; 鉴权、版本和证据校验在所有状态下继续生效。完整但无内容的索引可以 ready;无当前 head 且无索引状态的空文本 Scope, 合法请求鉴权后可直接返回空结果。

声明了检索能力的 family 首次写入内容时建立索引状态。一期保留首次构建、正文增量维护及失败 / 重启恢复, 允许框架内部按原索引定义修复重建整套索引,不提供选择性重建或新的公开管理入口。首次构建或内部修复重建时, 该 Scope / family 按上表暂停搜索,并执行:

  1. 登记构建并清理:沿用固定索引定义,保存构建身份 build_id;修复重建时分批清理原投影和完成记录。
  2. 回填并追平:扫描当前内容,按提交顺序记录的变更补处理并发写入、删除和资格变化;投影、完成记录与进度共同提交。
  3. 校验并恢复:确认全部适用内容均已处理、没有旧片段残留且没有遗漏并发变化,再原子地将整套索引置为 ready。 期间发生变化则继续追平,不分通道开放。

build_id 独立于内容 revision 和插件注册代次,清理、构建和恢复检索均须核验它,旧任务不能影响新构建。 模型计算在事务外完成,保存前复核内容版本、资格和构建身份。失败或重启从持久进度接续,包括未完成的清理工作。 清理只影响当前 Scope / family 的派生数据,保留共享存储及其他数据,并保护在途查询的一致读视图;必要时等待其结束。

重建不重跑生成插件、不推进 Source cursor、不改写正文或 lineage。框架生成的文本向量可从持久文本重新编码。 插件自带向量按原索引定义从持久内容恢复,不提供在线索引定义迁移或向量迁移。历史版本保留原 schema 和模型含义。

生成停用或卸载不影响索引恢复,资源缺失时保留进度等待重试;持续写入可能延长就绪时间。 维护只处理明确触发和未完成的工作,不周期性遍历全部 family / Scope,不新增调度器、队列表或配置; 已 ready 的索引在重启时不重建。

存储由框架管理:SQLite 使用共享向量表,OceanBase / seekDB 按完整空间使用原生 VECTOR(d) 表,不复用 Memory 专用表。 投影保留 Scope、family、revision、索引、片段和构建身份,并校验完整 profile 关联;插件不指定物理表或 DDL。 统一数据库初始化负责创建并校验缺失的管理表、文本索引和向量空间;reload、正文写入和后台构建只操作数据。 新插件首次注册所需的原生向量空间若尚未预配,需再次执行数据库初始化(例如重启 Server)才能开始构建,其间适用上表的不可用状态。 已有表升级与完整版本迁移不在本提案范围内;后端须满足原子更新和一致读要求,才可开放相应能力。

缺点

可信 Python 插件使用 Worker 的操作系统权限,可访问进程可用的文件、网络和凭据。受控 SDK 约束标准调用, 不限制任意 Python 系统访问。子进程隔离普通故障,不提供不可信代码沙箱、供应链认证或内存 / CPU 硬配额; 更强隔离由部署环境提供。

每窗口重新加载和初始化有成本,共用环境要求依赖兼容。ready 时同步维护索引增加写入延迟, 所需投影计算失败可阻止该次正文提交。重建期间检索不可用,正文写入继续;持续写入可能延长追平与就绪校验。 插件自带向量同时保存在正文和索引中,增加存储开销。

设计理由与替代方案

方案取舍
每个 family 修改核心代码接口直接,但业务扩展受核心发布制约,重复版本与消费逻辑
每插件一个常驻实例可摊薄初始化成本,但引入状态复用、取消和升级协议,超出单窗口生成需要
Worker 调用远程生成服务适合专用算力、用户侧网络或异语言;需另定身份、证据序列化、超时、取消和迟到结果协议

统一读取由框架解释持久 schema,而不是调用插件 reader,才能兑现卸载后仍可读和可重建。 业务查询放在应用层,避免问题类型和答案协议绑定生成生命周期。

向量物理表采用共享投影而非 Memory 专用表,保留 family、多索引、片段和构建身份。exact L2 是当前适配选择, 不是插件框架对后端能力的限制。自定义索引接入已有 ANN 能力时,须明确近似召回语义,以及多片段折叠、权限过滤后 候选不足的处理方式,并保持索引隔离、资格校验、Artifact 去重和精确版本读取。

参考设计

复用的主线基础本提案新增的通用能力
Supervisor、Worker 执行与回收插件声明校验、注册及热管理
Source journal / cursor、受控证据读取与事务提交按输入契约消费持久 Projection 的通用生成处理器
Artifact revision、head、lineage 及公共读取持久 schema 驱动的自定义内容校验与读取
Artifact Search 分派与公共检索契约可选声明式索引装配、重建及整体就绪控制

未决问题

以下事项由实现 PR 给出具体方案和证据,维护者在对应能力首次发布前确认;不能借此推迟本文的原子提交、 代次保护或历史读取约束。

事项已确定边界与待决定内容
SDK 与内容 schemaAPI v1 单 family;确定正式导出及可持久 JSON Schema 子集
预算与资源必须有界且超限不部分提交;确定配置默认值、实际工作负载预算和诊断方式
后端支持矩阵每种模式实际验收后才公开;给出 SQLite / OceanBase / seekDB 的版本、规模与维护限制
可观测性复用既有身份、操作词汇及 log_safely,不记录正文、向量或秘密;新增字段按开发指南登记并同步双语契约

后续可能性

以下方向可另行设计,不纳入本提案:

  • 生成能力:远程生成、常驻 pipeline、多 family 联合输出、历史重放,以及消费同一 Source 的多个 Projection。
  • 插件管理:插件数据彻底清理、执行历史与回执、代码分发、签名和安全沙箱。
  • 检索能力:在线索引定义迁移、向量迁移、选择性重建、其他距离度量、任意 JSON 条件索引和历史 revision 搜索,需另行明确预算、兼容与准确性边界。

跨 Scope 生成、任意 Artifact 依赖触发链、自动拆窗跳过坏输入、业务查询 handler 和通用任务队列不在本提案范围内。

On this page