Prompt Playground(实现提示词工作台)

本次功能

Prompt Playground(提示词工作台)

效果:

  • 每个会话都能单独编辑 system prompt
  • 可以恢复到当前角色的默认 prompt
  • 修改后立即影响后续对话
  • 更像真正的 AI 产品调试台

1)改 web/src/utils/session.js

createSession

yaml 复制代码
  return {
    id: crypto.randomUUID(),
    title,
    mode,
    customPrompt: persona.systemPrompt,
    pinned: false,
    createdAt: Date.now(),
    updatedAt: Date.now(),
    messages: [
      {
        role: 'system',
        content: persona.systemPrompt,
      },
      {
        role: 'assistant',
        content: '你好,我已经准备好了。你今天想聊什么?',
      },
    ],
  }

loadSessions 里的 normalize

ini 复制代码
    const normalized = sessions.map(item => {
      const mode = item.mode || 'companion'
      const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion

      return {
        mode,
        customPrompt: item.customPrompt || item.messages?.find(m => m.role === 'system')?.content || persona.systemPrompt,
        pinned: false,
        ...item,
      }
    })

2)改 web/src/App.vue

新增状态

csharp 复制代码
const promptDraft = ref('')

新增计算属性

javascript 复制代码
const currentSystemPrompt = computed(() => {
  return currentSession.value?.customPrompt || ''
})

新增监听

ini 复制代码
watch(
  currentSystemPrompt,
  newVal => {
    promptDraft.value = newVal || ''
  },
  { immediate: true }
)

resetSystemMessageByMode

ini 复制代码
const resetSystemMessageByMode = (messages = [], mode = 'companion', prompt) => {
  const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion
  const finalPrompt = prompt || persona.systemPrompt
  const nextMessages = [...messages]

  const systemIndex = nextMessages.findIndex(item => item.role === 'system')
  if (systemIndex > -1) {
    nextMessages[systemIndex] = {
      ...nextMessages[systemIndex],
      content: finalPrompt,
    }
  } else {
    nextMessages.unshift({
      role: 'system',
      content: finalPrompt,
    })
  }

  return nextMessages
}

handleChangeSessionMode

ini 复制代码
const handleChangeSessionMode = (id, mode) => {
  const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion

  sessions.value = sortSessions(
    sessions.value.map(item =>
      item.id === id
        ? {
            ...item,
            mode,
            customPrompt: persona.systemPrompt,
            updatedAt: Date.now(),
            messages: resetSystemMessageByMode(item.messages, mode, persona.systemPrompt),
          }
        : item
    )
  )
}

新增 3 个方法

ini 复制代码
const handleSavePrompt = () => {
  if (!currentSession.value) return

  const nextPrompt = promptDraft.value.trim()
  if (!nextPrompt) return

  sessions.value = sortSessions(
    sessions.value.map(item =>
      item.id === currentSessionId.value
        ? {
            ...item,
            customPrompt: nextPrompt,
            updatedAt: Date.now(),
            messages: resetSystemMessageByMode(item.messages, item.mode, nextPrompt),
          }
        : item
    )
  )
}

const handleResetPrompt = () => {
  if (!currentSession.value) return

  const persona = PERSONA_MAP[currentSession.value.mode] || PERSONA_MAP.companion
  promptDraft.value = persona.systemPrompt

  sessions.value = sortSessions(
    sessions.value.map(item =>
      item.id === currentSessionId.value
        ? {
            ...item,
            customPrompt: persona.systemPrompt,
            updatedAt: Date.now(),
            messages: resetSystemMessageByMode(item.messages, item.mode, persona.systemPrompt),
          }
        : item
    )
  )
}

const handleUsePromptTemplate = template => {
  promptDraft.value = template
}

3)改模板

添加

ini 复制代码
<div class="prompt-panel">
  <div class="prompt-panel-header">
    <div class="prompt-panel-title">Prompt Playground</div>
    <div class="prompt-panel-actions">
      <button class="prompt-btn secondary" @click="handleResetPrompt">恢复默认</button>
      <button class="prompt-btn" @click="handleSavePrompt">保存 Prompt</button>
    </div>
  </div>

  <textarea
    v-model="promptDraft"
    class="prompt-textarea"
    placeholder="编辑当前会话的 system prompt"
  />

  <div class="prompt-template-list">
    <span
      class="prompt-template-tag"
      @click="handleUsePromptTemplate('你是一个专业、友好、清晰的 AI 助手,回答准确,表达简洁。')"
    >
      通用助手
    </span>
    <span
      class="prompt-template-tag"
      @click="handleUsePromptTemplate('你是一个资深技术顾问,回答时要结构化、专业、可执行,优先给出步骤、代码和避坑建议。')"
    >
      技术顾问模板
    </span>
    <span
      class="prompt-template-tag"
      @click="handleUsePromptTemplate('你是一个资深面试教练,请从面试官视角给出高质量回答,突出考点、答题框架和表达建议。')"
    >
      面试教练模板
    </span>
    <span
      class="prompt-template-tag"
      @click="handleUsePromptTemplate('你是一个温柔、稳定、善于倾听和鼓励的陪伴型 AI,回答自然、真诚、有情绪价值。')"
    >
      陪伴模板
    </span>
  </div>
</div>

4)补样式

css 复制代码
.prompt-panel {
  margin-bottom: 16px;
  padding: 16px;
  border: 1px solid #e5e7eb;
  border-radius: 12px;
  background: #fafafa;
}

.prompt-panel-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 12px;
}

.prompt-panel-title {
  font-size: 16px;
  font-weight: 600;
  color: #111827;
}

.prompt-panel-actions {
  display: flex;
  align-items: center;
  gap: 8px;
}

.prompt-btn {
  border: none;
  border-radius: 10px;
  background: #111827;
  color: #fff;
  padding: 8px 12px;
  font-size: 12px;
  cursor: pointer;
}

.prompt-btn.secondary {
  background: #6b7280;
}

.prompt-textarea {
  width: 100%;
  min-height: 96px;
  resize: vertical;
  box-sizing: border-box;
  border: 1px solid #d1d5db;
  border-radius: 10px;
  padding: 12px;
  font-size: 14px;
  line-height: 1.6;
  outline: none;
  background: #fff;
  margin-bottom: 12px;
}

.prompt-template-list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}

.prompt-template-tag {
  display: inline-flex;
  align-items: center;
  padding: 6px 10px;
  border-radius: 999px;
  background: #eef2ff;
  color: #4338ca;
  font-size: 12px;
  cursor: pointer;
}

.prompt-template-tag:hover {
  background: #e0e7ff;
}

5)验证

测试 1:自定义 Prompt

把 prompt 改成:

复制代码
你是一个只用项目符号回答的技术顾问,回答必须简洁,每次最多 5 条。

然后问:

复制代码
如何准备 AI Agent 岗位面试

测试 2:恢复默认

点"恢复默认",再问同一个问题,回答风格应该回到当前角色默认风格。

测试 3:模板切换

点不同模板标签,再保存,马上提问,回答应该切换风格。

nice !

相关推荐
医学AI望远镜3 小时前
公开数据集整理:心脏CMR分割、心肌瘢痕、肋骨骨折、骨关节炎等
人工智能·数据集·医学图像分割
懂AI的老郑3 小时前
智能体演变路径预测:AI未来行为的核心解码
人工智能
wayz113 小时前
Day 7:第一周复习与模型综合比较
人工智能·算法·机器学习·量化交易
小超同学你好3 小时前
Transformer 27. Vision Transformer(ViT):把图像当作「词序列」的编码器
人工智能·深度学习·transformer
登山人在路上3 小时前
RAGAS 中的已知偏差详解
人工智能·全文检索·ai编程
空白诗3 小时前
ModelEngine Nexent:一句话创建智能体的全新范式
人工智能·nexent
qq_12084093713 小时前
Three.js 工程向:相机控制与交互手感调优(OrbitControls)
前端·javascript·orbitcontrols
stark张宇3 小时前
Go 语言实现安全的分享链接:AES 加密 + SHA256 签名 + 过期防重放
后端·go
疯狂的魔鬼3 小时前
从 5 个 Hooks 到注册表模式:Vue 3 复杂详情页的架构演进与原则沉淀
前端·架构
元直数字电路验证3 小时前
AI入门体系化知识框架
人工智能