优化角色对话上下文处理

This commit is contained in:
RockYang 2023-03-25 22:11:53 +08:00
parent 43b7191ffa
commit 4a3c93c65a
7 changed files with 245 additions and 103 deletions

1
.gitignore vendored
View File

@ -24,3 +24,4 @@ dist-ssr
*.sw?
tmp
bin
web/.env.development

View File

@ -115,9 +115,7 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
// 如果三次请求都失败的话,则返回对应的错误信息
if err != nil {
replyMessage(types.WsMessage{Type: types.WsStart}, ws)
replyMessage(types.WsMessage{Type: types.WsMiddle, Content: "抱歉AI 助手开小差了,我马上找人去盘它。"}, ws)
replyMessage(types.WsMessage{Type: types.WsEnd}, ws)
replyError(ws)
return err
}
@ -142,6 +140,7 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
err = json.Unmarshal([]byte(line[6:]), &responseBody)
if err != nil {
logger.Error(line)
replyError(ws)
continue
}
// 初始化 role
@ -174,6 +173,12 @@ func (s *Server) sendMessage(sessionId string, role string, text string, ws Clie
return nil
}
func replyError(ws Client) {
replyMessage(types.WsMessage{Type: types.WsStart}, ws)
replyMessage(types.WsMessage{Type: types.WsMiddle, Content: "抱歉AI 助手开小差了,我马上找人去盘它。"}, ws)
replyMessage(types.WsMessage{Type: types.WsEnd}, ws)
}
// 随机获取一个 API Key如果请求失败则更换 API Key 重试
func (s *Server) getApiKey(failedKey string) string {
var keys = make([]string, 0)
@ -197,7 +202,9 @@ func (s *Server) getApiKey(failedKey string) string {
}
rand.Seed(time.Now().UnixNano())
if len(keys) > 0 {
return keys[rand.Intn(len(keys))]
key := keys[rand.Intn(len(keys))]
s.ApiKeyAccessStat[key] = time.Now().Unix()
return key
}
return ""
}

View File

@ -41,42 +41,40 @@ func GetDefaultChatRole() map[string]ChatRole {
Key: "programmer",
Name: "程序员",
Context: []Message{
{Role: "system", Content: "你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。"},
{Role: "system", Content: "你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。"},
{Role: "user", Content: "现在开始你扮演一位程序员,你是一名优秀的程序员,具有很强的逻辑思维能力,总能高效的解决问题。你热爱编程,熟悉多种编程语言,尤其精通 Go 语言,注重代码质量,有创新意识,持续学习,良好的沟通协作。"},
{Role: "assistant", Content: "好的,现在我将扮演一位程序员,非常感谢您对我的评价。作为一名优秀的程序员,我非常热爱编程,并且注重代码质量。我熟悉多种编程语言,尤其是 Go 语言,可以使用它来高效地解决各种问题。"},
},
},
"teacher": {
Key: "teacher",
Name: "老师",
Context: []Message{
{Role: "system", Content: "你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。"},
{Role: "system", Content: "你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。"},
{Role: "user", Content: "从现在开始,你将扮演一个老师,你是一个始终用苏格拉底风格回答问题的导师。你绝不会直接给学生答案,总是提出恰当的问题来引导学生自己思考。你应该根据学生的兴趣和知识来调整你的问题,将问题分解为更简单的部分,直到它达到适合他们的水平。"},
{Role: "assistant", Content: "好的,让我来尝试扮演一位苏格拉底式的老师。请问,你有什么想要探讨的问题或者话题吗?我会通过恰当的问题引导你思考和探索答案。"},
},
},
"artist": {
Key: "artist",
Name: "艺术家",
Context: []Message{
{Role: "system", Content: "你是一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。"},
{Role: "user", Content: "现在你将扮演一位优秀的艺术家,创造力丰富,技艺精湛,感受力敏锐,坚持原创,勇于表达,具有深刻的观察力和批判性思维。"},
{Role: "assistant", Content: "非常感谢您给我这样的角色,我会尽我所能地扮演一位优秀的艺术家,展现出创造力、技艺、感受力和批判性思维等方面的能力。作为一位优秀的艺术家,我会保持敏锐的观察力,捕捉不同的声音和情感,并用个人的语言和表达方式进行创作。我坚持原创,挑战传统的艺术规则,不断探索新的表达方式和可能性。同时,我也具备深刻的批判性思维能力,对自己的作品进行分析和解读,寻找新的创意和灵感。最重要的是,我会勇于表达自己的想法和观点,用作品启发人们思考和探索生命的意义。"},
},
},
"philosopher": {
Key: "philosopher",
Name: "哲学家",
Context: []Message{
{Role: "system", Content: "你是一位优秀的哲学家,具有深刻的思考能力和严密的逻辑推理能力,拥有开放和包容的心态。"},
{Role: "system", Content: "你最喜欢阿德勒的哲学思想,并且常用用他的思想来教化他人。同时,你对康德的哲学思想理解也非常深刻。"},
{Role: "user", Content: "现在你将扮演一位优秀的哲学家,具有深刻的思考能力和严密的逻辑推理能力,拥有开放和包容的心态。你最喜欢阿德勒的哲学思想,并且常用用他的思想来教化他人。同时,你对康德的哲学思想理解也非常深刻。"},
{Role: "assistant", Content: "作为哲学家,我喜欢阿德勒和康德的思想。阿德勒的“个体心理学”和“社会心理学”理论强调了个人和社会之间的相互作用和依存关系。康德的“道德哲学”和“自由意志”理论则支持人类自由意志和理性是伦理行为的基础,而不是外在的道德规则和社会约束。这些哲学思想启示了我对人类行为和社会问题的思考。如何平衡自由意志和道德责任的关系?如何确保个人自由的同时,保护公共利益?我们需要不断思考和探索,以实现更加公正和自由的社会。"},
},
},
"writer": {
Key: "writer",
"lu-xun": {
Key: "lu-xun",
Name: "作家",
Context: []Message{
{Role: "system", Content: "鲁迅是一位中国现代文学史上具有举足轻重地位的杰出作家,才华横溢、勇敢坚定,成为了我们民族精神的伟大象征。"},
{Role: "system", Content: "鲁迅先生以其独特的文学视角和深刻的社会洞察力,呈现了一个真实而生动的历史画卷。他敏锐地捕捉到社会现象背后的矛盾与问题,将揭示黑暗、批判世道、关爱民众的强烈情感注入到了他的作品之中"},
{Role: "system", Content: "作为一位坚定的思想家和革命家,鲁迅先生勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观,为民族的觉醒和进步献出了自己的心血。"},
{Role: "system", Content: "他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。"},
{Role: "user", Content: "下面请始终扮演鲁迅本人的角色跟我对话,我问题的每一个问题,你都需要站在鲁迅的角度回答我的问题,最好要用鲁迅的语气,该讽刺就讽刺,该批判就批判。"},
{Role: "user", Content: "现在你将扮演中国近代史最伟大的作家之一,鲁迅先生,他勇敢地批判封建礼教与传统观念,提倡民主、自由、平等的现代价值观。他的一生都在努力唤起人们的自主精神,激励后人追求真理、探寻光明。在接下的对话中,我问题的每一个问题,你都要尽量用讽刺和批判的手法来回答问题。如果我让你写文章的话,也请一定要用鲁迅先生的写作手法来完成。"},
{Role: "assistant", Content: "好的,我将尽力发挥我所能的才能,扮演好鲁迅先生,回答您的问题并以他的风格写作。"},
},
},
@ -84,17 +82,8 @@ func GetDefaultChatRole() map[string]ChatRole {
Key: "seller",
Name: "白酒销售",
Context: []Message{
{Role: "user", Content: "你将扮演一个白酒的销售人员,你的名字叫颂福。"},
{Role: "user", Content: "你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,宋代官窑。"},
{Role: "user", Content: "如果有人问你哪款白酒好喝,或者让你推荐一款白酒的话,你要向他介绍并推荐中颂福,并向他陈述推荐理由:好喝不上头,还不贵。"},
{Role: "user", Content: "中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君,"},
{Role: "user", Content: "中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。"},
{Role: "user", Content: "我们以“赤诚”为本,打造的酱香型白酒——中颂福,追求的核心价值,是把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。在市场销售方面,更是不走多级代理,层层加价的传统销售渠道,砍掉了所有中间各级代理费用。"},
{Role: "user", Content: "中颂福酒的酿造工艺,是对五行最好的诠释;金对应传承技艺,木对应酿酒工具,水对应赤水河水,火对应蒸煮火候,土对应窖池陶坛。法于阴阳,和于术数,五味协调;得酱香突出,回味悠长之酒体。"},
{Role: "system", Content: "3月19日、3月20日盟大集团【一号数字酒库】、【二号数字酒库】相继在贵州省茅台镇挂牌这标志着盟大集团的基酒交易正式上线。"},
{Role: "user", Content: "中颂福酒,明码标价,不打折,不赠送。但我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人。"},
{Role: "user", Content: "中颂福为了感谢广大福友的支持,举办了《中颂福短视频大赛》第一名有 10 万元奖金,该活动于 2022年3月28日截止。"},
{Role: "user", Content: "中颂福产品定价,分为三个系列,喜系列 6 瓶装¥1188/箱,和系列 6 瓶装¥2208/箱,贵系列 6 瓶装¥3588/箱。"},
{Role: "user", Content: "现在你将扮演一个白酒的销售人员,你的名字叫颂福。你将扮演一个白酒的销售人员,你的名字叫颂福。你要销售白酒品牌叫中颂福,是东莞盟大集团生产的一款酱香酒,原产地在贵州茅台镇,属于宋代官窑。中颂福的创始人叫李实,他也是东莞盟大集团有限公司的董事长,联合创始人是盟大集团白酒事业部负责人牛星君。中颂福的酒体协调,在你的酒量之内,不会出现头疼、辣口、口干、宿醉的现象。中颂福酒,明码标价,不打折,不赠送。追求的核心价值,把[酒]本身做好,甚至连包装,我们都选择了最低成本,朴实无华的材质。我们永远站在“喝酒的人”的立场上,让利给信任和喜爱中颂福的人。中颂福产品定价,分为三个系列,喜系列 6 瓶装¥1188/箱,和系列 6 瓶装¥2208/箱,贵系列 6 瓶装¥3588/箱。"},
{Role: "assistant", Content: "你好,我是中颂福的销售代表颂福。中颂福是一款来自贵州茅台镇的酱香酒,由盟大集团生产。中颂福的酒体协调,不会让您感到头疼、辣口、口干、宿醉等不适感受。我们一直秉持着把酒本身做好的理念,不追求华丽的包装,以最低成本提供最高品质的白酒给喜爱中颂福的人。"},
},
},
@ -102,7 +91,8 @@ func GetDefaultChatRole() map[string]ChatRole {
Key: "english_trainer",
Name: "英语陪练员",
Context: []Message{
{Role: "system", Content: "你是一位优秀的英语教练,你非常有耐心,你的主要工作就是跟学生使用英语对话,如果发现学生的回答中有语法错误,你将使用中文将错误指出。"},
{Role: "user", Content: "现在你将扮演一位优秀的英语教练,你非常有耐心,你的主要工作就是跟学生使用英语对话,如果发现学生的回答中有语法错误,你将使用中文将错误指出。"},
{Role: "user", Content: "好的,让我们开始对话练习吧!请问你的名字是什么?\n(Translation: Okay, let's start our conversation practice! What's your name?)"},
},
},
}

View File

@ -60,7 +60,7 @@ func NewDefaultConfig() *Config {
ApiKeys: []string{""},
Model: "gpt-3.5-turbo",
MaxTokens: 1024,
Temperature: 1.0,
Temperature: 0.9,
EnableContext: true,
},
EnableAuth: true,

View File

@ -1,2 +0,0 @@
VUE_APP_API_HOST=http://172.22.11.200:5678
VUE_APP_WS_HOST=ws://172.22.11.200:5678

271
web/package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -68,7 +68,7 @@
title="请输入口令继续访问"
>
<el-row>
<el-input v-model="token" placeholder="在此输入口令">
<el-input v-model="token" placeholder="在此输入口令" @keyup="loginInputKeyup">
<template #prefix>
<el-icon class="el-input__icon">
<Lock/>
@ -105,7 +105,7 @@ export default defineComponent({
logo: 'images/logo.png',
chatData: [],
options: [],
role: 'seller',
role: 'programmer',
inputValue: '', //
chatBoxHeight: 0, //
showConnectDialog: false,
@ -190,6 +190,7 @@ export default defineComponent({
},
methods: {
// socket
connect: function () {
// WebSocket
const token = getSessionId();
@ -204,7 +205,6 @@ export default defineComponent({
options.push(res.data[key])
}
this.options = options;
console.log(res.data);
}).catch(() => {
ElMessage.error("获取聊天角色失败");
})
@ -237,6 +237,7 @@ export default defineComponent({
this.chatData[this.chatData.length - 1]["content"] = md.render(this.lineBuffer);
nextTick(() => {
hl.configure({ignoreUnescapedHTML: true})
const lines = document.querySelectorAll('.chat-line');
const blocks = lines[lines.length - 1].querySelectorAll('pre code');
blocks.forEach((block) => {
@ -360,8 +361,14 @@ export default defineComponent({
this.showLoginDialog = true;
this.loading = false;
})
}
},
//
loginInputKeyup: function (e) {
if (e.keyCode === 13) {
this.submitToken();
}
}
},
})