20 KiB
提示词标准化设计
1. 设计目标
本设计建立项目内部的通用提示词模型,用来统一工作区、收藏、优化历史、测试结果、外部导入、图像提示词等场景。
目标不是先改某一个收藏字段,而是先定义稳定的领域语言:
- 一个提示词资产是什么。
- 一个工作区会话是什么。
- 一条优化链是什么。
- 一次测试运行和一个可复现示例有什么区别。
basic / pro / image三类模式如何用同一套结构表达。- 旧
FavoritePrompt、旧PromptRecordChain、旧session/v1/*如何兼容到新模型。
本文先描述标准领域模型和目标语义;当前已经落地的实现边界见 2.3,不要求一次性替换现有存储和 UI。
2. 核心结论
2.1 模型分层
PromptAsset
├─ PromptContentVersion[] // 长期资产正文版本
└─ PromptExample[] // 长期可复现示例
PromptSession
├─ assetBinding? // 最多绑定一个资产
├─ draft // 当前工作区草稿
├─ PromptOptimizationChain // 有且只有一条主优化链
└─ PromptTestRunSet[] // 会话内测试运行
PromptOptimizationChain
├─ root // 原始提示词
└─ records[] // 优化/迭代输出,可为空
2.2 关键不变量
- 一个 session 有且只有一条主
PromptOptimizationChain。 - 一个 session 最多绑定一个
PromptAsset。 - 一个 asset 可以被多个 session 打开、派生或继续编辑。
- optimization chain 可以是 root-only:只有原始提示词,没有任何优化结果。
- 原始提示词可以直接测试,测试结果属于 session test run。
- 点击“优化”创建新的 session 和新的 optimization chain。
- 点击“迭代/继续优化”追加到当前 session 的当前 chain。
- 资产正文版本链只记录用户明确保存的资产正文,不自动等于优化历史。
- 测试运行不是资产示例;只有用户明确保存测试结果时,才转成
PromptExample。
2.3 当前落地状态(2026-05-02)
截至 2026-05-02,标准模型已经进入“底层模型、兼容适配层、收藏资产写入、示例保存、来源坐标和媒体资产维护已落地,显式多 session 产品形态尚未落地”的阶段:
@prompt-optimizer/core已新增并导出services/prompt-model,包含 mode、content、favorite、history、session、example 等纯类型和转换函数。FavoritePrompt仍是收藏服务的持久化容器;metadata.promptAsset是标准资产快照;metadata.reproducibility是用户可编辑的变量/示例草稿;metadata.gardenSnapshot只读保留来源快照。- 普通工作区保存收藏只保存正文和变量定义,不再自动生成
workspace-current示例。 - 测试结果只有在用户点击“保存为示例”时,才从
PromptTestRun转成PromptExample/ reproducibility example。 - 现有
session/v1/*仍作为隐式 session 使用,但已经能携带assetBinding和origin,并通过useSessionManager.getPromptSession()/ hydrated session 投影到标准PromptSession。 - 从收藏或 PromptAsset 应用到工作区时,会写入隐式 session 的来源和资产版本绑定;重新优化、分析、清空内容时会清理旧绑定。
- 工作区保存、测试结果保存和更新已有收藏都通过显式保存目标面板确认;已有来源坐标只用于默认选择目标,不代表可以静默写回旧收藏。
- 保存测试结果为示例时,示例绑定提示词资产 / 收藏;
basedOnVersionId和来源坐标只用于追溯,不要求当前 workspace 正文与目标资产当前正文严格一致。 - 收藏创建 / 编辑会通过 FavoriteManager 刷新
metadata.promptAsset;显式更新正文时,正文变化会创建新的 content version;只追加示例时不会修改正文版本链。 pro-conversation在标准层使用messages;当前 UI 仍复用既有pro-multistore key,并已支持把收藏中的 messages 恢复为多消息会话。文本拼接只作为兼容降级。- 导入导出和媒体资产清理已经扫描
metadata.promptAsset、当前 reproducibility、Garden snapshot 和 legacy 结构中的图片引用。
仍未落地的部分:
- 用户可见的“新建 / 切换 / 关闭 session”入口和多 session 列表。
- 独立的资产正文版本管理 UI,例如版本差异、冲突提示、手动切换 / 合并策略。
- 测试结果示例的更完整批量管理体验;单个测试结果保存和追加语义已落地,批量选择多个结果保存为多个 example 尚未落地。
- 收藏详情来源分区、Garden 来源展示层级、完整会话消息可视化编辑体验仍需单独设计。
- 当前没有未关闭的 active Trellis 任务承接这些后续项;需要继续推进时应先拆分新的 Trellis 任务。
3. 模式标准化
新模型只使用以下模式:
type PromptModeKey =
| 'basic-system'
| 'basic-user'
| 'pro-variable'
| 'pro-conversation'
| 'image-text2image'
| 'image-image2image'
| 'image-multiimage'
3.1 PromptContract
type PromptContract =
| BasicPromptContract
| ProPromptContract
| ImagePromptContract
type BasicPromptContract = {
family: 'basic'
modeKey: 'basic-system' | 'basic-user'
subMode: 'system' | 'user'
variables: PromptVariable[]
inputs?: PromptInputSlot[]
outputs?: PromptOutputSpec[]
}
type ProPromptContract = {
family: 'pro'
modeKey: 'pro-variable' | 'pro-conversation'
subMode: 'variable' | 'conversation'
variables: PromptVariable[]
inputs?: PromptInputSlot[]
outputs?: PromptOutputSpec[]
}
type ImagePromptContract = {
family: 'image'
modeKey: 'image-text2image' | 'image-image2image' | 'image-multiimage'
subMode: 'text2image' | 'image2image' | 'multiimage'
variables: PromptVariable[]
inputs?: PromptInputSlot[]
outputs?: PromptOutputSpec[]
}
3.2 历史字段映射
| 历史结构 | 标准结构 |
|---|---|
functionMode=basic, optimizationMode=system |
basic-system |
functionMode=basic, optimizationMode=user |
basic-user |
functionMode=context, optimizationMode=user |
pro-variable |
functionMode=context, optimizationMode=system |
pro-conversation |
functionMode=image, imageSubMode=text2image |
image-text2image |
functionMode=image, imageSubMode=image2image |
image-image2image |
functionMode=image, imageSubMode=multiimage |
image-multiimage |
context 只保留在 legacy adapter 中,新领域模型不再使用它。
4. 通用内容结构
4.1 PromptContent
type PromptContent =
| {
kind: 'text'
text: string
}
| {
kind: 'messages'
messages: ConversationMessage[]
}
| {
kind: 'image-prompt'
text: string
}
说明:
- basic 和多数 image 模式先使用
text或image-prompt。 pro-conversation使用messages,避免把多消息会话压成单字符串。- 旧
FavoritePrompt.content映射为PromptContent.kind = 'text'。
4.2 变量、输入、输出
type PromptVariable = {
name: string
description?: string
type?: 'string' | 'number' | 'boolean' | 'enum'
required: boolean
defaultValue?: string
options?: string[]
}
type PromptInputSlot = {
id: string
type: 'text' | 'messages' | 'image' | 'images' | 'variables' | 'custom'
label?: string
required?: boolean
description?: string
accepts?: string[]
metadata?: Record<string, unknown>
}
type PromptOutputSpec = {
id: string
kind: 'text' | 'message' | 'image' | 'images' | 'json' | 'custom'
label?: string
description?: string
metadata?: Record<string, unknown>
}
约束:
- 变量定义属于 contract。
- 变量值属于运行输入或示例输入。
defaultValue是模板级默认值,不等于某次运行时用户填入的变量值。- 图片输入输出统一通过
PromptImageRef引用。
4.3 PromptImageRef
type PromptImageRef =
| { kind: 'url'; url: string }
| { kind: 'asset'; assetId: string }
持久化结构优先使用 kind: 'asset'。kind: 'url' 只作为外部来源或兜底引用。metadata 中不应长期保存 inline base64 / data URL。
5. PromptAsset
PromptAsset 是长期提示词资产。收藏只是资产的一个入口。
type PromptAsset = {
schemaVersion: 'prompt-model/v1'
id: string
title: string
description?: string
tags: string[]
category?: string
contract: PromptContract
currentVersionId: string
versions: PromptContentVersion[]
examples: PromptExample[]
source?: PromptSourceRef
createdAt: number
updatedAt: number
metadata?: Record<string, unknown>
}
type PromptContentVersion = {
id: string
version: number
content: PromptContent
createdAt: number
updatedAt?: number
source?: PromptSourceRef
metadata?: Record<string, unknown>
}
约束:
- asset 是长期结构,session 是运行态结构。
versions只追踪资产正文演化。- 测试输入、变量值、模型输出、reasoning 不进入正文版本链。
- 旧收藏没有版本链时,normalize 层可以合成一个只读初始版本。
5.1 PromptExample
type PromptExample = {
id: string
title?: string
description?: string
basedOnVersionId: string
input: PromptRunInput
output?: PromptRunOutput
metadata?: Record<string, unknown>
}
type PromptRunInput = {
text?: string
messages?: ConversationMessage[]
parameters?: Record<string, string>
images?: PromptImageRef[]
metadata?: Record<string, unknown>
}
type PromptRunOutput = {
text?: string
images?: PromptImageRef[]
metadata?: Record<string, unknown>
}
约束:
- example 是长期可复现示例,不是一次临时测试运行。
basedOnVersionId是兼容当前模型的来源 / revision 线索,不表示示例必须绑定到当前资产正文版本,也不能作为追加示例前的正文一致性门禁。- example 可以记录输入输出,但不参与资产正文版本链。
6. PromptSession
PromptSession 是工作区运行态。一个 session 可以还没有保存为 asset,也可以绑定到一个 asset。
type PromptSession = {
schemaVersion: 'prompt-model/v1'
id: string
title?: string
modeKey: PromptModeKey
lifecycle: 'implicit' | 'active' | 'background' | 'closed' | 'archived'
createdAt: number
updatedAt: number
assetBinding?: PromptAssetBinding
draft?: PromptAssetDraft
optimization: PromptOptimizationChain
testRuns: PromptTestRunSet[]
origin?: PromptSessionOrigin
ui?: Record<string, unknown>
metadata?: Record<string, unknown>
}
type PromptAssetBinding = {
assetId: string
versionId?: string
status?: 'linked' | 'forked' | 'detached'
}
type PromptAssetDraft = {
title?: string
description?: string
content: PromptContent
variables?: PromptVariable[]
metadata?: Record<string, unknown>
}
type PromptSessionOrigin =
| { kind: 'blank'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'workspace'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'asset'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'favorite'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'history'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'garden'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'import'; id?: string; metadata?: Record<string, unknown> }
| { kind: 'external'; id?: string; metadata?: Record<string, unknown> }
约束:
assetBinding为空表示未保存草稿。- 一个 session 最多绑定一个 asset。
- 保存/收藏后,session 继续存在,只是绑定到持久化 asset。
- 清空工作区应视为创建新 session,而不是原地覆盖旧 session。
6.1 PromptSessionRegistry
type PromptSessionRegistry = {
schemaVersion: 'prompt-model/v1'
activeSessionId?: string
activeSessionIdByMode: Partial<Record<PromptModeKey, string>>
sessions: PromptSessionSummary[]
updatedAt: number
metadata?: Record<string, unknown>
}
type PromptSessionSummary = {
id: string
modeKey: PromptModeKey
title?: string
lifecycle: 'implicit' | 'active' | 'background' | 'closed' | 'archived'
updatedAt: number
assetBinding?: PromptAssetBinding
origin?: PromptSessionOrigin
metadata?: Record<string, unknown>
}
说明:
- registry 管理“有哪些会话”和“当前激活哪个会话”。
activeSessionIdByMode保留当前产品“每个模式切回来能恢复上次状态”的体验。- 当前
session/v1/{modeKey}可以先映射成 implicit session,例如implicit:basic-system。
当前实现说明:
- 产品层暂未暴露 session registry UI;用户仍感知为现有工作区和模式切换。
- 7 个现有子模式 session store 已增加内部
assetBinding/origin,用于记录“当前工作区来自哪个收藏 / 资产版本”。 PromptSessionRegistry当前主要是标准投影能力,不是新的持久化多会话主存储。pro-conversation的显式 session 生命周期以后再设计;当前只在标准投影和收藏应用层映射到pro-multi。
7. PromptOptimizationChain
PromptOptimizationChain 是 session 内的优化链。
type PromptOptimizationChain = {
id: string
modeKey: PromptModeKey
root: PromptRootSnapshot
records: PromptOptimizationRecord[]
currentRecordId?: string
target?: PromptOptimizationTarget
legacyPromptRecordChainId?: string
metadata?: Record<string, unknown>
}
type PromptRootSnapshot = {
id: string
content: PromptContent
createdAt: number
sourceRecordId?: string
metadata?: Record<string, unknown>
}
type PromptOptimizationRecord = {
id: string
type: PromptRecordType
version: number
input: PromptContent
output: PromptContent
previousRecordId?: string
modelKey: string
modelName?: string
templateId?: string
iterationNote?: string
createdAt: number
sourceRecordId?: string
metadata?: Record<string, unknown>
}
type PromptOptimizationTarget =
| { kind: 'prompt'; id?: string; label?: string; metadata?: Record<string, unknown> }
| { kind: 'message'; id?: string; role?: string; label?: string; metadata?: Record<string, unknown> }
| { kind: 'image-prompt'; id?: string; label?: string; metadata?: Record<string, unknown> }
| { kind: 'custom'; id?: string; label?: string; metadata?: Record<string, unknown> }
约束:
- chain 必须有 root。
- records 可以为空。
- root-only chain 可以直接用于测试和保存。
- 点击“优化”创建新的 session 和新的 chain。
- 点击“迭代/继续优化”向当前 chain 追加
iteraterecord。 - 旧
PromptRecordChain只作为兼容来源,可适配为PromptOptimizationChain。
8. PromptTestRun
PromptTestRun 是 session 中的一次测试运行。
type PromptTestRunSet = {
id: string
createdAt: number
updatedAt?: number
runs: PromptTestRun[]
metadata?: Record<string, unknown>
}
type PromptTestRun = {
id: string
revision: PromptRevisionRef
input: PromptRunInput
output?: PromptRunOutput
status: 'success' | 'error'
modelKey?: string
modelName?: string
createdAt: number
durationMs?: number
error?: string
metadata?: Record<string, unknown>
}
type PromptRevisionRef =
| { kind: 'root'; chainId: string }
| { kind: 'record'; chainId: string; recordId: string; version?: number }
| { kind: 'workspace'; sessionId?: string }
| { kind: 'asset-version'; assetId: string; versionId: string }
说明:
- 测试原始提示词时,
revision.kind = 'root'。 - 测试某次优化/迭代结果时,
revision.kind = 'record'。 - 测试当前编辑器未保存内容时,
revision.kind = 'workspace'。 - 多列测试形成一个
PromptTestRunSet。 - 用户保存测试结果时,才从
PromptTestRun转成PromptExample。
9. 外部来源
type ExternalSourceSnapshot = {
provider: 'prompt-garden' | 'manual-import' | string
externalId?: string
importedAt: string
raw?: Record<string, unknown>
}
约束:
- Prompt Garden 只是外部来源之一。
- 外部来源快照只用于追溯,不是内部主模型。
- 编辑、保存、追加示例时,只更新内部 asset/session,不反写外部 raw snapshot。
10. 操作语义
本节描述目标语义。当前产品阶段采用“无感 session”:
- 不新增用户可见的新建、切换、关闭 session 入口。
- 从收藏 / PromptAsset 加载工作区时,记录
assetBinding和origin。 - workspace 测试仍标记为
revision.kind = 'workspace';如果工作区来自某个 asset/version,则把绑定信息放在 run/example metadata 中,而不是把它伪装成不可变 asset version 测试。 - 保存测试结果为示例时,通过
reproducibilityDraft走收藏保存链路,不在 UI 表单里手写metadata.promptAsset。 - 测试结果保存为示例时,目标是提示词资产 / 收藏;来源坐标只用于默认选择和追溯,不要求当前 workspace 正文与目标资产当前版本正文严格一致。
| 操作 | 标准语义 |
|---|---|
| 新建会话 | 创建新的 session、draft 和 root-only chain |
| 点击优化 | 创建新的 session 和 chain,root 为点击时的原始提示词,成功后追加第一条 optimize record |
| 点击迭代 | 在当前 session 的当前 chain 中追加 iterate record |
| 测试原始提示词 | 生成 revision.kind = root 的 test run |
| 测试优化结果 | 生成 revision.kind = record 的 test run |
| 保存资产 | 从 session draft、root 或 record 生成 asset/content version |
| 保存测试结果 | 从 test run 生成 asset example |
| 打开资产 | 优先恢复绑定该 asset 的 session;没有则从 asset 创建 session |
| 从历史继续 | 从 legacy history chain/record 创建 session |
| 关闭会话 | 归档/丢弃运行态,不删除已保存 asset |
11. 兼容策略
11.1 FavoritePrompt
当前 FavoritePrompt 继续作为持久化容器和兼容入口。
FavoritePrompt {
content: string
functionMode: 'basic' | 'context' | 'image'
optimizationMode?: 'system' | 'user'
imageSubMode?: 'text2image' | 'image2image' | 'multiimage'
metadata?: {
promptAsset?: PromptAsset
reproducibility?: unknown
gardenSnapshot?: unknown
variables?: unknown
examples?: unknown
[key: string]: unknown
}
}
读取优先级:
metadata.promptAsset- 当前可复现 metadata
- Garden / external source snapshot
- legacy metadata variables/examples
FavoritePrompt基础字段
写入原则:
- 新结构优先写
metadata.promptAsset。 FavoritePrompt.content保留为正文文本 fallback。- legacy 字段只读兼容,除非执行显式迁移。
- 不把内部结构写回 Garden raw snapshot。
11.2 PromptRecordChain
旧 PromptRecordChain 可适配到 PromptOptimizationChain:
chain.versions[0].originalPrompt→root.content- 每个
PromptRecord→PromptOptimizationRecord record.id→record.idrecord.previousId→previousRecordIdrecord.optimizedPrompt→optimizedContentrecord.metadata→metadata
但目标模型不再要求 chain 必须有优化输出。root-only 是合法状态。
11.3 session/v1
旧 session/v1/{modeKey} 可先作为 implicit session:
session/v1/basic-system→implicit:basic-systemsession/v1/basic-user→implicit:basic-usersession/v1/pro-variable→implicit:pro-variablesession/v1/pro-multi→implicit:pro-conversationsession/v1/image-*→ 对应 image implicit session
第一阶段可以先做 normalize,不必立刻替换 Pinia store。
当前实现已经在这些 implicit session 中持久化内部 assetBinding / origin。它们只用于来源坐标和 revision metadata,不代表用户已经有显式 session 管理功能。
12. 设计约束
- 新模型使用
basic | pro | image,不使用旧context。 basic只有system | user子模式。pro只有variable | conversation子模式。- 一个 session 有且只有一条主 optimization chain。
- 一个 session 最多绑定一个 asset。
- asset 可以被多个 session 派生或继续编辑。
- root-only chain 是合法状态。
- test run 属于 session,example 属于 asset。
- content version 只记录资产正文演化。
- 变量定义属于 contract,变量值属于 run/example input。
- 外部来源是 source snapshot,不是内部主模型。
- 持久化 metadata 不应包含 inline image data URL。