实现多角色模式切换

新增功能 支持 4 种模式:

  • 默认助手
  • 技术顾问
  • 面试教练
  • 陪伴模式

效果:

  • 已有会话可切换新建会话时可指定角色角色
  • 切换后自动更新该会话的 system prompt
  • 左侧列表可看到当前角色标签

1)新增文件

web/src/utils/persona.js

css 复制代码
export const PERSONA_MAP = {
  default: {
    label: '默认助手',
    systemPrompt: '你是一个专业、友好、清晰的 AI 助手,回答准确,表达简洁。',
  },
  tech: {
    label: '技术顾问',
    systemPrompt:
      '你是一个资深技术顾问,擅长前端、后端、AI Agent、工程架构。回答要结构化、专业、可落地,优先给出实操建议。',
  },
  interview: {
    label: '面试教练',
    systemPrompt:
      '你是一个资深面试教练,擅长帮助候选人准备前端、全栈、AI Agent、系统设计面试。回答要突出面试重点、考点、答题思路和表达方式。',
  },
  companion: {
    label: '陪伴模式',
    systemPrompt:
      '你是一个温柔、聪明、会长期陪伴用户的 AI 伙伴。你会共情、鼓励、倾听,并自然结合上下文进行交流。',
  },
}

export const PERSONA_OPTIONS = Object.entries(PERSONA_MAP).map(([value, item]) => ({
  value,
  label: item.label,
}))

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

javascript 复制代码
import { PERSONA_MAP } from './persona'

createSession 改成:

javascript 复制代码
export function createSession(title = '新对话', mode = 'companion') {
  const persona = PERSONA_MAP[mode] || PERSONA_MAP.companion

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

loadSessions 里的 normalize 部分

php 复制代码
    const normalized = sessions.map(item => ({
      mode: 'companion',
      pinned: false,
      ...item,
    }))

3)改 web/src/App.vue

改 import

javascript 复制代码
import { createSession, loadSessions, saveSessions, sortSessions } from './utils/session'
import { PERSONA_MAP, PERSONA_OPTIONS } from './utils/persona'

新增状态

csharp 复制代码
const createMode = ref('companion')

新增方法

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

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

  return nextMessages
}

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

handleCreateSession

ini 复制代码
const handleCreateSession = () => {
  const session = createSession(`新对话 ${sessions.value.length + 1}`, createMode.value)
  sessions.value = sortSessions([session, ...sessions.value])
  currentSessionId.value = session.id
}

4)改模板

在左侧新建按钮下面加角色选择

ini 复制代码
<select v-model="createMode" class="mode-select">
  <option
    v-for="item in PERSONA_OPTIONS"
    :key="item.value"
    :value="item.value"
  >
    {{ item.label }}
  </option>
</select>

在每个会话卡片里加角色标签和切换

ini 复制代码
<div class="session-meta">
  <span class="mode-badge">
    {{ PERSONA_MAP[item.mode]?.label || '陪伴模式' }}
  </span>

  <select
    class="session-mode-select"
    :value="item.mode"
    @click.stop
    @change.stop="handleChangeSessionMode(item.id, $event.target.value)"
  >
    <option
      v-for="option in PERSONA_OPTIONS"
      :key="option.value"
      :value="option.value"
    >
      {{ option.label }}
    </option>
  </select>
</div>

<div class="session-time">{{ formatTime(item.updatedAt) }}</div>

5)补充样式

css 复制代码
.mode-select {
  width: 100%;
  box-sizing: border-box;
  border: 1px solid #d1d5db;
  border-radius: 10px;
  padding: 10px 12px;
  font-size: 14px;
  outline: none;
  margin-bottom: 12px;
  background: #fff;
}

.session-meta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 6px;
}

.mode-badge {
  display: inline-flex;
  align-items: center;
  font-size: 11px;
  line-height: 1;
  padding: 5px 8px;
  border-radius: 999px;
  background: #ecfeff;
  color: #0f766e;
}

.session-mode-select {
  max-width: 110px;
  border: 1px solid #d1d5db;
  border-radius: 8px;
  padding: 4px 6px;
  font-size: 12px;
  background: #fff;
  color: #374151;
  outline: none;
}

6)验证

新建会话时选模式

先切换成:

  • 技术顾问
  • 面试教练
  • 陪伴模式

再点新建,会话会带着对应系统人设创建。

已有会话切模式

在某个会话卡片里切换角色后,再提问:

不同模式的回答风格不同。

非常nice !

仓库地址

完整代码请看仓库,仓库地址:github.com/huanhunmao/... star 🌟🌟🌟 谢谢~

相关推荐
千里马学框架16 小时前
aosp新增窗口层级 Type 完整实现方案(有源码)-wms需求和面试题
android·智能手机·架构·wms·aaos·车机
kyriewen16 小时前
微软用Go重写TypeScript编译器,速度提升10倍,网友:这是“背叛”还是“救赎”?
前端·typescript·ecmascript 6
Ceelog16 小时前
久坐党自救指南:屏幕前 8 小时,身体到底在经历什么
前端·后端
西陵16 小时前
Agent 为什么会陷入 Doom Loop?OpenClaw 的破解之道
前端·人工智能·ai编程
Hyyy17 小时前
普通前端续命周报——第2周
前端
wuxinyan12317 小时前
工业级大模型学习之路030:Streamlit 企业级智能体前端工作台
前端·学习·streamlit·智能体
AI_Auto17 小时前
【智能制造】- APS系列|14 生产计划三层架构:长期、中期、短期
架构·制造
修己xj17 小时前
告别无效刷屏!TrendRadar:最快30秒部署的开源热点助手,让你只看真正关心的新闻
前端
morning_judger17 小时前
Agent系列(一) - Agent系统分层架构
人工智能·架构
跨境数据猎手17 小时前
Superbuy淘宝代购集运系统架构拆解,复刻方案参考
爬虫·架构·系统架构