wujingjing
2024-09-10 312dd4fbc040b0f413c9b27149613d6f22c949a0
src/components/chat/Chat.vue
@@ -36,23 +36,43 @@
                                          v-for="fixItem in item.content.origin.err_json.fix_question?.values"
                                          :key="fixItem"
                                          class="bg-gray-200 p-3 hover:bg-[#c5e0ff] hover:text-[#1c86ff] cursor-pointer rounded-lg"
                                          @click="fixQuestionClick(fixItem)"
                                          @click="fixQuestionClick(fixItem, item.content.origin)"
                                       >
                                          {{ fixItem.title }}
                                       </div>
                                    </div>
                                 </div>
                              </div>
                              <component v-else :is="answerTypeMapCom[item.content.type]" :data="item.content.values" :originData="item" />
                              <template v-else>
                                 <component :is="answerTypeMapCom[item.content.type]" :data="item.content.values" :originData="item" />
                                 <div
                                    v-if="item.role === RoleEnum.assistant && item.content.origin?.ext_call_list"
                                    class="flex font-bold items-center mt-6"
                                 >
                                    <div class="flex-0 mb-auto -mr-4">关联功能:</div>
                                    <div class="space-x-5 flex flex-wrap">
                                       <div
                                          v-for="callItem in item.content.origin?.ext_call_list"
                                          :key="callItem.call_ext_id"
                                          @click="relativeQueryClick(callItem)"
                                          class="cursor-pointer hover:underline first-of-type:ml-5"
                                       >
                                          {{ callItem.question }}
                                       </div>
                                    </div>
                                 </div>
                              </template>
                           </div>
                           <!-- 操作 -->
                           <div v-if="item.role === RoleEnum.assistant" class="absolute flex items-center right-0 mr-4 mt-2 space-x-2">
                              <div
                                 class="flex items-center justify-center size-[15px]"
                                 v-if="item.content?.type === AnswerType.Text || item.content?.type === AnswerType.Knowledge"
                              >
                                 <i
                                    class="p-2 ywicon icon-copy cursor-pointer hover:text-[#0284ff] hover:!text-[18px]"
                                    class="p-2 ywifont ywicon-copy cursor-pointer hover:text-[#0284ff] hover:!text-[18px]"
                                    @click="copyClick(item)"
                                 />
                              </div>
@@ -60,14 +80,14 @@
                                 <div class="flex items-center justify-center size-[15px]">
                                    <i
                                       :class="{ 'text-[#0284ff]': item.state === AnswerState.Like }"
                                       class="p-2 ywicon icon-dianzan cursor-pointer hover:text-[#0284ff] font-medium hover:!text-[18px]"
                                       class="p-2 ywifont ywicon-dianzan cursor-pointer hover:text-[#0284ff] font-medium hover:!text-[18px]"
                                       @click="likeClick(item)"
                                    />
                                 </div>
                                 <div class="flex items-center justify-center size-[15px]">
                                    <i
                                       :class="{ 'text-[#0284ff]': item.state === AnswerState.Unlike }"
                                       class="p-2 ywicon icon-buzan cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
                                       class="p-2 ywifont ywicon-buzan cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
                                       @click="unLikeClick(item)"
                                    />
                                 </div>
@@ -75,7 +95,7 @@
                              <div class="flex items-center justify-center size-[15px] relative">
                                 <i
                                    class="p-2 ywicon icon-wentifankui cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
                                    class="p-2 ywifont ywicon-wentifankui cursor-pointer hover:text-[#0284ff] !text-[13px] hover:!text-[15px]"
                                    @click="
                                       ($event) =>
                                          feedbackClick(
@@ -99,7 +119,7 @@
                           </div>
                        </div>
                        <Loding v-else class="w-fit" :process="process" />
                        <Loding v-if="isTalking && index === messageList.length - 1" class="w-fit" :process="process" />
                     </div>
                  </div>
               </div>
@@ -147,7 +167,7 @@
import { useScrollToBottom } from './hooks/useScrollToBottom';
import type { ChatContent } from './model/types';
import { AnswerState, AnswerType, RoleEnum, answerTypeMapCom, roleImageMap, type ChatMessage } from './model/types';
import { GetHistoryAnswer, QueryHistoryDetail, QuestionAi } from '/@/api/ai/chat';
import { GetHistoryAnswer, QueryHistoryDetail, QuestionAi, extCallQuery } from '/@/api/ai/chat';
import PlayBar from '/@/components/chat/components/playBar/PlayBar.vue';
import CustomDrawer from '/@/components/drawer/CustomDrawer.vue';
import router from '/@/router';
@@ -230,30 +250,58 @@
};
const { clearQueryProcess, process, processId, queryProcess } = useQueryProcess();
const DEFAULT_SECTION_A_ID = 'knowledge_base';
let questionRes = null;
let finalCalcSectionAId = null;
const questionAi = async (text) => {
   if (!currentSectionId) {
      ElMessage.warning('发送失败,未确定应用场景!');
   }
   processId.value = uuidv4();
   let judgeParams = null;
   if (!preQuestion.value) {
      // const aiContent = computedMessageList.value.filter((item) => item.role === RoleEnum.assistant);
      // const lastQuestion = aiContent[aiContent.length - 2]?.content?.origin?.question;
      // judgeParams = lastQuestion
      //    ? {
      //          prev_question: lastQuestion,
      //      }
      //    : {};
         // 正常回答暂时不采用
      judgeParams = {};
   } else {
      judgeParams = {
         prev_question: preQuestion.value,
      };
   }
   let currentSectionAId = '';
   if (activeSectionAId.value) {
      currentSectionAId = activeSectionAId.value;
      activeSectionAId.value = '';
   } else {
      const lastSectionAItem = _.findLast(computedMessageList.value as any, (item) => item.role === RoleEnum.assistant && !!item.sectionAId);
      currentSectionAId = lastSectionAItem?.sectionAId ?? DEFAULT_SECTION_A_ID;
   }
   finalCalcSectionAId = currentSectionAId;
   const params = {
      process_id: processId.value,
      question: text,
      // FIXME: 暂时这样
      section_a_id: currentSectionId,
      section_a_id: currentSectionAId,
      history_group_id: currentRouteId,
      raw_mode: roomConfig.value?.[currentRouteId]?.isAnswerByLLM ?? false,
      next_chat: isNextChat.value,
      ...judgeParams,
   } as any;
   if (currentSampleId) {
      params.sample_id = currentSampleId;
      currentSampleId = '';
   }
   if (currentLLMId) {
      params.llm_id = currentLLMId;
   }
   // if (currentLLMId) {
   //    params.llm_id = currentLLMId;
   // }
   clearQueryProcess();
   queryProcess();
   const res = await QuestionAi(params).finally(() => {
@@ -270,8 +318,7 @@
      values: '',
   });
let currentSectionId = null;
let currentSampleId = null;
let currentSampleId = '';
let currentLLMId = null;
@@ -281,8 +328,8 @@
   });
};
const sendChatMessage = async (content: ChatContent = messageContent.value, cb?: any) => {
   if (!content?.values) return;
const sendChatMessage = async (content: ChatContent = messageContent.value, cb?: any, isCallExtParams?: any) => {
   if (!content?.values || isTalking.value) return;
   const isNewChat = messageList.value.length === 0;
   if (isNewChat) {
      if (activeSampleId.value) {
@@ -293,9 +340,7 @@
         currentLLMId = activeLLMId.value;
      }
      if (activeSectionAId.value) {
         currentSectionId = activeSectionAId.value;
      }
   }
   let resMsgContent: ChatContent = null;
@@ -310,8 +355,14 @@
      // 出现回复,置空出现等待动画
      messageList.value.push(assistantItem);
      if (isCallExtParams) {
         const extRes = await extCallQuery(isCallExtParams);
         questionRes = extRes;
         resMsgContent = parseContent(extRes);
      } else {
         resMsgContent = await questionAi(content.values);
      }
      resMsgContent = await questionAi(content.values);
      if (isNewChat) {
         const firstResCb = getRoomConfig(currentRouteId, 'firstResCb');
         firstResCb?.(resMsgContent);
@@ -319,7 +370,9 @@
         cb?.(resMsgContent);
      }
      userItem.historyId = questionRes.history_id;
      userItem.content.values = questionRes?.question ?? userItem.content.values;
      assistantItem.historyId = questionRes.history_id;
      assistantItem.sectionAId = finalCalcSectionAId;
      appendLastMessageContent(resMsgContent);
   } catch (error: any) {
      // appendLastMessageContent({
@@ -355,13 +408,19 @@
         },
      } as ChatMessage;
   });
   currentSectionId = res?.details?.[0]?.section_a_id;
   currentSampleId = res?.details?.[0]?.sample_id;
   const resList = await Promise.all((res.details ?? []).map((item) => getAnswerById(item.history_id)));
   let i = 0;
   const sectionAIdMap = new Map();
   const resList = 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;
      const userMsg = messageList.value[insertIndex - 1];
      userMsg.content.values = item?.answer?.question ??userMsg.content.values;
      messageList.value.splice(
         insertIndex,
         0,
@@ -372,6 +431,8 @@
                  role: RoleEnum.assistant,
                  content: parseContent(item.answer),
                  state: item.answer_state,
                  sectionAId: sectionAIdMap.get(item.answer.history_id),
              }
      );
      i++;
@@ -392,6 +453,24 @@
   displayMessageList: computedMessageList,
});
//#region ====================== 关联查询 ======================
const relativeQueryClick = async (val) => {
   sendChatMessage(
      {
         type: AnswerType.Text,
         values: val.question,
      },
      undefined,
      {
         history_group_id: currentRouteId,
         question: val.question,
         call_ext_id: val.call_ext_id,
         call_ext_args: val.agrs ? JSON.stringify(val.agrs) : null,
      }
   );
};
//#endregion
const {
   copyClick,
   likeClick,
@@ -404,7 +483,7 @@
   feedbackClick,
   askMoreClick,
   fixQuestionClick,
   isNextChat,
   preQuestion,
   showFixQuestion,
   showAskMore,
} = useAssistantContentOpt({