Browse Source

完善智能体交互功能

han_v0
han2015 4 months ago
parent
commit
6608c5dbf4
  1. 50
      src/api/doc/space.ts
  2. 148
      src/views/doc/agent.vue

50
src/api/doc/space.ts

@ -129,3 +129,53 @@ export function doAiChat(_url:string,data: aiChatData,sig?:AbortSignal){
}
)
}
/**
* userid获取记录列表
* @requires userid
*/
export function getAiChatList(data:any){
return request({
url: '/aibot/chat/list',
method: 'post',
data: data
});
}
/**
*
* @requires userid
* @requires uuid
*/
export function getAiChat(data: any){
return request({
url: '/aibot/chat',
method: 'post',
data: data
});
}
/**
*
* @requires userid
* @requires uuid
*/
export function delAiChat(data: any){
return request({
url: '/aibot/chat/del',
method: 'post',
data: data
});
}
/**
*
* @requires userid
* @requires uuid
*/
export function setAiChat(data: any){
return request({
url: '/aibot/chat/update',
method: 'post',
data: data
});
}

148
src/views/doc/agent.vue

@ -8,7 +8,7 @@ import {
Promotion,
Remove
} from '@element-plus/icons-vue'
import { doAiTraining,doAiChat,aiChatData} from "@/api/doc/space"
import { doAiTraining,doAiChat,aiChatData,getAiChatList,getAiChat,setAiChat,delAiChat} from "@/api/doc/space"
import {ElText,ElInput, ButtonInstance} from "element-plus";
import { VueMarkdown } from '@crazydos/vue-markdown'
import rehypeRaw from 'rehype-raw'
@ -17,12 +17,14 @@ import remarkGfm from 'remark-gfm'
//
const checkedModel = ref([])
//
const aimodels = [{name:'新对话',key:"context"}, {name:'联网检索',key:"onlineSearch"}, {name:'公司知识库',key:"useDataset"}]
const aimodels = [{name:'联网检索',key:"onlineSearch"}, {name:'公司知识库',key:"useDataset"}]
const baseURL=import.meta.env.VITE_APP_BASE_API
const conversation=ref("")
const conversation=ref("") //uuid
const myquestion=ref('')
const controller = ref<AbortController | null>(null)
const inputState=ref(true)
const conversations=ref<chatRecord[]>([])
const centHoverItem=ref("")
const interact_msg=ref<{ask:boolean,think:string,content:string}[]>([])
const props = withDefaults(defineProps<{
@ -33,6 +35,20 @@ const props = withDefaults(defineProps<{
const respMsg=ref("")
//
interface message{
ask:boolean,
think:string,
content:string
}
//
interface chatRecord{
uuid:string,
agentuuid:string,
brief:string,
messages:message[]
}
/* 中断函数,供按钮调用 */
function abortFetch() {
if (controller.value) {
@ -44,17 +60,21 @@ function abortFetch() {
async function onSendTextToAI(){
if(myquestion.value==="")return;
inputState.value=false
interact_msg.value.push({ask:true,think:"", content:myquestion.value})
const params={
"onlineSearch":"否",
"useDataset":"否"
}
for (let item of checkedModel.value){
if(item==="context") conversation.value=""
if(item==="onlineSearch") params.onlineSearch="是"
if(item==="useDataset") params.useDataset="是"
}
if (conversation.value==""){
//
interact_msg.value=[{ask:true,think:"", content:myquestion.value}]
}else{
interact_msg.value.push({ask:true,think:"", content:myquestion.value})
}
controller.value = new AbortController();
try{
@ -63,7 +83,7 @@ async function onSendTextToAI(){
query:myquestion.value,
response_mode:"streaming",
conversation_id:conversation.value,
user:atob(props.userid),
user:atob(props.userid),//base64
},controller.value.signal
)
@ -100,6 +120,7 @@ async function onSendTextToAI(){
if (e.name === 'AbortError') {
console.log('用户手动中断')
}
}finally{
inputState.value=true
}
@ -112,13 +133,69 @@ async function onSendTextToAI(){
}
respMsg.value=""
setAiChat({
"userid":atob(props.userid),
"uuid":conversation.value,
"brief":interact_msg.value[0].content,
"content":JSON.stringify(interact_msg.value)
})
}
//
function loadKnownLibList(){
//userid base64
getAiChatList({"userid":atob(props.userid)}).then(resp=>{
conversations.value=resp.data
})
}
//
function showChat(uuid:string){
getAiChat({
"userid":atob(props.userid),
"uuid":uuid
}).then(resp=>{
interact_msg.value = JSON.parse(resp.data.content)
conversation.value=resp.data.uuid
})
}
//
function onDelChat(uuid:string){
delAiChat({
"userid":atob(props.userid),
"uuid":uuid
}).then(resp=>{
loadKnownLibList()
})
}
function handleMouseEnter(row:any){
if(centHoverItem.value==row.uuid) return;
centHoverItem.value=row.uuid
}
function handleMouseLeave(){
centHoverItem.value=""
}
function newContext(){
inputState.value=true
interact_msg.value=[]
conversation.value=""
loadKnownLibList() //
}
function resetContext(){
interact_msg.value=[]
conversation.value=""
props.closefunc()
}
//
onMounted(() => {
//loadKnownLibList()
loadKnownLibList()
});
</script>
<template>
@ -126,12 +203,21 @@ onMounted(() => {
:model-value="agent.model"
:title="agent.name+' : 知识库'"
direction="rtl"
size="60%"
@close="closefunc"
:style="{padding:'17px'}">
<el-row :gutter="24" style="height: 99%;">
<el-col style="position: relative;background: white;">
size="80%"
@close="resetContext"
:style="{padding:'17px',backgroundColor:'#f3f3f3'}">
<div style="display:grid;grid-template-columns:1fr 4fr; width: 100%;height: 100%;">
<div style="overflow-y: auto;">
<ul>
<li class="action_menu" @click="newContext">
新建会话
</li>
<li class="list_item" v-for="item in conversations" @mouseover="handleMouseEnter(item)" @mouseleave="handleMouseLeave()" @click="showChat(item.uuid)">{{ item.brief }}
<el-button v-show="centHoverItem == item.uuid" icon="Delete" size="small" circle @click="(e)=>{e.stopPropagation();onDelChat(item.uuid)}"></el-button>
</li>
</ul>
</div>
<div style="position: relative;background: white;overflow-y: auto;">
<div class="reply_area" >
<template v-for="msg of interact_msg">
<el-text v-if="msg.ask" class="t_ask" >{{ msg.content }}</el-text>
@ -143,20 +229,22 @@ onMounted(() => {
</template>
<VueMarkdown :markdown="respMsg" :rehype-plugins="[rehypeRaw]" class="t_resp"></VueMarkdown>
</div>
<div class="question_com">
<div class="question_com" :class="{newquestion:conversation!='' || !inputState}">
<h1 v-show="conversation =='' && inputState" style="font-size: 78px;margin: 10px;">恒信高科AI平台</h1>
<el-checkbox-group v-model="checkedModel" style="display:flex; margin-bottom: 10px;">
<el-checkbox-button v-for="mod in aimodels" :value="mod.key">
{{ mod.name }}
</el-checkbox-button>
</el-checkbox-group>
<el-input placeholder="问灵犀..." v-model="myquestion" input-style="border-radius: 20px;"
resize="none" :autosize="{minRows: 4}" type="textarea" />
<el-button :style="{display :inputState ? '':'none'}" type="primary" :icon="Promotion" circle @click="onSendTextToAI"/>
<el-button :style="{display :inputState ? 'none':''}" type="primary" :icon="Remove" circle @click="abortFetch"/>
<span>内容由 AI 生成请仔细甄别</span>
</div>
</el-col>
</el-row>
</div>
</div>
</el-drawer>
</template>
@ -167,9 +255,11 @@ onMounted(() => {
height: 100%;
width: 100%;
}
.newquestion{
bottom: 20px;
}
.question_com{
position: fixed;
bottom: 25px;
width: 52%;
margin: 0 50px;
text-align: center;
@ -182,6 +272,7 @@ onMounted(() => {
}
.reply_area{
display: flex;
min-height: 20%;
flex-direction: column;
margin: 15px 15px 110px 0px;
}
@ -203,6 +294,27 @@ onMounted(() => {
.dynamic-width-message-box-byme .el-message-box__message{
width: 100%;
}
.action_menu{
background-color: white;
padding: 10px 8px;
margin: 3px 14px 18px 0;
border-radius: 8px;
border: 1px solid #c9c6c6;
}
.list_item{
display: flex;
background-color: #dddddd;
padding: 10px 8px;
margin: 3px 14px 3px 0;
overflow: hidden;
text-overflow: ellipsis;
border-radius: 8px;
text-wrap-mode: nowrap;
button{
margin-left: auto;
}
}
</style>
<style>
think {

Loading…
Cancel
Save