add chat avatar icon for different roles
@ -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,
|
||||||
|
@ -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 {
|
||||||
|
if v, ok := s.Config.ChatRoles[k]; ok {
|
||||||
|
roles = append(roles, struct {
|
||||||
Key string `json:"key"`
|
Key string `json:"key"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
}{
|
}{
|
||||||
Key: v.Key,
|
Key: v.Key,
|
||||||
Name: v.Name,
|
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})
|
||||||
|
@ -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,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
web/public/images/avatar/artist.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
web/public/images/avatar/english_trainer.jpg
Normal file
After Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 3.5 KiB After Width: | Height: | Size: 3.5 KiB |
BIN
web/public/images/avatar/luxun.jpg
Normal file
After Width: | Height: | Size: 27 KiB |
BIN
web/public/images/avatar/philosopher.jpg
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
web/public/images/avatar/programmer.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
web/public/images/avatar/seller.jpg
Normal file
After Width: | Height: | Size: 16 KiB |
BIN
web/public/images/avatar/teacher.jpg
Normal file
After Width: | Height: | Size: 40 KiB |
Before Width: | Height: | Size: 24 KiB After Width: | Height: | Size: 24 KiB |
7
web/src/assets/css/bootstrap.min.css
vendored
@ -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;
|
||||||
|
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|