docs/workspace/prompt-data-standardization/01-提示词数据格式标准化设计.md
本设计建立项目内部的通用提示词模型,用来统一工作区、收藏、优化历史、测试结果、外部导入、图像提示词等场景。
目标不是先改某一个收藏字段,而是先定义稳定的领域语言:
basic / pro / image 三类模式如何用同一套结构表达。FavoritePrompt、旧 PromptRecordChain、旧 session/v1/* 如何兼容到新模型。本文先描述标准领域模型和目标语义;当前已经落地的实现边界见 2.3,不要求一次性替换现有存储和 UI。
PromptAsset
├─ PromptContentVersion[] // 长期资产正文版本
└─ PromptExample[] // 长期可复现示例
PromptSession
├─ assetBinding? // 最多绑定一个资产
├─ draft // 当前工作区草稿
├─ PromptOptimizationChain // 有且只有一条主优化链
└─ PromptTestRunSet[] // 会话内测试运行
PromptOptimizationChain
├─ root // 原始提示词
└─ records[] // 优化/迭代输出,可为空
PromptOptimizationChain。PromptAsset。PromptExample。截至 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。basedOnVersionId 和来源坐标只用于追溯,不要求当前 workspace 正文与目标资产当前正文严格一致。metadata.promptAsset;显式更新正文时,正文变化会创建新的 content version;只追加示例时不会修改正文版本链。pro-conversation 在标准层使用 messages;当前 UI 仍复用既有 pro-multi store key,并已支持把收藏中的 messages 恢复为多消息会话。文本拼接只作为兼容降级。metadata.promptAsset、当前 reproducibility、Garden snapshot 和 legacy 结构中的图片引用。仍未落地的部分:
新模型只使用以下模式:
type PromptModeKey =
| 'basic-system'
| 'basic-user'
| 'pro-variable'
| 'pro-conversation'
| 'image-text2image'
| 'image-image2image'
| 'image-multiimage'
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[]
}
| 历史结构 | 标准结构 |
|---|---|
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 中,新领域模型不再使用它。
type PromptContent =
| {
kind: 'text'
text: string
}
| {
kind: 'messages'
messages: ConversationMessage[]
}
| {
kind: 'image-prompt'
text: string
}
说明:
text 或 image-prompt。pro-conversation 使用 messages,避免把多消息会话压成单字符串。FavoritePrompt.content 映射为 PromptContent.kind = 'text'。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>
}
约束:
defaultValue 是模板级默认值,不等于某次运行时用户填入的变量值。PromptImageRef 引用。type PromptImageRef =
| { kind: 'url'; url: string }
| { kind: 'asset'; assetId: string }
持久化结构优先使用 kind: 'asset'。kind: 'url' 只作为外部来源或兜底引用。metadata 中不应长期保存 inline base64 / data URL。
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>
}
约束:
versions 只追踪资产正文演化。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>
}
约束:
basedOnVersionId 是兼容当前模型的来源 / revision 线索,不表示示例必须绑定到当前资产正文版本,也不能作为追加示例前的正文一致性门禁。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 为空表示未保存草稿。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>
}
说明:
activeSessionIdByMode 保留当前产品“每个模式切回来能恢复上次状态”的体验。session/v1/{modeKey} 可以先映射成 implicit session,例如 implicit:basic-system。当前实现说明:
assetBinding / origin,用于记录“当前工作区来自哪个收藏 / 资产版本”。PromptSessionRegistry 当前主要是标准投影能力,不是新的持久化多会话主存储。pro-conversation 的显式 session 生命周期以后再设计;当前只在标准投影和收藏应用层映射到 pro-multi。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> }
约束:
iterate record。PromptRecordChain 只作为兼容来源,可适配为 PromptOptimizationChain。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。type ExternalSourceSnapshot = {
provider: 'prompt-garden' | 'manual-import' | string
externalId?: string
importedAt: string
raw?: Record<string, unknown>
}
约束:
本节描述目标语义。当前产品阶段采用“无感 session”:
assetBinding 和 origin。revision.kind = 'workspace';如果工作区来自某个 asset/version,则把绑定信息放在 run/example metadata 中,而不是把它伪装成不可变 asset version 测试。reproducibilityDraft 走收藏保存链路,不在 UI 表单里手写 metadata.promptAsset。| 操作 | 标准语义 |
|---|---|
| 新建会话 | 创建新的 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 |
当前 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.promptAssetFavoritePrompt 基础字段写入原则:
metadata.promptAsset。FavoritePrompt.content 保留为正文文本 fallback。旧 PromptRecordChain 可适配到 PromptOptimizationChain:
chain.versions[0].originalPrompt → root.contentPromptRecord → PromptOptimizationRecordrecord.id → record.idrecord.previousId → previousRecordIdrecord.optimizedPrompt → optimizedContentrecord.metadata → metadata但目标模型不再要求 chain 必须有优化输出。root-only 是合法状态。
旧 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 管理功能。
basic | pro | image,不使用旧 context。basic 只有 system | user 子模式。pro 只有 variable | conversation 子模式。