核心摘要

本文提出的四层模型是一种工程拆分,而不是厂商标准:指令层定义稳定策略,知识层提供任务证据,记忆层携带跨轮状态,编排层选择并校验其他层。只有当每层都有负责人、接口、信任模型和可测量的失败路径时,分层才真正有价值。

不要把某层理解为上下文窗口的固定百分比。Token 限制、价格、缓存行为和模型注意力会随供应商与版本变化。应在实际部署的模型和工作负载上测量最终请求。

为什么需要分层

把所有内容拼成一个 Prompt 会隐藏关键差异:

失败现象 常见原因 分层控制
重要规则消失 历史或检索噪声过长 预留并校验指令预算
引用过期事实 没有新鲜度和权威性元数据 知识路由与来源检查
用户状态丢失 无界截断 显式记忆策略与压缩测试
成本和延迟上升 每次请求携带全部信息 编排、预算和遥测

模型在推理时仍只接收一个请求。分层改善的是构建和验证流程,并不会创造新的注意力机制。

graph TD O["编排:选择、预算、校验"] --> I["指令:策略与输出契约"] O --> K["知识:检索证据与 Schema"] O --> M["记忆:会话状态与获准偏好"] I --> C["最终请求上下文"] K --> C M --> C C --> L["模型或兼容运行时"]

第一层:指令层

指令层是相对稳定的契约,包括安全边界、能力范围、输出 Schema 和项目约定。它应版本控制并保持短小。好的规则需要说明可观察行为和验证方法:

typescript
type InstructionSet = {
  version: string;
  globalRules: string[];
  domainRules: Record<string, string[]>;
  forbiddenActions: string[];
  outputSchema?: string;
};

function buildInstructions(set: InstructionSet, domain?: string): string {
  const rules = [
    ...set.globalRules,
    ...(domain ? set.domainRules[domain] ?? [] : []),
  ];
  return [
    `## Contract ${set.version}`,
    '### Rules',
    ...rules.map(rule => `- ${rule}`),
    '### Do not do',
    ...set.forbiddenActions.map(rule => `- ${rule}`),
    set.outputSchema ? `### Output schema\n${set.outputSchema}` : '',
  ].filter(Boolean).join('\n');
}

任务请求不能静默覆盖授权、密钥处理或合规策略。两个受信规则冲突时,应返回冲突并交给人工处理。厂商规则文件只是适配器,其路径和优先级必须结合客户端版本核验。

text.length / 4 这类 Token 估算只能用于粗略诊断,不能代表计费或模型真实 Token 数。预算应使用目标供应商的 Tokenizer,并记录模型版本。

第二层:知识层

知识层是动态证据,包括文档、API Schema、数据库元数据和批准的工具说明。检索结果不会自动变成事实;应同时保存来源、版本日期、权威性、租户和访问决策。

typescript
type KnowledgeChunk = {
  id: string;
  text: string;
  source: string;
  updatedAt: string;
  authority: 'official' | 'reviewed' | 'unknown';
  tokenCount: number;
  relevance: number;
};

function selectKnowledge(
  chunks: KnowledgeChunk[],
  budget: number,
): KnowledgeChunk[] {
  const eligible = chunks
    .filter(chunk => chunk.authority !== 'unknown')
    .sort((a, b) => b.relevance - a.relevance);
  const selected: KnowledgeChunk[] = [];
  let used = 0;
  for (const chunk of eligible) {
    if (used + chunk.tokenCount > budget) continue;
    selected.push(chunk);
    used += chunk.tokenCount;
  }
  return selected;
}

生产检索需要定义查询路由、租户过滤、ACL、新鲜度、去重、重排、引用格式和“没有证据”时的响应。相关性分数不是安全决策,也不能证明事实正确。应评测检索精度、过时来源比例、引用覆盖率和未授权数据泄露。

工具 Schema 只能表示客户端可以提出的能力;服务端必须独立校验参数并执行授权,模型不能通过生成工具调用自行获得权限。

第三层:记忆层

记忆是状态,不是无限增长的对话转录。至少分开:

  • 工作记忆:当前请求和即时工具结果;
  • 会话记忆:经过批准的摘要和未决决定;
  • 长期记忆:带同意、留存、删除和租户范围的用户或组织事实。

结构化状态可以使用确定性压缩,散文摘要可以调用模型辅助,但摘要有损且在校验前不可信:

typescript
type Turn = {
  role: 'user' | 'assistant' | 'tool';
  content: string;
  createdAt: number;
  tokenCount: number;
};

function compactHistory(
  turns: Turn[],
  keepRecent: number,
  maxTokens: number,
): { recent: Turn[]; older: Turn[] } {
  const recent = turns.slice(-keepRecent);
  let used = recent.reduce((sum, turn) => sum + turn.tokenCount, 0);
  const older: Turn[] = [];
  for (let index = turns.length - keepRecent - 1; index >= 0; index -= 1) {
    const turn = turns[index];
    if (used + turn.tokenCount > maxTokens) break;
    older.unshift(turn);
    used += turn.tokenCount;
  }
  return { recent, older };
}

未经来源和策略检查,不要把用户说法或工具结果提升为长期记忆。应支持删除、纠正、过期和租户隔离,并用召回率、错误记忆率、过期记忆率和删除测试评估记忆系统。

第四层:编排层

编排层组装最终上下文并负责预算。它应是可审计的策略,而不是不透明的字符串拼接:

typescript
type ContextParts = {
  instructions: string;
  knowledge: string;
  memory: string;
  task: string;
};

type Budget = {
  totalTokens: number;
  instructions: number;
  knowledge: number;
  memory: number;
};

function assemble(parts: ContextParts, budget: Budget): string {
  // 生产环境应替换为目标供应商的 Tokenizer。
  const estimate = (text: string) => Math.ceil(text.length / 4);
  const required = estimate(parts.instructions) + estimate(parts.task);
  if (required > budget.totalTokens) {
    throw new Error('required context exceeds the configured budget');
  }
  return [
    '## Instructions',
    parts.instructions,
    '## Evidence',
    parts.knowledge,
    '## Memory',
    parts.memory,
    '## Task',
    parts.task,
  ].join('\n\n');
}

生产实现应为每层计数、为响应预留空间、只截断可选证据,并在必要策略无法装入时安全失败。记录输入/输出 Token、延迟、缓存、检索结果、工具调用、重试和人工修正。不要声称固定配额适用于所有模型。

评测与失败路径

上下文变化应像代码一样评估:

yaml
case: "answer-with-current-policy"
fixture:
  tenant: "synthetic-tenant"
  policy_revision: "2026-01"
assertions:
  - "只查询 fixture 租户"
  - "过期策略不能被引用为当前策略"
  - "缺少证据时明确表达不确定性"
  - "工具参数通过服务端授权"
record:
  model: "确切模型和版本"
  tokenizer: "确切 Tokenizer"
  context_revision: "git commit"

加入负向和对抗用例:检索文档中的 Prompt Injection、畸形工具结果、缺失记忆、冲突指令、过期凭证、超大文档和供应商超时。把质量、安全、成本、延迟和恢复能力分开测量。

安全与运维

检索和工具使用最小权限。日志脱敏密钥和个人数据,默认不要持久化完整 Prompt。需要可复现时固定 Schema 与供应商版本。每条记忆都应有租户、来源、创建时间、过期/复核策略和删除路径。

四层模型不能替代普通应用控制:授权仍在服务端执行,输出仍需校验,模型响应在应用代码和测试接受前只是提案。

延伸阅读

总结

四层模型的价值在于分离职责,而不是成为通用规范。让指令受治理、知识有来源、记忆有同意和删除机制、编排可测量;当每层都有明确的信任与失败边界时,系统就能演进,而不会把更长的 Prompt 当作工程能力的替代品。