Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
131 changes: 67 additions & 64 deletions ui/src/components/ai-chat/KnowledgeSource.vue
Original file line number Diff line number Diff line change
@@ -1,66 +1,71 @@
<template>
<div class="flex align-center mt-16" v-if="!isWorkFlow(props.type)">
<span class="mr-4 color-secondary">{{ $t('chat.KnowledgeSource.title') }}</span>
<el-divider direction="vertical" />
<el-button type="primary" class="mr-8" link @click="openParagraph(data)">
<AppIcon iconName="app-reference-outlined" class="mr-4"></AppIcon>
{{ $t('chat.KnowledgeSource.referenceParagraph') }}
{{ data.paragraph_list?.length || 0 }}</el-button
>
</div>
<div class="mt-8" v-if="!isWorkFlow(props.type)">
<el-row :gutter="8" v-if="uniqueParagraphList?.length">
<template v-for="(item, index) in uniqueParagraphList" :key="index">
<el-col :span="12" class="mb-8">
<el-card shadow="never" class="file-List-card" data-width="40">
<div class="flex-between">
<div class="flex">
<img :src="getImgUrl(item && item?.document_name)" alt="" width="20" />
<div class="ml-4 ellipsis-1" :title="item?.document_name" v-if="!item.source_url">
<p>{{ item && item?.document_name }}</p>
</div>
<div class="ml-8" v-else>
<a
:href="getNormalizedUrl(item?.source_url)"
target="_blank"
class="ellipsis"
:title="item?.document_name?.trim()"
>
<span :title="item?.document_name?.trim()">{{ item?.document_name }}</span>
</a>
<div class="chat-knowledge-source">
<div class="flex align-center mt-16" v-if="!isWorkFlow(props.type)">
<span class="mr-4 color-secondary">{{ $t('chat.KnowledgeSource.title') }}</span>
<el-divider direction="vertical" />
<el-button type="primary" class="mr-8" link @click="openParagraph(data)">
<AppIcon iconName="app-reference-outlined" class="mr-4"></AppIcon>
{{ $t('chat.KnowledgeSource.referenceParagraph') }}
{{ data.paragraph_list?.length || 0 }}</el-button
>
</div>
<div class="mt-8" v-if="!isWorkFlow(props.type)">
<el-row :gutter="8" v-if="uniqueParagraphList?.length">
<template v-for="(item, index) in uniqueParagraphList" :key="index">
<el-col :span="12" class="mb-8">
<el-card shadow="never" class="file-List-card" data-width="40">
<div class="flex-between">
<div class="flex">
<img :src="getImgUrl(item && item?.document_name)" alt="" width="20" />
<div class="ml-4 ellipsis-1" :title="item?.document_name" v-if="!item.source_url">
<p>{{ item && item?.document_name }}</p>
</div>
<div class="ml-8" v-else>
<a
:href="getNormalizedUrl(item?.source_url)"
target="_blank"
class="ellipsis"
:title="item?.document_name?.trim()"
>
<span :title="item?.document_name?.trim()">{{ item?.document_name }}</span>
</a>
</div>
</div>
</div>
</div>
</el-card>
</el-col>
</template>
</el-row>
</div>

<div
class="border-t color-secondary flex-between mt-12"
style="padding-top: 12px; padding-bottom: 8px"
>
<div>
<span class="mr-8">
{{ $t('chat.KnowledgeSource.consume') }}: {{ data?.message_tokens + data?.answer_tokens }}
</span>
<span> {{ $t('chat.KnowledgeSource.consumeTime') }}: {{ data?.run_time?.toFixed(2) }} s</span>
</el-card>
</el-col>
</template>
</el-row>
</div>
<el-button
v-if="isWorkFlow(props.type)"
type="primary"
link
@click="openExecutionDetail(data.execution_details)"
>
<el-icon class="mr-4"><Document /></el-icon>
{{ $t('chat.executionDetails.title') }}</el-button

<div
class="execution-details border-t color-secondary flex-between mt-12"
style="padding-top: 12px; padding-bottom: 8px"
>
<div>
<span class="mr-8">
{{ $t('chat.KnowledgeSource.consume') }}: {{ data?.message_tokens + data?.answer_tokens }}
</span>
<span>
{{ $t('chat.KnowledgeSource.consumeTime') }}: {{ data?.run_time?.toFixed(2) }} s</span
>
</div>
<el-button
v-if="isWorkFlow(props.type)"
type="primary"
link
@click="openExecutionDetail(data.execution_details)"
style="padding: 0;"
>
<el-icon class="mr-4"><Document /></el-icon>
{{ $t('chat.executionDetails.title') }}</el-button
>
</div>
<!-- 知识库引用 dialog -->
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
<!-- 执行详情 dialog -->
<ExecutionDetailDialog ref="ExecutionDetailDialogRef" />
</div>
<!-- 知识库引用 dialog -->
<ParagraphSourceDialog ref="ParagraphSourceDialogRef" />
<!-- 执行详情 dialog -->
<ExecutionDetailDialog ref="ExecutionDetailDialogRef" />
</template>
<script setup lang="ts">
import { computed, ref } from 'vue'
Expand Down Expand Up @@ -107,13 +112,11 @@ const uniqueParagraphList = computed(() => {
})
</script>
<style lang="scss" scoped>
.source_dataset-button {
background: var(--app-text-color-light-1);
border: 1px solid #ffffff;
&:hover {
border: 1px solid var(--el-color-primary);
background: var(--el-color-primary-light-9);
color: var(--el-text-color-primary);
@media only screen and (max-width: 430px) {
.chat-knowledge-source {
.execution-details {
display: block;
}
}
}
</style>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are several issues and optimizations you can address in your provided code:

Issues:

  1. CSS Media Query:

    • The media query is targeting screens with a maximum width of 430px, which might not be universal enough to cover all devices. Consider adjusting it based on your application's design needs.
  2. Unused Variables uniqueParagraphList:

    • This variable seems unused since neither data.paragraph_list?.length nor uniqueParagraphList?.length is directly utilized anywhere else in the template or the script.
  3. Unnecessary Class Definitions:

    • In some parts, there are unnecessary class definitions like .source_dataset-button, where styles could be combined or more efficiently applied using CSS variables instead of inline classes.
  4. Inline Styles in Buttons/Links:

    • Inline padding styles in buttons and links (<el-button>s) do not contribute much value. They should ideally be handled via CSS styling or less hardcoded.
  5. Variable Names:

    • Variable names like props, computed, etc., don't provide descriptive context about their purpose. Renaming them can improve readability and maintainability.

Optimization Suggestions:

  1. Merge Similar Code Blocks:

    • Some sections look similar (e.g., handling document icons and linking), consider creating reusable components or functions to avoid repetition.
  2. Dynamic Classes:

    • Use Vue’s dynamic class binding features to simplify CSS management without resorting to multiple conditionals.
  3. Remove Unused Components:

    • If no component instance is created (like <ParagraphSourceDialog />) at runtime, ensure its removal from the template or remove the associated setup logic.

Here's an example of how you might refactor these suggestions:

Revised Template

<template>
  <div class="chat-knowledge-source">
    <div v-if="!isWorkFlow(props.type)" class="flex align-center mt-16">
      <span class="mr-4 color-secondary">{{ $t('chat.KnowledgeSource.title') }}</span>
      <el-divider direction="vertical" />
      <el-button class="text-primary mr-8 hover:bg-primary hover:text-white" @click="openParagraph(data)">
        <AppIcon iconName="app-reference-outlined" />
        <span>{{ $t('chat.KnowledgeSource.referenceParagraph') }} {{ data.paragraph_list.length || 0 }}</span>
      </el-button>
    </div>

    <div class="mt-8 mb-12" v-if="!isWorkFlow(props.type)">
      <ElRow :gutter="8" v-if="displayUniqueParagraphList">
        <ElCol :span="12" class="mb-8" v-for="(item, index) in uniqueParagraphList" :key="index">
          <ElCard shadow="never" class="file-list-card">
            <DivWrapper imgSrc="getImgUrl(item.document_name)">
              <ContentEllipsis text="item.document_name" url="getNormalizedUrl(item.source_url)" titleText="docTitle" />
            </DivWrapper>
          </ElCard>
        </ElCol>
      </ElRow>
    </div>

    <div class="border-t color-secondary flex items-center mt-12 p-y-8">
      <span class="mr-8">Consumed Tokens: {{ totalTokens }}</span>
      <span>Tokens Consumption Time: {{ formattedRunTime }}</span>
      
      <Divider dashed />

      <div v-if="isWorkFlow(props.type)">
        <ButtonPrimary variant="link" iconLeft="Document" @click="openExecutionDetail(data.execution_details)">
          Execution Details
        </ButtonPrimary>
      </div>
    </div>

    <ParagraphSourceDialog ref="paragraphSourceDialogRef" />
    <ExecutionDetailDialog ref="executionDetailDialogRef" v-model:visible="detailsVisible" />
  </div>
</template>

Improved Script Setup

<script setup lang="ts">
import { computed, ref } from "vue";
import AppIcon from "@/components/AppIcon.vue";
import ElTooltip from "@element-plus/el-tooltip";
import ElTag from "@element-plus/el-tag";

const props = defineProps({
  type: String,
});

const openParagraph = async (payload: unknown): Promise<void> => {};

const detailsVisible = ref(false);

const uniqueParagraphList = computed(() => []);
// Calculate total tokens and run time if needed

function getImgUrl(docName: string | null | undefined): string {
}

const getNormalizedUrl = (url: string | null | undefined): string => "";

const displayUniqueParagraphList = computed(() => !isEmpty(uniqueParagraphList));

async function openExecutionDetail(data: Record<string, any>): Promise<void> {};
</script>

By making these changes, you enhance the reusability, efficiency, and manageability of your codebase while maintaining a consistent interface and style across different views. You may also want to further optimize specific sections like image loading, navigation paths, or tooltips to suit better performance requirements under various conditions.

8 changes: 5 additions & 3 deletions ui/src/components/ai-chat/component/answer-content/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -34,9 +34,11 @@
{{ $t('chat.tip.answerLoading') }} <span class="dotting"></span>
</p>
<!-- 知识来源 -->
<div v-if="showSource(chatRecord) && index === chatRecord.answer_text_list.length - 1">
<KnowledgeSource :data="chatRecord" :type="application.type" />
</div>
<KnowledgeSource
:data="chatRecord"
:type="application.type"
v-if="showSource(chatRecord) && index === chatRecord.answer_text_list.length - 1"
/>
</el-card>
</div>
</template>
Expand Down
Loading