123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609 |
- <template>
- <div class="chat" v-loading="loading">
- <div class="c_chat" ref="chatRef">
- <div class="c_c_i_ai">
- <div class="c_c_i_ai_avatar">
- <el-avatar
- style="width: 100%; height: 100%"
- :src="
- require('../../../../assets/icon/pblCourse/aiTeacherAvatar.png')
- "
- fit="fit"
- ></el-avatar>
- </div>
- <div class="c_c_i_ai_message">
- <div class="c_c_i_ai_m_top">
- <span>小可老师</span>
- <span class="chatTime">{{ new Date().toLocaleString().replaceAll('/','-') }}</span>
- </div>
- <div class="c_c_i_ai_m_bottom">
- <div
- v-loading="false"
- class="c_c_i_ai_m_content chatContent"
- >
- <p>同学你好,我是你的助教老师小可,你有什么问题要问我吗?</p>
- <p style="margin-top:5px">我很擅长协助你探索以下问题哦~</p>
- <ul style="color:#3673E8;margin-top: 10px;">
- <li style="margin-top: 5px;cursor: pointer;" @click="sendChat('作业思路讨论')">作业思路讨论</li>
- <li style="margin-top: 5px;cursor: pointer;" @click="sendChat('回答学习疑惑')">回答学习疑惑</li>
- <li style="margin-top: 5px;cursor: pointer;" @click="sendChat('查找资源资料')">查找资源资料</li>
- <li style="margin-top: 5px;cursor: pointer;" @click="sendChat('整理学习资料')">整理学习资料</li>
- </ul>
- </div>
- <!-- <span class="coptText" @click="copyText(item.aiContent)"></span> -->
- </div>
- </div>
- </div>
- <div class="c_c_item" v-for="item in chatList" :key="item.uid">
- <div class="c_c_i_user" v-if="item.content">
- <div class="c_c_i_u_message">
- <div class="c_c_i_u_m_top">
- <span class="chatTime">{{ item.createtime }}</span>
- <span>科科</span>
- </div>
- <div class="c_c_i_u_m_bottom">
- <span class="coptText" @click="copyText(item.aiContent)"></span>
- <div
- class="c_c_i_u_m_content chatContent"
- v-html="item.content"
- ></div>
- </div>
- </div>
- <div class="c_c_i_u_avatar">
- <el-avatar
- style="width: 100%; height: 100%"
- :src="require('../../../../assets/icon/pblCourse/userAvatar.png')"
- fit="fit"
- ></el-avatar>
- </div>
- </div>
- <div class="c_c_i_ai">
- <div class="c_c_i_ai_avatar">
- <el-avatar
- style="width: 100%; height: 100%"
- :src="
- require('../../../../assets/icon/pblCourse/aiTeacherAvatar.png')
- "
- fit="fit"
- ></el-avatar>
- </div>
- <div class="c_c_i_ai_message">
- <div class="c_c_i_ai_m_top">
- <span>小可老师</span>
- <span class="chatTime">{{item.createtime}}</span>
- </div>
- <div class="c_c_i_ai_m_bottom">
- <div
- v-loading="item.loading"
- class="c_c_i_ai_m_content chatContent"
- v-html="item.aiContent"
- ></div>
- <span class="coptText" @click="copyText(item.aiContent)"></span>
- </div>
- </div>
- </div>
- </div>
- </div>
- <!-- <div class="c_controls">
- <span class="c_controls_item" @click="clearChat">清空对话</span>
- </div> -->
- <div class="c_bottom" v-loading="chatLoading">
- <!-- <div class="c_b_record">
- <span></span>
- </div> -->
- <div class="c_b_inputArea">
- <el-input
- class="c_b_input"
- @keyup.enter.native="send()"
- v-model="textValue"
-
- >
- </el-input>
- <!-- <span></span> -->
- </div>
- <div class="c_b_send" @click="send">
- <span></span>
- </div>
- </div>
- </div>
- </template>
- <script>
- import { v4 as uuidv4 } from "uuid";
- import MarkdownIt from "markdown-it";
- export default {
- data() {
- return {
- loading: false,
- chatLoading:false,
- userId:this.$route.query['userid'],
- cid: this.$route.query.cid,
- chatList: [],
- textValue: "",
- };
- },
- methods: {
- // 发送消息
- send() {
- if(this.chatLoading || this.loading)return this.$message.info("请稍等...")
- if(!this.textValue.trim())return this.$message.info("请输入内容");
- const _uuid = uuidv4();
- this.chatLoading = true;
- this.chatList.push({
- role: "user",
- content: `${this.textValue}`,
- uid: _uuid,
- AI: "AI",
- aiContent: "",
- oldContent: "",
- filename: "",
- index: this.chatList.length,
- createtime:new Date().toLocaleString().replaceAll("/",'-'),
- loading: true,
- })
- let history = [];
- let _msg = ''
- if(this.textValue=='作业思路讨论'){
- this,$message.info("作业思路讨论")
- _msg = `作业思路讨论`
- }else if(this.textValue=='回答学习疑惑'){
- this,$message.info("回答学习疑惑")
- _msg = `回答学习疑惑`
- }else if(this.textValue=='查找资源资料'){
- this,$message.info("查找资源资料")
- _msg = `查找资源资料`
- }else if(this.textValue=='整理学习资料'){
- this,$message.info("整理学习资料")
- _msg = `整理学习资料`
- }
- if(_msg){
- history.push({role:"user",content:_msg})
- }
- history.push({role:"user",content:this.textValue})
- // let params = {
- // model: "gpt-3.5-turbo",
- // temperature: 0,
- // max_tokens: 4096,
- // top_p: 1,
- // frequency_penalty: 0,
- // presence_penalty: 0,
- // messages: history,
- // uid: _uuid,
- // mind_map_question: this.textValue,
- // }
- let params = JSON.stringify({
- message: {
- anthropic_version: "bedrock-2023-05-31",
- max_tokens: 4096,
- temperature: 0,
- top_p: 1,
- messages: history
- },
- uid: _uuid,
- model: "Claude 3 Sonnet" // Claude 3 Sonnet或者Claude 3 Haiku
- });
- this.scrollBottom();
- this.textValue = "";
- this.ajax
- // .post("https://gpt4.cocorobo.cn/chat", params)
- .post("https://claude3.cocorobo.cn/chat", params)
- .then((res) => {
- if (res.data.FunctionResponse.result == "发送成功") {
- } else {
- this.chatLoading = false;
- this.$message.warning(res.data.FunctionResponse.result);
- }
- })
- .catch((e) => {
- this.chatLoading = false;
- console.log(e);
- });
- // this.$message.info(`发送:${this.textValue}`);
- // this.textValue = "";
- this.getAiContent(_uuid)
- },
- getAiContent(_uid) {
- let _source = new EventSource(`https://claude3.cocorobo.cn/streamChat/${_uid}`);
- // let _source = new EventSource(`https://gpt4.cocorobo.cn/stream/${_uid}`); //http://gpt4.cocorobo.cn:8011/stream/ https://gpt4.cocorobo.cn/stream/
- let _allText = "";
- let _mdText = "";
- const md = new MarkdownIt();
- _source.onmessage = (_e) => {
- if (_e.data.replace("'", "").replace("'", "") == "[DONE]") {
- //对话已经完成
- _mdText = _mdText.replace("_", "");
- _source.close();
- this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
- this.chatList.find((i) => i.uid == _uid).isalltext = true;
- this.chatList.find((i) => i.uid == _uid).isShowSynchronization = true;
- this.chatList.find((i) => i.uid == _uid).loading = false;
- this.chatLoading = false;
- this.insertChat(_uid);
- return;
- } else {
- //对话还在继续
- let _text = "";
- _text = _e.data.replaceAll("'", "");
- if (_allText == "") {
- _allText = _text.replace(/^\n+/, ""); //去掉回复消息中偶尔开头就存在的连续换行符
- } else {
- _allText += _text;
- }
- _mdText = _allText + "_";
- _mdText = _mdText.replace(/\\n/g, "\n");
- _mdText = _mdText.replace(/\\/g, "");
- if (_allText.split("```").length % 2 == 0) _mdText += "\n```\n";
- //转化返回的回复流数据
- _mdText = md.render(_mdText);
- this.chatList.find((i) => i.uid == _uid).aiContent = _mdText;
- this.chatList.find((i) => i.uid == _uid).loading = false;
- this.scrollBottom();
- // 处理流数据
- }
- };
- },
- // 复制
- copyText(_html) {
- const div = document.createElement("div")
- div.innerHTML = _html
- const _text = div.innerText
- navigator.clipboard.writeText(_text).then(_=>{
- this.$message.success("复制成功")
- }, function(err) {
- this.$message.error(`无法复制:${err}`)
- });
- },
- // 保存对话
- //保存消息
- insertChat(_uid) {
- let _data = this.chatList.find((i) => i.uid == _uid);
- if (!_data) return;
- let params = {
- userId: this.userId,
- userName: "qgt",
- groupId: "602def61-005d-11ee-91d8-005056b8q12w",
- answer: _data.aiContent,
- problem: _data.content,
- file_id: "",
- alltext: _data.aiContent,
- type: "chat",
- filename: _data.filename,
- session_name: `${this.userId}-${this.cid}-pblCourse`,
- };
- this.ajax
- .post("https://gpt4.cocorobo.cn/insert_chat", params)
- .then((res) => {
- console.log("保存对话")
- });
- },
- // 获取对话记录
- getChatList() {
- return new Promise((resolve, reject) => {
- this.chatList = [];
- this.loading = true;
- this.chatLoading = true;
- let params = {
- userid: this.userId,
- groupid: "602def61-005d-11ee-91d8-005056b8q12w",
- // session_name:``
- session_name: `${this.userId}-${this.cid}-pblCourse`,
- };
- this.ajax
- .post("https://gpt4.cocorobo.cn/get_agent_park_chat", params)
- .then((res) => {
- let _data = JSON.parse(res.data.FunctionResponse);
- if (_data.length > 0) {
- console.log(_data)
- let _chatList = [];
- for (let i = 0; i < _data.length; i++) {
- _chatList.push({
- loading: false,
- role: "user",
- content: _data[i].problem,
- uid: _data[i].id,
- AI: "AI",
- aiContent: _data[i].answer,
- oldContent: _data[i].answer,
- isShowSynchronization: false,
- filename: _data[i].filename,
- index: i,
- is_mind_map: false,
- fileid: _data[i].fileid,
- createtime:_data[i].createtime
- });
- }
- this.chatList = _chatList;
- this.chatLoading = false;
- this.loading = false;
- } else {
- //没有对话记录
- this.loading = false;
- this.chatLoading = false;
- }
- resolve();
- this.scrollBottom();
- })
- .catch((err) => {
- console.log(err);
- this.$message.error("获取对话记录失败");
- this.chatLoading = false;
- this.scrollBottom();
- resolve();
- });
- });
- },
- //对话触底
- scrollBottom(){
- this.$nextTick(()=>{
- this.$refs.chatRef.scrollTop = this.$refs.chatRef.scrollHeight;
- })
- },
- //清除对话
- clearChat(){
- this.chatList = [];
- this.scrollBottom();
- },
- sendChat(_text){
- this.textValue = _text;
- this.send();
- }
- },
- mounted() {
- this.getChatList().then(_=>{
- this.scrollBottom();
- })
- },
- };
- </script>
- <style scoped>
- .chat {
- width: 100%;
- height: 100%;
- background-color: #ffffff;
- border-radius: 12px;
- box-sizing: border-box;
- border: solid 1px #f3f7fd;
- box-shadow: 0 4px 10px 0 #1d388321;
- }
- .c_chat {
- width: 100%;
- height: calc(100% - 56px);
- box-sizing: border-box;
- padding: 15px;
- overflow: auto;
- }
- .c_c_item {
- background-color: none;
- }
- .c_c_i_user {
- width: 100%;
- height: auto;
- display: flex;
- justify-content: flex-end;
- align-items: flex-start;
- margin-bottom: 10px;
- }
- .c_c_i_u_message {
- height: auto;
- width: auto;
- max-width: calc(100% - 50px - 40px);
- display: flex;
- flex-direction: column;
- align-items: flex-end;
- margin-right: 5px;
- }
- .c_c_i_u_m_top {
- margin-bottom: 10px;
- display: flex;
- align-items: flex-end;
- }
- .c_c_i_u_m_top > span {
- margin-left: 5px;
- }
- .c_c_i_u_m_bottom {
- display: flex;
- align-items: flex-end;
- }
- .coptText {
- min-width: 15px;
- min-height: 15px;
- display: block;
- background: url("../../../../assets/icon/pblCourse/copyIcon.png") no-repeat;
- background-size: 100% 100%;
- margin: 0px 10px 6px 10px;
- cursor: pointer;
- }
- .c_c_i_u_m_content {
- width: auto;
- height: auto;
- padding: 10px;
- background-color: #e2eeff;
- border-radius: 8px 2px 8px 8px;
- border: solid 1px #000000e5;
- }
- .c_c_i_u_avatar {
- width: 45px;
- height: 45px;
- margin: 0px 0 0 10px;
- }
- .c_c_i_ai {
- margin-top: 10px;
- width: 100%;
- height: auto;
- display: flex;
- align-items: flex-start;
- margin-bottom: 10px;
- }
- .c_c_i_ai_avatar {
- width: 45px;
- height: 45px;
- margin: 0px 0 0 10px;
- }
- .c_c_i_ai_message {
- height: auto;
- width: auto;
- max-width: calc(100% - 50px - 40px);
- display: flex;
- flex-direction: column;
- align-items: flex-start;
- margin-left: 5px;
- }
- .c_c_i_ai_m_top {
- display: flex;
- align-items: flex-end;
- margin-bottom: 10px;
- }
- .c_c_i_ai_m_top > span {
- margin-left: 5px;
- }
- .c_c_i_ai_m_bottom {
- display: flex;
- align-items: flex-end;
- }
- .c_c_i_ai_m_content {
- min-width: 40px;
- min-height: 25px;
- width: auto;
- height: auto;
- padding: 10px;
- background-color: #ffffff;
- border-radius: 2px 8px 8px 8px;
- border: solid 1px #000000e5;
- }
- .chatContent >>> ol {
- margin-left: 25px;
- }
- .chatContent >>> ul {
- margin-left: 25px;
- }
- .chatTime{
- font-size: 14px;
- margin: 0 10px;
- color: #2c2f3b;
- }
- .c_controls{
- width: 100%;
- height: 30px;
- }
- .c_controls>span{
- max-height: 30px;
- width: auto;
- padding: 5px 10px;
- font-size: 14px;
- border-radius: 15px;
- box-shadow: 0 0 2px 0px gray;
- margin-left: 10px;
- cursor: pointer;
- }
- .c_controls>span:hover{
- background-color: #f3f7fd;
- }
- .c_bottom {
- width: 100%;
- height: 56px;
- display: flex;
- align-items: center;
- justify-content: center;
- box-sizing: border-box;
- border-top: solid 0.5px #e7e7e7;
- }
- .c_b_record {
- width: 30px;
- height: 30px;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .c_b_record > span {
- width: 24px;
- height: 24px;
- background-image: url("../../../../assets/icon/pblCourse/recordIcon.png");
- background-size: 100% 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- }
- .c_b_inputArea {
- width: calc(100% - 100px);
- background-color: #f3f3f3;
- border-radius: 50px;
- height: 80%;
- display: flex;
- justify-content: center;
- align-items: center;
- margin: 0 15px;
- }
- .c_b_input {
- width: calc(100% - 40px);
- margin-right: 10px;
- }
- .c_b_input >>> .el-input__inner {
- border: none;
- background-color: #f3f3f3;
- outline: none;
- border-radius: 50px 0 0 50px;
- font-size: 1.2em;
- }
- .c_b_inputArea > span {
- width: 24px;
- height: 24px;
- background-image: url("../../../../assets/icon/pblCourse/fileIcon.png");
- background-size: 100% 100%;
- display: flex;
- justify-content: center;
- align-items: center;
- margin-right: 10px;
- cursor: pointer;
- }
- .c_b_send {
- width: 40px;
- height: 40px;
- border-radius: 50%;
- background-color: #3681fc;
- cursor: pointer;
- display: flex;
- justify-content: center;
- align-items: center;
- cursor: pointer;
- }
- .c_b_send > span {
- width: 60%;
- height: 60%;
- background-image: url("../../../../assets/icon/pblCourse/sendIcon.png");
- background-size: 100% 100%;
- }
- </style>
|