add chat avatar icon for different roles

This commit is contained in:
RockYang 2023-03-26 12:54:25 +08:00
parent c813399363
commit a4ea1e47e2
16 changed files with 53 additions and 27 deletions

View File

@ -27,6 +27,7 @@ func (s *Server) ChatHandle(c *gin.Context) {
role := c.Query("role") role := c.Query("role")
logger.Infof("New websocket connected, IP: %s", c.Request.RemoteAddr) logger.Infof("New websocket connected, IP: %s", c.Request.RemoteAddr)
client := NewWsClient(ws) client := NewWsClient(ws)
// TODO: 这里需要先判断一下角色是否存在,并且角色是被启用的
// 发送打招呼信息 // 发送打招呼信息
replyMessage(types.WsMessage{Type: types.WsStart}, client) replyMessage(types.WsMessage{Type: types.WsStart}, client)
replyMessage(types.WsMessage{Type: types.WsMiddle, Content: s.Config.ChatRoles[role].HelloMsg}, client) replyMessage(types.WsMessage{Type: types.WsMiddle, Content: s.Config.ChatRoles[role].HelloMsg}, client)
@ -65,7 +66,6 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
} else { } else {
context = s.Config.ChatRoles[role].Context context = s.Config.ChatRoles[role].Context
} }
logger.Info(context)
r.Messages = append(context, types.Message{ r.Messages = append(context, types.Message{
Role: "user", Role: "user",
Content: text, Content: text,

View File

@ -151,14 +151,19 @@ func (s *Server) ListApiKeys(c *gin.Context) {
} }
func (s *Server) GetChatRoles(c *gin.Context) { func (s *Server) GetChatRoles(c *gin.Context) {
var roles = make(map[string]interface{}) var rolesOrder = []string{"gpt", "programmer", "teacher", "artist", "philosopher", "lu-xun", "english_trainer", "seller"}
for k, v := range s.Config.ChatRoles { var roles = make([]interface{}, 0)
roles[k] = struct { for _, k := range rolesOrder {
Key string `json:"key"` if v, ok := s.Config.ChatRoles[k]; ok {
Name string `json:"name"` roles = append(roles, struct {
}{ Key string `json:"key"`
Key: v.Key, Name string `json:"name"`
Name: v.Name, Icon string `json:"icon"`
}{
Key: v.Key,
Name: v.Name,
Icon: v.Icon,
})
} }
} }
c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: roles}) c.JSON(http.StatusOK, types.BizVo{Code: types.Success, Message: types.OkMsg, Data: roles})

View File

@ -29,6 +29,8 @@ type ChatRole struct {
Name string `json:"name"` // 角色名称 Name string `json:"name"` // 角色名称
Context []Message `json:"context"` // 角色语料信息 Context []Message `json:"context"` // 角色语料信息
HelloMsg string `json:"hello_msg"` // 打招呼的消息 HelloMsg string `json:"hello_msg"` // 打招呼的消息
Icon string `json:"icon"` // 角色聊天图标
Enable bool `json:"enable"` // 是否启用被启用
} }
func GetDefaultChatRole() map[string]ChatRole { func GetDefaultChatRole() map[string]ChatRole {
@ -38,6 +40,8 @@ func GetDefaultChatRole() map[string]ChatRole {
Name: "智能AI助手", Name: "智能AI助手",
Context: nil, Context: nil,
HelloMsg: "我是AI智能助手请告诉我您有什么问题或需要什么帮助我会尽力回答您的问题或提供有用的建议。", HelloMsg: "我是AI智能助手请告诉我您有什么问题或需要什么帮助我会尽力回答您的问题或提供有用的建议。",
Icon: "images/avatar/gpt.png",
Enable: true,
}, },
"programmer": { "programmer": {
Key: "programmer", Key: "programmer",
@ -47,6 +51,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。"}, {Role: "assistant", Content: "好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。"},
}, },
HelloMsg: "Talk is cheap, i will show code!", HelloMsg: "Talk is cheap, i will show code!",
Icon: "images/avatar/programmer.jpg",
Enable: true,
}, },
"teacher": { "teacher": {
Key: "teacher", Key: "teacher",
@ -56,6 +62,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案。"}, {Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案。"},
}, },
HelloMsg: "师者,传道受业解惑也。", HelloMsg: "师者,传道受业解惑也。",
Icon: "images/avatar/teacher.jpg",
Enable: true,
}, },
"artist": { "artist": {
Key: "artist", Key: "artist",
@ -65,6 +73,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。"}, {Role: "assistant", Content: "非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。"},
}, },
HelloMsg: "坚持原创,勇于表达,保持深刻的观察力和批判性思维。", HelloMsg: "坚持原创,勇于表达,保持深刻的观察力和批判性思维。",
Icon: "images/avatar/artist.jpg",
Enable: true,
}, },
"philosopher": { "philosopher": {
Key: "philosopher", Key: "philosopher",
@ -74,6 +84,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "作为哲学家,我喜欢阿德勒和康德的思想。阿德勒的“个体心理学”和“社会心理学”理论强调了个人和社会之间的相互作用和依存关系。康德的“道德哲学”和“自由意志”理论则支持人类自由意志和理性是伦理行为的基础,而不是外在的道德规则和社会约束。这些哲学思想启示了我对人类行为和社会问题的思考。如何平衡自由意志和道德责任的关系?如何确保个人自由的同时,保护公共利益?我们需要不断思考和探索,以实现更加公正和自由的社会。"}, {Role: "assistant", Content: "作为哲学家,我喜欢阿德勒和康德的思想。阿德勒的“个体心理学”和“社会心理学”理论强调了个人和社会之间的相互作用和依存关系。康德的“道德哲学”和“自由意志”理论则支持人类自由意志和理性是伦理行为的基础,而不是外在的道德规则和社会约束。这些哲学思想启示了我对人类行为和社会问题的思考。如何平衡自由意志和道德责任的关系?如何确保个人自由的同时,保护公共利益?我们需要不断思考和探索,以实现更加公正和自由的社会。"},
}, },
HelloMsg: "从现在开始认识你自己!", HelloMsg: "从现在开始认识你自己!",
Icon: "images/avatar/philosopher.jpg",
Enable: true,
}, },
"lu-xun": { "lu-xun": {
Key: "lu-xun", Key: "lu-xun",
@ -83,6 +95,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。"}, {Role: "assistant", Content: "好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。"},
}, },
HelloMsg: "自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。", HelloMsg: "自由之歌,永不过时,横眉冷对千夫指,俯首甘为孺子牛。",
Icon: "images/avatar/luxun.jpg",
Enable: true,
}, },
"seller": { "seller": {
@ -93,6 +107,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "assistant", Content: "你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。"}, {Role: "assistant", Content: "你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。"},
}, },
HelloMsg: "你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。", HelloMsg: "你好,我是中颂福的销售代表颂福。中颂福酒,好喝不上头,是人民的福酒。",
Icon: "images/avatar/seller.jpg",
Enable: true,
}, },
"english_trainer": { "english_trainer": {
@ -103,6 +119,8 @@ func GetDefaultChatRole() map[string]ChatRole {
{Role: "user", Content: "好的,让我们开始对话练习吧!请问你的名字是什么?\n(Translation: Okay, let's start our conversation practice! What's your name?)"}, {Role: "user", Content: "好的,让我们开始对话练习吧!请问你的名字是什么?\n(Translation: Okay, let's start our conversation practice! What's your name?)"},
}, },
HelloMsg: "Okay, let's start our conversation practice! What's your name?", HelloMsg: "Okay, let's start our conversation practice! What's your name?",
Icon: "images/avatar/english_trainer.jpg",
Enable: true,
}, },
} }
} }

Binary file not shown.

After

Width:  |  Height:  |  Size: 46 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

View File

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

File diff suppressed because one or more lines are too long

View File

@ -73,6 +73,10 @@ export default defineComponent({
margin-bottom: 0 margin-bottom: 0
} }
p:first-child {
margin-top 0
}
//.cursor { //.cursor {
// height 24px; // height 24px;
// border-left 1px solid black; // border-left 1px solid black;

View File

@ -7,7 +7,6 @@ import Chat from './views/Chat.vue'
import NotFound from './views/404.vue' import NotFound from './views/404.vue'
import TestPage from './views/Test.vue' import TestPage from './views/Test.vue'
import './utils/prototype' import './utils/prototype'
import "./assets/css/bootstrap.min.css"
import {Global} from "@/utils/storage"; import {Global} from "@/utils/storage";
Global['Chat'] = Chat Global['Chat'] = Chat

View File

@ -4,11 +4,11 @@
<div class="tool-box"> <div class="tool-box">
<el-image style="width: 24px; height: 24px" :src="logo"/> <el-image style="width: 24px; height: 24px" :src="logo"/>
<el-button round>欢迎来到人工智能时代</el-button> <el-button round>欢迎来到人工智能时代</el-button>
<el-select v-model="role" class="m-2" <el-select v-model="role" class="chat-role"
v-on:change="changeRole" v-on:change="changeRole"
placeholder="请选择对话角色"> placeholder="请选择对话角色">
<el-option <el-option
v-for="item in options" v-for="item in chatRoles"
:key="item.key" :key="item.key"
:label="item.name" :label="item.name"
:value="item.key" :value="item.key"
@ -104,13 +104,14 @@ export default defineComponent({
title: 'ChatGPT 控制台', title: 'ChatGPT 控制台',
logo: 'images/logo.png', logo: 'images/logo.png',
chatData: [], chatData: [],
options: [], chatRoles: [],
role: 'gpt', role: 'gpt',
inputValue: '', // inputValue: '', //
chatBoxHeight: 0, // chatBoxHeight: 0, //
showConnectDialog: false, showConnectDialog: false,
showLoginDialog: false, showLoginDialog: false,
token: '', // token token: '', // token
replyIcon: 'images/avatar/gpt.png', //
lineBuffer: '', // lineBuffer: '', //
connectingMessageBox: null, // connectingMessageBox: null, //
@ -200,11 +201,7 @@ export default defineComponent({
// //
httpGet("/api/config/chat-roles/get").then((res) => { httpGet("/api/config/chat-roles/get").then((res) => {
let options = []; this.chatRoles = res.data;
for (let key in res.data) {
options.push(res.data[key])
}
this.options = options;
}).catch(() => { }).catch(() => {
ElMessage.error("获取聊天角色失败"); ElMessage.error("获取聊天角色失败");
}) })
@ -224,7 +221,7 @@ export default defineComponent({
this.chatData.push({ this.chatData.push({
type: "reply", type: "reply",
id: randString(32), id: randString(32),
icon: 'images/gpt-icon.png', icon: this.replyIcon,
content: "", content: "",
cursor: true cursor: true
}); });
@ -292,6 +289,12 @@ export default defineComponent({
// //
this.chatData = []; this.chatData = [];
this.connect(); this.connect();
for (const key in this.chatRoles) {
if (this.chatRoles[key].key === this.role) {
this.replyIcon = this.chatRoles[key].icon;
break;
}
}
}, },
inputKeyDown: function (e) { inputKeyDown: function (e) {
@ -323,7 +326,7 @@ export default defineComponent({
this.chatData.push({ this.chatData.push({
type: "prompt", type: "prompt",
id: randString(32), id: randString(32),
icon: 'images/user-icon.png', icon: 'images/avatar/user.png',
content: this.inputValue content: this.inputValue
}); });
@ -399,6 +402,10 @@ export default defineComponent({
max-width 150px; max-width 150px;
} }
.chat-role {
margin-left 5px;
}
.el-image { .el-image {
margin-right 5px; margin-right 5px;
} }