| | |
| | | AnswerState, |
| | | AnswerType, |
| | | ChatContent, |
| | | ChatMessage, |
| | | RoleEnum, |
| | | roleImageMap |
| | | } from "@/model/chat/types"; |
| | | import { |
| | | CHAT_GROUP_DATA, |
| | | TEST_DATA |
| | | } from "./testData"; |
| | | import { |
| | | TAB_BAR_HEIGHT |
| | | } from "@/custom-tab-bar/constants"; |
| | | import { |
| | | checkAuth |
| | | } from "@/utils/http"; |
| | | import { GetHistoryAnswer, QueryHistoryDetail } from "@/api/chat"; |
| | | import { CreateHistoryGroup, DeleteHistoryGroups, extCallQuery, GetHistoryAnswer, GetHistoryGroups, getQuestionProcess, getSelectSample, QueryHistoryDetail, QuestionAi, setHistoryGroupTitle } from "@/api/chat"; |
| | | |
| | | import { ErrorCode } from "@/utils/http"; |
| | | import { ComponentWithComputed, } from "miniprogram-computed"; |
| | | import { uuid } from "@/utils/uuid"; |
| | | import { getStorage } from "@/utils/storage"; |
| | | import { getCurrentUrl } from "@/utils/common"; |
| | | import { SHARE_CONFIG } from "@/config/constants"; |
| | | |
| | | const app = getApp(); |
| | | // pages/question/question.js |
| | | const getAnswerById = async (historyId: string) => { |
| | | return await GetHistoryAnswer({ |
| | | history_id: historyId, |
| | | }); |
| | | }; |
| | | |
| | | const DEFAULT_SECTION_A_ID = 'knowledge_base' |
| | | |
| | | const parseContent = (res) => { |
| | | if (!res) return null; |
| | |
| | | type: AnswerType.Summary, |
| | | values: res.summary, |
| | | }; |
| | | |
| | | break; |
| | | case AnswerType.Url: |
| | | content = { |
| | |
| | | content.origin = res; |
| | | return content; |
| | | }; |
| | | Component({ |
| | | |
| | | |
| | | |
| | | let processId = ''; |
| | | const QUERY_PROCESS_INTERVAL = 1000; |
| | | let processTimer = null; |
| | | let finishProcess = true; |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | |
| | | Page({ |
| | | |
| | | |
| | | |
| | | // 页面的初始数据 |
| | | data: { |
| | | isTalking: false, |
| | | AnswerType, |
| | | sendText: '', |
| | | sendText: '你是谁?', |
| | | chatHistory: [], |
| | | roleImageMap, |
| | | RoleEnum, |
| | | drawerIsShow: false, |
| | | displayChatRoom: CHAT_GROUP_DATA, |
| | | chatRoomList: [], |
| | | toViewId: '', |
| | | TAB_BAR_HEIGHT: TAB_BAR_HEIGHT, |
| | | ErrorCode, |
| | | questionRes: null, |
| | | activeChatRoom: { |
| | | "group_id": "a8197e731f704943974946e0d260bd5c", |
| | | "group_title": "查询控江路压流一体设备的昨日瞬时流量", |
| | | "chat_count": "8", |
| | | "create_time": "2024-07-19 20:56:24" |
| | | }, |
| | | }, |
| | | methods: { |
| | | onSendTextChange: function (e) { |
| | | // this.setData({ |
| | | // sendText:e.detail.value |
| | | // }) |
| | | }, |
| | | chatRoomClick(e) { |
| | | const item = e.currentTarget.dataset.item; |
| | | this.setData({ |
| | | activeChatRoom: item, |
| | | }) |
| | | }, |
| | | delChatRoomClick(e) { |
| | | const id = e.currentTarget.dataset.id; |
| | | wx.modal({ |
| | | content: '确定删除当前聊天室吗?' |
| | | }).then(val => { |
| | | if (!val) return; |
| | | }) |
| | | }, |
| | | processText: '', |
| | | /** @description 所有得sample */ |
| | | sampleList: [], |
| | | /** @description 随机抽出最多三个例子 */ |
| | | displaySampleList: [], |
| | | section_a_id: '', |
| | | sample_id: '', |
| | | userName: getStorage('username'), |
| | | keyboardHeight: 0, |
| | | |
| | | // 聊天室图标点击 |
| | | chatRoomListClick() { |
| | | }, |
| | | onClickClear() { |
| | | console.log('clear'); |
| | | |
| | | this.setData({ |
| | | sendText: '' |
| | | }) |
| | | }, |
| | | inputFocus(e) { |
| | | if (e.detail.height > 0) { |
| | | this.setData({ |
| | | drawerIsShow: true, |
| | | }) |
| | | }, |
| | | drawerCloseClick() { |
| | | this.setData({ |
| | | drawerIsShow: false, |
| | | keyboardHeight: e.detail.height - 55 |
| | | }) |
| | | } |
| | | }, |
| | | |
| | | lifetimes: { |
| | | async attached() { |
| | | const isPassed = checkAuth(); |
| | | if (!isPassed) return; |
| | | const res = await QueryHistoryDetail({ |
| | | history_group_id: this.data.activeChatRoom.group_id, |
| | | }); |
| | | changeInputBlur(e) { |
| | | this.setData({ |
| | | keyboardHeight: 0 |
| | | }) |
| | | }, |
| | | async getSampleList() { |
| | | const res = await getSelectSample({ |
| | | section_b_id: '', |
| | | }); |
| | | this.setData({ |
| | | sampleList: res?.samples ?? [] |
| | | }) |
| | | this.setData({ |
| | | displaySampleList: wx.$_.sampleSize(this.data.sampleList, 3) |
| | | }) |
| | | }, |
| | | sampleClick(e) { |
| | | const item = e.currentTarget.dataset.item; |
| | | this.setData({ |
| | | sample_id: item.sample_id, |
| | | sendText: item.sample_question, |
| | | section_a_id: item.section_a_id, |
| | | }) |
| | | }, |
| | | queryProcess() { |
| | | processTimer = setInterval(() => { |
| | | if (!finishProcess) return; |
| | | finishProcess = false; |
| | | this.queryProcessApi(); |
| | | }, QUERY_PROCESS_INTERVAL); |
| | | }, |
| | | async queryProcessApi() { |
| | | const res = await getQuestionProcess({ |
| | | process_id: processId, |
| | | }, { |
| | | isLoading: false |
| | | }).catch((err) => { |
| | | this.setData({ |
| | | chatHistory: (res.details ?? []).map((item) => { |
| | | return { |
| | | historyId: item.history_id, |
| | | role: RoleEnum.user, |
| | | content: { |
| | | type: AnswerType.Text, |
| | | values: item.question, |
| | | }, |
| | | } |
| | | }) |
| | | processText: err |
| | | }) |
| | | }); |
| | | this.setData({ |
| | | processText: res.process |
| | | }) |
| | | finishProcess = true; |
| | | }, |
| | | clearQueryProcess() { |
| | | this.setData({ |
| | | processText: '' |
| | | }) |
| | | clearInterval(processTimer); |
| | | }, |
| | | async questionAi(text) { |
| | | // if (!currentSectionId) { |
| | | // ElMessage.warning('发送失败,未确定应用场景!'); |
| | | // } |
| | | processId = uuid(); |
| | | // const judgeParams = !preQuestion.value |
| | | // ? {} |
| | | // : { |
| | | // prev_question: preQuestion.value, |
| | | // }; |
| | | let currentSectionAId = ''; |
| | | if (this.data.section_a_id) { |
| | | currentSectionAId = this.data.section_a_id; |
| | | this.data.section_a_id = ''; |
| | | } else { |
| | | const lastSectionAItem = wx.$_.findLast(this.data.chatHistory, (item) => item.role === RoleEnum.assistant && !!item.sectionAId); |
| | | currentSectionAId = lastSectionAItem?.sectionAId ?? DEFAULT_SECTION_A_ID; |
| | | } |
| | | const judgeParams = {} |
| | | const params = { |
| | | process_id: processId, |
| | | question: text, |
| | | section_a_id: currentSectionAId, |
| | | history_group_id: this.data.activeChatRoom.id, |
| | | raw_mode: false, |
| | | ...judgeParams, |
| | | } as any; |
| | | if (this.data.sample_id) { |
| | | params.sample_id = this.data.sample_id; |
| | | this.data.sample_id = ''; |
| | | } |
| | | |
| | | // currentSectionId = res?.details?.[0]?.section_a_id; |
| | | // currentSampleId = res?.details?.[0]?.sample_id; |
| | | const resList: any[] = await Promise.all((res.details ?? []).map((item) => getAnswerById(item.history_id))); |
| | | let i = 0; |
| | | |
| | | resList.map((item, index) => { |
| | | const insertIndex = index + 1 + i; |
| | | this.data.chatHistory.splice( |
| | | insertIndex, |
| | | 0, |
| | | item.answer === null ? |
| | | null : |
| | | { |
| | | historyId: item.answer?.history_id, |
| | | role: RoleEnum.assistant, |
| | | content: parseContent(item.answer), |
| | | state: item.answer_state, |
| | | } |
| | | ); |
| | | i++; |
| | | // if (currentLLMId) { |
| | | // params.llm_id = currentLLMId; |
| | | // } |
| | | this.clearQueryProcess(); |
| | | this.queryProcess(); |
| | | const res = await QuestionAi(params, { |
| | | isLoading: false |
| | | }).finally(() => { |
| | | this.clearQueryProcess(); |
| | | }); |
| | | this.questionRes = res; |
| | | const content = parseContent(res); |
| | | return content; |
| | | }, |
| | | async sendText(cb?: any, callExtParams?: any) { |
| | | if (!this.data.sendText || this.data.isTalking) return; |
| | | let resMsgContent: ChatContent = null; |
| | | const isInitial = this.data.activeChatRoom.isInitial; |
| | | if (isInitial) { |
| | | this.data.activeChatRoom.isInitial = false; |
| | | this.setData({ |
| | | activeChatRoom: this.data.activeChatRoom |
| | | }) |
| | | /** @description 修改聊天室名称 */ |
| | | const res = await setHistoryGroupTitle({ |
| | | history_group_id: this.data.activeChatRoom.id, |
| | | title: this.data.sendText, |
| | | }, { |
| | | isLoading: false |
| | | }); |
| | | if (!res?.json_ok) return; |
| | | this.data.activeChatRoom.title = this.data.sendText; |
| | | wx.setNavigationBarTitle({ |
| | | title: this.data.activeChatRoom.title |
| | | }) |
| | | this.setData({ |
| | | chatRoomList: this.data.chatRoomList |
| | | }) |
| | | } |
| | | try { |
| | | |
| | | const userItem: ChatMessage = { |
| | | role: RoleEnum.user, content: { |
| | | type: AnswerType.Text, |
| | | values: this.data.sendText |
| | | } |
| | | } as any; |
| | | const assistantItem: ChatMessage = { role: RoleEnum.assistant, content: null, state: AnswerState.Null } as any; |
| | | |
| | | |
| | | // 发送当前 |
| | | this.data.chatHistory.push(userItem); |
| | | const currentText = this.data.sendText; |
| | | |
| | | // 清空输入框 |
| | | this.setData({ |
| | | sendText: '', |
| | | }) |
| | | // 出现回复,等待恢复对话 |
| | | this.setData({ |
| | | isTalking: true |
| | | }) |
| | | this.data.chatHistory.push(assistantItem); |
| | | this.setData({ |
| | | chatHistory: this.data.chatHistory |
| | | }) |
| | | |
| | | // if (messageList.value.length === 0) { |
| | | // messageContent.value = { |
| | | // type: AnswerType.Text, |
| | | // values: activeChatRoom.value.title, |
| | | // }; |
| | | |
| | | // sendChatMessage(); |
| | | // } |
| | | this.scrollToBottom(); |
| | | if (callExtParams) { |
| | | const extRes = await extCallQuery(callExtParams); |
| | | this.questionRes = extRes; |
| | | resMsgContent = parseContent(extRes); |
| | | } else { |
| | | resMsgContent = await this.questionAi(currentText); |
| | | } |
| | | userItem.historyId = this.questionRes.history_id; |
| | | assistantItem.historyId = this.questionRes.history_id; |
| | | this.data.chatHistory[this.data.chatHistory.length - 1].content = resMsgContent |
| | | this.setData({ |
| | | chatHistory: this.data.chatHistory |
| | | }) |
| | | this.scrollToBottom(); |
| | | } catch (error: any) { |
| | | } finally { |
| | | this.setData({ |
| | | isTalking: false |
| | | }) |
| | | } |
| | | }, |
| | | inputRighBtnClick() { |
| | | if (this.data.sendText) { |
| | | this.sendText(); |
| | | } else { |
| | | |
| | | pageLifetimes: { |
| | | show() { |
| | | if (typeof this.getTabBar === 'function' && |
| | | this.getTabBar()) { |
| | | this.getTabBar().setData({ |
| | | selected: 0 |
| | | } |
| | | }, |
| | | async newChatRoomClick(isLoading = true) { |
| | | const res = await CreateHistoryGroup({ |
| | | group_title: 'chat room', |
| | | }, { |
| | | isLoading: isLoading |
| | | }); |
| | | |
| | | const newRoom = { |
| | | id: res.history_group_id, |
| | | isInitial: true, |
| | | title: 'chat room', |
| | | }; |
| | | if (!this.data.chatRoomList) { |
| | | this.data.chatRoomList = [newRoom]; |
| | | } else { |
| | | this.data.chatRoomList.unshift(newRoom); |
| | | } |
| | | this.setData({ |
| | | chatRoomList: this.data.chatRoomList |
| | | }) |
| | | await this.setActiveChatRoom(newRoom); |
| | | }, |
| | | async getHistoryGroupData() { |
| | | const res = await GetHistoryGroups(); |
| | | const resData = (res?.groups || []) as any[]; |
| | | |
| | | // 按最晚时间到最早时间 |
| | | this.data.chatRoomList = wx.$_.orderBy(resData, ['create_time'], ['desc']) |
| | | .map((item) => { |
| | | return { |
| | | id: item.group_id, |
| | | title: item.group_title, |
| | | createTime: item.create_time, |
| | | isInitial: Number(item.chat_count) === 0, |
| | | }; |
| | | }); |
| | | |
| | | if (!this.data.chatRoomList || this.data.chatRoomList.length === 0 || !this.data.chatRoomList?.[0].isInitial) { |
| | | await this.newChatRoomClick(false); |
| | | } else { |
| | | this.setActiveChatRoom(this.data.chatRoomList[0]); |
| | | this.setData( |
| | | { |
| | | chatRoomList: this.data.chatRoomList |
| | | } |
| | | ) |
| | | } |
| | | |
| | | |
| | | |
| | | }, |
| | | onSendTextChange: function (e) { |
| | | // this.setData({ |
| | | // sendText:e.detail.value |
| | | // }) |
| | | }, |
| | | scrollToBottom() { |
| | | wx.nextTick(() => { |
| | | setTimeout(() => { |
| | | this.setData({ |
| | | toViewId: `chat-item-${this.data.chatHistory.length - 1}`, |
| | | }) |
| | | }, 300); |
| | | }) |
| | | |
| | | }, |
| | | async getHistoryDetail() { |
| | | |
| | | const res = await QueryHistoryDetail({ |
| | | history_group_id: this.data.activeChatRoom.id, |
| | | }); |
| | | this.setData({ |
| | | chatHistory: (res.details ?? []).map((item) => { |
| | | return { |
| | | historyId: item.history_id, |
| | | role: RoleEnum.user, |
| | | content: { |
| | | type: AnswerType.Text, |
| | | values: item.question, |
| | | }, |
| | | } |
| | | }) |
| | | }) |
| | | |
| | | |
| | | // currentSampleId = res?.details?.[0]?.sample_id; |
| | | const sectionAIdMap = new Map(); |
| | | const resList: any[] = await Promise.all((res.details ?? []).map((item) => { |
| | | sectionAIdMap.set(item.history_id, item.section_a_id) |
| | | return getAnswerById(item.history_id) |
| | | })); |
| | | let i = 0; |
| | | |
| | | resList.map((item, index) => { |
| | | const insertIndex = index + 1 + i; |
| | | this.data.chatHistory.splice( |
| | | insertIndex, |
| | | 0, |
| | | item.answer === null ? |
| | | null : |
| | | { |
| | | historyId: item.answer?.history_id, |
| | | role: RoleEnum.assistant, |
| | | content: parseContent(item.answer), |
| | | state: item.answer_state, |
| | | sectionAId: sectionAIdMap.get(item.answer.history_id) |
| | | } |
| | | ); |
| | | i++; |
| | | }); |
| | | |
| | | // 过滤为null的结果 |
| | | this.setData({ |
| | | chatHistory: this.data.chatHistory.filter(item => !!item) |
| | | }) |
| | | this.scrollToBottom() |
| | | |
| | | |
| | | }, |
| | | |
| | | resetLastChatRoom() { |
| | | const isInitial = this.data.activeChatRoom.isInitial; |
| | | this.setData({ |
| | | sendText: isInitial ? '你是谁?' : '', |
| | | }) |
| | | }, |
| | | async setActiveChatRoom(room) { |
| | | if (!room) return; |
| | | this.setData({ |
| | | activeChatRoom: room, |
| | | }) |
| | | this.resetLastChatRoom(); |
| | | wx.setNavigationBarTitle({ |
| | | title: this.data.activeChatRoom.title |
| | | }) |
| | | await this.getHistoryDetail(); |
| | | }, |
| | | async chatRoomClick(e) { |
| | | const item = e.currentTarget.dataset.item; |
| | | this.setData({ |
| | | drawerIsShow: false, |
| | | }) |
| | | this.setActiveChatRoom(item) |
| | | }, |
| | | delChatRoomClick(e) { |
| | | const id = e.currentTarget.dataset.item.id; |
| | | wx.modal({ |
| | | content: '确定删除当前聊天室吗?' |
| | | }).then(async (val) => { |
| | | if (!val) return; |
| | | const res = await DeleteHistoryGroups({ |
| | | history_group_id: id, |
| | | }); |
| | | if (!res?.json_ok) return; |
| | | const foundIndex = this.data.chatRoomList.findIndex((item) => item.id === id); |
| | | this.data.chatRoomList.splice(foundIndex, 1); |
| | | if (this.data.chatRoomList.length === 0) { |
| | | await this.newChatRoomClick(); |
| | | } else { |
| | | this.setActiveChatRoom(this.data.chatRoomList[0]); |
| | | this.setData({ |
| | | chatRoomList: this.data.chatRoomList |
| | | }) |
| | | } |
| | | |
| | | }) |
| | | }, |
| | | |
| | | // 聊天室图标点击 |
| | | chatRoomListClick() { |
| | | this.setData({ |
| | | drawerIsShow: true, |
| | | }) |
| | | }, |
| | | drawerCloseClick() { |
| | | this.setData({ |
| | | drawerIsShow: false, |
| | | }) |
| | | }, |
| | | onLoad(option) { |
| | | const isPassed = checkAuth(); |
| | | if (!isPassed) return; |
| | | this.getHistoryGroupData(); |
| | | this.getSampleList(); |
| | | |
| | | }, |
| | | onShow() { |
| | | this.setData({ |
| | | userName: getStorage('username') |
| | | }) |
| | | }, |
| | | |
| | | async onRouteDone() { |
| | | const sectionAId = app.globalData.sectionAId; |
| | | |
| | | if (!sectionAId) { |
| | | return; |
| | | } |
| | | this.setData( |
| | | { |
| | | section_a_id: sectionAId |
| | | } |
| | | ) |
| | | if (!this.data.activeChatRoom.isInitial) { |
| | | try { |
| | | |
| | | await this.newChatRoomClick(false) |
| | | } finally { |
| | | wx.hideLoading(); |
| | | } |
| | | } |
| | | this.setData({ |
| | | sendText: app.globalData.sectionB.section_title |
| | | }) |
| | | |
| | | this.sendText(); |
| | | app.globalData.sectionAId = ''; |
| | | app.globalData.sectionB = null; |
| | | }, |
| | | onShareAppMessage() { |
| | | return wx.$_.defaults(SHARE_CONFIG, { |
| | | // path: getCurrentUrl(), |
| | | }) |
| | | } |
| | | |
| | | |
| | | // pageLifetimes: { |
| | | // show() { |
| | | // if (typeof this.getTabBar === 'function' && |
| | | // this.getTabBar()) { |
| | | // this.getTabBar().setData({ |
| | | // selected: 0 |
| | | // }) |
| | | // } |
| | | // } |
| | | // } |
| | | |
| | | |
| | | |
| | | }) |