mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
Merge branch 'main' of https://github.com/maxkb-dev/maxkb
This commit is contained in:
commit
5974bd7986
|
|
@ -14,8 +14,8 @@ class BaseDocumentExtractNode(IDocumentExtractNode):
|
|||
get_buffer = FileBufferHandle().get_buffer
|
||||
|
||||
self.context['document_list'] = document
|
||||
content = ''
|
||||
splitter = '\n-----------------------------------\n'
|
||||
content = []
|
||||
splitter = '\n`-----------------------------------`\n'
|
||||
if document is None:
|
||||
return NodeResult({'content': content}, {})
|
||||
|
||||
|
|
@ -29,10 +29,10 @@ class BaseDocumentExtractNode(IDocumentExtractNode):
|
|||
# 回到文件头
|
||||
buffer.seek(0)
|
||||
file_content = split_handle.get_content(buffer)
|
||||
content += splitter + '## ' + doc['name'] + '\n' + file_content
|
||||
content.append( '## ' + doc['name'] + '\n' + file_content)
|
||||
break
|
||||
|
||||
return NodeResult({'content': content}, {})
|
||||
return NodeResult({'content': splitter.join(content)}, {})
|
||||
|
||||
def get_details(self, index: int, **kwargs):
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -77,5 +77,6 @@ class BaseStartStepNode(IStarNode):
|
|||
'status': self.status,
|
||||
'err_message': self.err_message,
|
||||
'image_list': self.context.get('image'),
|
||||
'document_list': self.context.get('document'),
|
||||
'global_fields': global_fields
|
||||
}
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@ from common.util.field_message import ErrMessage
|
|||
from common.util.file_util import get_file_content
|
||||
from common.util.lock import try_lock, un_lock
|
||||
from dataset.models import Document, Problem, Paragraph, ProblemParagraphMapping
|
||||
from dataset.serializers.common_serializers import get_embedding_model_id_by_dataset_id
|
||||
from dataset.serializers.common_serializers import get_embedding_model_id_by_dataset_id, update_document_char_length
|
||||
from dataset.serializers.paragraph_serializers import ParagraphSerializers
|
||||
from embedding.task import embedding_by_paragraph, embedding_by_paragraph_list
|
||||
from setting.models import Model
|
||||
|
|
@ -620,6 +620,7 @@ class ChatRecordSerializer(serializers.Serializer):
|
|||
# 插入关联问题
|
||||
problem_paragraph_mapping.save()
|
||||
chat_record.improve_paragraph_id_list.append(paragraph.id)
|
||||
update_document_char_length(document_id)
|
||||
# 添加标注
|
||||
chat_record.save()
|
||||
return ChatRecordSerializerModel(chat_record).data, paragraph.id, dataset_id
|
||||
|
|
@ -718,5 +719,6 @@ class ChatRecordSerializer(serializers.Serializer):
|
|||
|
||||
# 批量保存聊天记录
|
||||
ChatRecord.objects.bulk_update(chat_record_list, ['improve_paragraph_id_list'])
|
||||
update_document_char_length(document_id)
|
||||
|
||||
return paragraph_ids, dataset_id
|
||||
|
|
|
|||
|
|
@ -41,4 +41,4 @@ class CsvSplitHandle(BaseParseTableHandle):
|
|||
return buffer.decode(detect(buffer)['encoding'])
|
||||
except BaseException as e:
|
||||
max_kb.error(f'csv split handle error: {e}')
|
||||
return [{'name': file.name, 'paragraphs': []}]
|
||||
return f'error: {e}'
|
||||
|
|
@ -63,21 +63,26 @@ class XlsSplitHandle(BaseParseTableHandle):
|
|||
|
||||
def get_content(self, file):
|
||||
# 打开 .xls 文件
|
||||
workbook = xlrd.open_workbook(file_contents=file.read(), formatting_info=True)
|
||||
sheets = workbook.sheets()
|
||||
md_tables = ''
|
||||
for sheet in sheets:
|
||||
try:
|
||||
workbook = xlrd.open_workbook(file_contents=file.read(), formatting_info=True)
|
||||
sheets = workbook.sheets()
|
||||
md_tables = ''
|
||||
for sheet in sheets:
|
||||
|
||||
# 获取表头和内容
|
||||
headers = sheet.row_values(0)
|
||||
data = [sheet.row_values(row_idx) for row_idx in range(1, sheet.nrows)]
|
||||
# 获取表头和内容
|
||||
headers = sheet.row_values(0)
|
||||
data = [sheet.row_values(row_idx) for row_idx in range(1, sheet.nrows)]
|
||||
|
||||
# 构建 Markdown 表格
|
||||
md_table = '| ' + ' | '.join(headers) + ' |\n'
|
||||
md_table += '| ' + ' | '.join(['---'] * len(headers)) + ' |\n'
|
||||
for row in data:
|
||||
# 将每个单元格中的内容替换换行符为 <br> 以保留原始格式
|
||||
md_table += '| ' + ' | '.join([str(cell).replace('\n', '<br>') if cell else '' for cell in row]) + ' |\n'
|
||||
md_tables += md_table + '\n\n'
|
||||
# 构建 Markdown 表格
|
||||
md_table = '| ' + ' | '.join(headers) + ' |\n'
|
||||
md_table += '| ' + ' | '.join(['---'] * len(headers)) + ' |\n'
|
||||
for row in data:
|
||||
# 将每个单元格中的内容替换换行符为 <br> 以保留原始格式
|
||||
md_table += '| ' + ' | '.join(
|
||||
[str(cell).replace('\n', '<br>') if cell else '' for cell in row]) + ' |\n'
|
||||
md_tables += md_table + '\n\n'
|
||||
|
||||
return md_tables
|
||||
return md_tables
|
||||
except Exception as e:
|
||||
max_kb.error(f'excel split handle error: {e}')
|
||||
return f'error: {e}'
|
||||
|
|
|
|||
|
|
@ -75,28 +75,32 @@ class XlsxSplitHandle(BaseParseTableHandle):
|
|||
|
||||
|
||||
def get_content(self, file):
|
||||
# 加载 Excel 文件
|
||||
workbook = load_workbook(file)
|
||||
md_tables = ''
|
||||
# 如果未指定 sheet_name,则使用第一个工作表
|
||||
for sheetname in workbook.sheetnames:
|
||||
sheet = workbook[sheetname] if sheetname else workbook.active
|
||||
try:
|
||||
# 加载 Excel 文件
|
||||
workbook = load_workbook(file)
|
||||
md_tables = ''
|
||||
# 如果未指定 sheet_name,则使用第一个工作表
|
||||
for sheetname in workbook.sheetnames:
|
||||
sheet = workbook[sheetname] if sheetname else workbook.active
|
||||
|
||||
# 获取工作表的所有行
|
||||
rows = list(sheet.iter_rows(values_only=True))
|
||||
if not rows:
|
||||
continue
|
||||
# 获取工作表的所有行
|
||||
rows = list(sheet.iter_rows(values_only=True))
|
||||
if not rows:
|
||||
continue
|
||||
|
||||
# 提取表头和内容
|
||||
headers = rows[0]
|
||||
data = rows[1:]
|
||||
# 提取表头和内容
|
||||
headers = rows[0]
|
||||
data = rows[1:]
|
||||
|
||||
# 构建 Markdown 表格
|
||||
md_table = '| ' + ' | '.join(headers) + ' |\n'
|
||||
md_table += '| ' + ' | '.join(['---'] * len(headers)) + ' |\n'
|
||||
for row in data:
|
||||
md_table += '| ' + ' | '.join(
|
||||
[str(cell).replace('\n', '<br>') if cell is not None else '' for cell in row]) + ' |\n'
|
||||
# 构建 Markdown 表格
|
||||
md_table = '| ' + ' | '.join(headers) + ' |\n'
|
||||
md_table += '| ' + ' | '.join(['---'] * len(headers)) + ' |\n'
|
||||
for row in data:
|
||||
md_table += '| ' + ' | '.join(
|
||||
[str(cell).replace('\n', '<br>') if cell is not None else '' for cell in row]) + ' |\n'
|
||||
|
||||
md_tables += md_table + '\n\n'
|
||||
return md_tables
|
||||
md_tables += md_table + '\n\n'
|
||||
return md_tables
|
||||
except Exception as e:
|
||||
max_kb.error(f'excel split handle error: {e}')
|
||||
return f'error: {e}'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M4.77756 1.66699C4.28664 1.66699 3.88867 2.06496 3.88867 2.55588V19.4448C3.88867 19.9357 4.28664 20.3337 4.77756 20.3337H17.222C17.7129 20.3337 18.1109 19.9357 18.1109 19.4448V6.3069C18.1109 6.19036 18.0651 6.07847 17.9834 5.99536L13.8597 1.79989C13.7761 1.71488 13.6619 1.66699 13.5427 1.66699H4.77756ZM7.04915 9.02062C7.04915 8.77516 7.24814 8.57617 7.4936 8.57617H14.5059C14.7514 8.57617 14.9504 8.77516 14.9504 9.02062V9.74789C14.9504 9.99335 14.7514 10.1923 14.5059 10.1923H7.4936C7.24814 10.1923 7.04915 9.99335 7.04915 9.74789V9.02062ZM7.04915 13.061C7.04915 12.8156 7.24814 12.6166 7.4936 12.6166H10.5553C10.8008 12.6166 10.9998 12.8156 10.9998 13.061V13.7883C10.9998 14.0338 10.8008 14.2327 10.5553 14.2327H7.4936C7.24814 14.2327 7.04915 14.0338 7.04915 13.7883V13.061Z" fill="white"/>
|
||||
<path opacity="0.5" d="M13.6665 1.68457C13.7391 1.70561 13.8058 1.74502 13.8597 1.7999L17.9835 5.99537C18.0172 6.02971 18.0449 6.06897 18.0657 6.11145H14.6755C14.1183 6.11145 13.6665 5.6597 13.6665 5.10244V1.68457Z" fill="#3370FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
|
|
@ -0,0 +1,5 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.3335 3.33333C5.3335 2.59695 5.93045 2 6.66683 2H19.8146C19.9934 2 20.1647 2.07183 20.29 2.19934L26.4756 8.49255C26.5982 8.61722 26.6668 8.78505 26.6668 8.95987V28.6667C26.6668 29.403 26.0699 30 25.3335 30H6.66683C5.93045 30 5.3335 29.403 5.3335 28.6667V3.33333Z" fill="#3370FF"/>
|
||||
<path d="M20 2.02637C20.1089 2.05793 20.2089 2.11704 20.2899 2.19936L26.4755 8.49256C26.5261 8.54408 26.5675 8.60297 26.5987 8.66668H21.5135C20.6776 8.66668 20 7.98906 20 7.15317V2.02637Z" fill="#2B5FD9"/>
|
||||
<path d="M10.7636 13.5757H20.8727C20.9932 13.5757 21.0909 13.6734 21.0909 13.7939V14.8121C21.0909 14.9326 20.9932 15.0303 20.8727 15.0303H10.7636C10.6431 15.0303 10.5454 14.9326 10.5454 14.8121V13.7939C10.5454 13.6734 10.6431 13.5757 10.7636 13.5757ZM10.7636 17.9394H20.8727C20.9932 17.9394 21.0909 18.0371 21.0909 18.1576V19.1757C21.0909 19.2962 20.9932 19.3939 20.8727 19.3939H10.7636C10.6431 19.3939 10.5454 19.2962 10.5454 19.1757V18.1576C10.5454 18.0371 10.6431 17.9394 10.7636 17.9394ZM10.7636 22.303H16.1454C16.2659 22.303 16.3636 22.4007 16.3636 22.5212V23.5394C16.3636 23.6599 16.2659 23.7576 16.1454 23.7576H10.7636C10.6431 23.7576 10.5454 23.6599 10.5454 23.5394V22.5212C10.5454 22.4007 10.6431 22.303 10.7636 22.303Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
|
|
@ -0,0 +1,6 @@
|
|||
<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M5.3335 3.33333C5.3335 2.59695 5.93045 2 6.66683 2H19.724C19.9008 2 20.0704 2.07024 20.1954 2.19526L26.4716 8.47141C26.5966 8.59643 26.6668 8.766 26.6668 8.94281V28.6667C26.6668 29.403 26.0699 30 25.3335 30H6.66683C5.93045 30 5.3335 29.403 5.3335 28.6667V3.33333Z" fill="#14C0FF"/>
|
||||
<path d="M20 2.05988C20.072 2.09264 20.1383 2.13825 20.1953 2.19526L26.4714 8.4714C26.5284 8.52841 26.574 8.59467 26.6068 8.66666H21.3333C20.597 8.66666 20 8.06971 20 7.33333V2.05988Z" fill="#11A3D9"/>
|
||||
<path d="M11.3335 16C12.4381 16 13.3335 15.1046 13.3335 14C13.3335 12.8954 12.4381 12 11.3335 12C10.2289 12 9.3335 12.8954 9.3335 14C9.3335 15.1046 10.2289 16 11.3335 16Z" fill="white"/>
|
||||
<path d="M22.2785 14.9317C22.4218 14.7884 22.6668 14.8899 22.6668 15.0925V24.0645C22.6668 24.1901 22.565 24.2919 22.4394 24.2919H13.4674L13.4587 24.2918H9.56142C9.35877 24.2918 9.25728 24.0468 9.40058 23.9035L14.366 18.938C14.4549 18.8492 14.5989 18.8492 14.6877 18.938L16.48 20.7302L22.2785 14.9317Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -0,0 +1,4 @@
|
|||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M1.99967 2C1.63149 2 1.33301 2.29848 1.33301 2.66667V13.3333C1.33301 13.7015 1.63149 14 1.99967 14H13.9997C14.3679 14 14.6663 13.7015 14.6663 13.3333V2.66667C14.6663 2.29848 14.3679 2 13.9997 2H1.99967ZM13.333 3.33328V10.0001L11.9021 8.56907C11.7719 8.43893 11.5608 8.43893 11.4306 8.56907L9.56874 10.431C9.43854 10.5612 9.22747 10.5612 9.09727 10.431L5.56871 6.9024C5.43853 6.77227 5.22748 6.77227 5.09731 6.9024L2.66634 9.3334V3.33328H13.333Z" fill="white"/>
|
||||
<path opacity="0.5" d="M10.333 5.33333C10.333 5.14924 10.4823 5 10.6663 5H11.6663C11.8504 5 11.9997 5.14924 11.9997 5.33333V6.33333C11.9997 6.51743 11.8504 6.66667 11.6663 6.66667H10.6663C10.4823 6.66667 10.333 6.51743 10.333 6.33333V5.33333Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 832 B |
|
|
@ -135,8 +135,7 @@
|
|||
v-if="
|
||||
item.type == WorkflowType.AiChat ||
|
||||
item.type == WorkflowType.Question ||
|
||||
item.type == WorkflowType.Application ||
|
||||
item.type == WorkflowType.ImageUnderstandNode
|
||||
item.type == WorkflowType.Application
|
||||
"
|
||||
>
|
||||
<div
|
||||
|
|
@ -175,7 +174,7 @@
|
|||
</div>
|
||||
<div class="card-never border-r-4 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ item.type == WorkflowType.Application ? '应用回答' : 'AI 回答' }}
|
||||
{{ item.type == WorkflowType.Application ? '参数输出' : 'AI 回答' }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
|
|
@ -313,6 +312,103 @@
|
|||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<!-- 表单收集 -->
|
||||
<template v-if="item.type === WorkflowType.FormNode">
|
||||
<div class="card-never border-r-4">
|
||||
<h5 class="p-8-12">参数输入</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<div v-for="(f, i) in item.form_field_list" :key="i" class="mb-8">
|
||||
<span class="color-secondary">{{ f.label.label }}:</span>
|
||||
{{ item.form_data[f.field] }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
<!-- 图片理解 -->
|
||||
<template v-if="item.type == WorkflowType.ImageUnderstandNode">
|
||||
<div
|
||||
class="card-never border-r-4"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">角色设定 (System)</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
{{ item.system || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
class="card-never border-r-4 mt-8"
|
||||
v-if="item.type !== WorkflowType.Application"
|
||||
>
|
||||
<h5 class="p-8-12">历史记录</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<template v-if="item.history_message?.length > 0">
|
||||
<p
|
||||
class="mt-4 mb-4"
|
||||
v-for="(history, historyIndex) in item.history_message"
|
||||
:key="historyIndex"
|
||||
>
|
||||
<span class="color-secondary mr-4">{{ history.role }}:</span>
|
||||
|
||||
<span v-if="Array.isArray(history.content)">
|
||||
<template v-for="(h, i) in history.content" :key="i">
|
||||
<el-image
|
||||
v-if="h.type === 'image_url'"
|
||||
:src="h.image_url.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-4"
|
||||
/>
|
||||
<span v-else>{{ h.text }}</span>
|
||||
</template>
|
||||
</span>
|
||||
|
||||
<span v-else>{{ history.content }}</span>
|
||||
</p>
|
||||
</template>
|
||||
<template v-else> - </template>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-4 mt-8">
|
||||
<h5 class="p-8-12">本次对话</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter pre-wrap">
|
||||
<div v-if="item.image_list?.length > 0">
|
||||
<p class="mb-8 color-secondary">图片:</p>
|
||||
<el-space wrap>
|
||||
<template v-for="(f, i) in item.image_list" :key="i">
|
||||
<el-image
|
||||
:src="f.url"
|
||||
alt=""
|
||||
fit="cover"
|
||||
style="width: 40px; height: 40px; display: block"
|
||||
class="border-r-4"
|
||||
/>
|
||||
</template>
|
||||
</el-space>
|
||||
</div>
|
||||
<div>
|
||||
<p class="mb-8 color-secondary">提示词:</p>
|
||||
{{ item.question || '-' }}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-never border-r-4 mt-8">
|
||||
<h5 class="p-8-12">
|
||||
{{ item.type == WorkflowType.Application ? '参数输出' : 'AI 回答' }}
|
||||
</h5>
|
||||
<div class="p-8-12 border-t-dashed lighter">
|
||||
<MdPreview
|
||||
v-if="item.answer"
|
||||
ref="editorRef"
|
||||
editorId="preview-only"
|
||||
:modelValue="item.answer"
|
||||
style="background: none"
|
||||
/>
|
||||
<template v-else> - </template>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
</template>
|
||||
<template v-else>
|
||||
<div class="card-never border-r-4">
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
<el-icon><CircleCloseFilled /></el-icon>
|
||||
</div>
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis" :title="item && item?.name">
|
||||
<div class="ml-4 ellipsis" style="max-width: 160px" :title="item && item?.name">
|
||||
{{ item && item?.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -83,18 +83,29 @@
|
|||
:accept="getAcceptList()"
|
||||
:on-change="(file: any, fileList: any) => uploadFile(file, fileList)"
|
||||
>
|
||||
<el-button text>
|
||||
<el-icon><Paperclip /></el-icon>
|
||||
</el-button>
|
||||
<el-tooltip effect="dark" placement="top" popper-class="upload-tooltip-width">
|
||||
<template #content
|
||||
>上传文件:最多{{
|
||||
props.applicationDetails.file_upload_setting.maxFiles
|
||||
}}个,每个文件限制
|
||||
{{ props.applicationDetails.file_upload_setting.fileLimit }}MB<br />文件类型:{{
|
||||
getAcceptList()
|
||||
}}</template
|
||||
>
|
||||
<el-button text>
|
||||
<el-icon><Paperclip /></el-icon>
|
||||
</el-button>
|
||||
</el-tooltip>
|
||||
</el-upload>
|
||||
<el-divider direction="vertical" />
|
||||
</span>
|
||||
<span v-if="props.applicationDetails.stt_model_enable" class="flex align-center">
|
||||
<el-button text v-if="mediaRecorderStatus" @click="startRecording">
|
||||
<el-button text @click="startRecording" v-if="mediaRecorderStatus">
|
||||
<el-icon>
|
||||
<Microphone />
|
||||
</el-icon>
|
||||
</el-button>
|
||||
|
||||
<div v-else class="operate flex align-center">
|
||||
<el-text type="info"
|
||||
>00:{{ recorderTime < 10 ? `0${recorderTime}` : recorderTime }}</el-text
|
||||
|
|
@ -191,26 +202,30 @@ const audioExtensions = ['mp3', 'wav', 'aac', 'flac']
|
|||
|
||||
const getAcceptList = () => {
|
||||
const { image, document, audio, video } = props.applicationDetails.file_upload_setting
|
||||
let accepts = ''
|
||||
let accepts: any = []
|
||||
if (image) {
|
||||
accepts += imageExtensions.map((ext) => '.' + ext).join(',')
|
||||
accepts = [...imageExtensions]
|
||||
}
|
||||
if (document) {
|
||||
accepts += documentExtensions.map((ext) => '.' + ext).join(',')
|
||||
accepts = [...accepts, ...documentExtensions]
|
||||
}
|
||||
if (audio) {
|
||||
accepts += audioExtensions.map((ext) => '.' + ext).join(',')
|
||||
accepts = [...accepts, ...audioExtensions]
|
||||
}
|
||||
if (video) {
|
||||
accepts += videoExtensions.map((ext) => '.' + ext).join(',')
|
||||
accepts = [...accepts, ...videoExtensions]
|
||||
}
|
||||
return accepts
|
||||
// console.log(accepts)
|
||||
return accepts.map((ext: any) => '.' + ext).join(',')
|
||||
}
|
||||
|
||||
const uploadFile = async (file: any, fileList: any) => {
|
||||
const { maxFiles, fileLimit } = props.applicationDetails.file_upload_setting
|
||||
if (fileList.length > maxFiles) {
|
||||
// 单次上传文件数量限制
|
||||
const file_limit_once = uploadImageList.value.length + uploadDocumentList.value.length
|
||||
if (file_limit_once >= maxFiles) {
|
||||
MsgWarning('最多上传' + maxFiles + '个文件')
|
||||
fileList.splice(0, fileList.length)
|
||||
return
|
||||
}
|
||||
if (fileList.filter((f: any) => f.size > fileLimit * 1024 * 1024).length > 0) {
|
||||
|
|
@ -454,4 +469,7 @@ onMounted(() => {
|
|||
z-index: 1;
|
||||
}
|
||||
}
|
||||
.upload-tooltip-width {
|
||||
width: 300px;
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -18,10 +18,13 @@
|
|||
<div class="mb-8" v-if="document_list.length">
|
||||
<el-space wrap>
|
||||
<template v-for="(item, index) in document_list" :key="index">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px" class="file cursor">
|
||||
<div class="flex align-center">
|
||||
<el-card shadow="never" style="--el-card-padding: 8px" class="download-file cursor">
|
||||
<div class="download-button flex align-center" @click="downloadFile(item)">
|
||||
<el-icon class="mr-4"><Download /></el-icon>点击下载文件
|
||||
</div>
|
||||
<div class="show flex align-center">
|
||||
<img :src="getImgUrl(item && item?.name)" alt="" width="24" />
|
||||
<div class="ml-4 ellipsis" :title="item && item?.name">
|
||||
<div class="ml-4 ellipsis" style="max-width: 150px" :title="item && item?.name">
|
||||
{{ item && item?.name }}
|
||||
</div>
|
||||
</div>
|
||||
|
|
@ -55,7 +58,7 @@
|
|||
</template>
|
||||
<script setup lang="ts">
|
||||
import { type chatType } from '@/api/type/application'
|
||||
import { getImgUrl, getAttrsArray } from '@/utils/utils'
|
||||
import { getImgUrl, getAttrsArray, downloadByURL } from '@/utils/utils'
|
||||
import { onMounted, computed } from 'vue'
|
||||
const props = defineProps<{
|
||||
application: any
|
||||
|
|
@ -80,13 +83,33 @@ const image_list = computed(() => {
|
|||
}
|
||||
})
|
||||
|
||||
onMounted(() => {
|
||||
console.log(props.chatRecord.execution_details)
|
||||
if (props.chatRecord.execution_details?.length > 0) {
|
||||
props.chatRecord.execution_details[0].image_list?.forEach((image: any) => {
|
||||
console.log('image', image.name, image.url)
|
||||
})
|
||||
}
|
||||
})
|
||||
function downloadFile(item: any) {
|
||||
downloadByURL(item.url, item.name)
|
||||
}
|
||||
|
||||
onMounted(() => {})
|
||||
</script>
|
||||
<style lang="scss" scoped></style>
|
||||
<style lang="scss" scoped>
|
||||
.download-file {
|
||||
width: 200px;
|
||||
height: 43px;
|
||||
&:hover {
|
||||
color: var(--el-color-primary);
|
||||
border: 1px solid var(--el-color-primary);
|
||||
.download-button {
|
||||
display: block;
|
||||
text-align: center;
|
||||
line-height: 26px;
|
||||
}
|
||||
.show {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.show {
|
||||
display: block;
|
||||
}
|
||||
.download-button {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
|
|
|
|||
|
|
@ -60,7 +60,7 @@ function checkboxChange() {
|
|||
emit('change')
|
||||
}
|
||||
</script>
|
||||
<style lang="scss" scoped>
|
||||
<style lang="scss">
|
||||
.card-checkbox {
|
||||
&.active {
|
||||
border: 1px solid var(--el-color-primary);
|
||||
|
|
|
|||
|
|
@ -12,5 +12,6 @@ export enum modelType {
|
|||
LLM = '大语言模型',
|
||||
STT = '语音识别',
|
||||
TTS = '语音合成',
|
||||
IMAGE = '图片理解',
|
||||
RERANKER = '重排模型'
|
||||
}
|
||||
|
|
|
|||
|
|
@ -88,3 +88,14 @@ export function getAttrsArray(array: Array<any>, attr: string) {
|
|||
export function getSum(array: Array<any>) {
|
||||
return array.reduce((total, item) => total + item, 0)
|
||||
}
|
||||
|
||||
// 下载
|
||||
export function downloadByURL(url: string, name: string) {
|
||||
const a = document.createElement('a')
|
||||
a.setAttribute('href', url)
|
||||
a.setAttribute('target', '_blank')
|
||||
a.setAttribute('download', name)
|
||||
document.body.appendChild(a)
|
||||
a.click()
|
||||
document.body.removeChild(a)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -198,6 +198,8 @@
|
|||
:value-on-clear="0"
|
||||
controls-position="right"
|
||||
class="w-full"
|
||||
:step="1"
|
||||
:step-strictly="true"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item
|
||||
|
|
|
|||
|
|
@ -79,9 +79,9 @@
|
|||
/>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="lighter mr-8" size="small">
|
||||
<el-text class="color-secondary" size="small">
|
||||
<auto-tooltip :content="item.username">
|
||||
创建人: {{ item.username }}
|
||||
创建者: {{ item.username }}
|
||||
</auto-tooltip>
|
||||
</el-text>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -48,12 +48,12 @@
|
|||
$t('login.ldap.enableAuthentication')
|
||||
}}</el-checkbox>
|
||||
</el-form-item>
|
||||
<el-button @click="submit(authFormRef, 'test')" :disabled="loading">
|
||||
{{ $t('login.ldap.test') }}</el-button
|
||||
>
|
||||
</el-form>
|
||||
|
||||
<div class="text-right">
|
||||
<el-button @click="submit(authFormRef, 'test')" :disabled="loading">
|
||||
{{ $t('login.ldap.test') }}</el-button
|
||||
>
|
||||
<el-button @click="submit(authFormRef)" type="primary" :disabled="loading">
|
||||
{{ $t('login.ldap.save') }}
|
||||
</el-button>
|
||||
|
|
|
|||
|
|
@ -82,7 +82,7 @@
|
|||
</div>
|
||||
</el-scrollbar>
|
||||
<div>
|
||||
<el-checkbox v-model="checkedConnect" @change="changeHandle">
|
||||
<el-checkbox v-model="checkedConnect" @change="changeHandle" style="white-space: normal;">
|
||||
导入时添加分段标题为关联问题(适用于标题为问题的问答对)
|
||||
</el-checkbox>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -62,9 +62,9 @@
|
|||
</AppAvatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="lighter mr-8" size="small">
|
||||
<el-text class="color-secondary" size="small">
|
||||
<auto-tooltip :content="item.username">
|
||||
创建人: {{ item.username }}
|
||||
创建者: {{ item.username }}
|
||||
</auto-tooltip>
|
||||
</el-text>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -67,9 +67,9 @@
|
|||
</AppAvatar>
|
||||
</template>
|
||||
<template #subTitle>
|
||||
<el-text class="lighter mr-8" size="small">
|
||||
<el-text class="color-secondary" size="small">
|
||||
<auto-tooltip :content="item.username">
|
||||
创建人: {{ item.username }}
|
||||
创建者: {{ item.username }}
|
||||
</auto-tooltip>
|
||||
</el-text>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -221,7 +221,7 @@ export const imageUnderstandNode = {
|
|||
fields: [
|
||||
{
|
||||
label: 'AI 回答内容',
|
||||
value: 'content'
|
||||
value: 'answer'
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
|||
|
|
@ -71,7 +71,11 @@ class CustomEdge2 extends BezierEdge {
|
|||
delete style.stroke
|
||||
|
||||
return h('g', {}, [
|
||||
h('style', { type: 'text/css' }, '.lf-edge{stroke:#afafaf}.lf-edge:hover{stroke: #3370FF;}'),
|
||||
h(
|
||||
'style' as any,
|
||||
{ type: 'text/css' },
|
||||
'.lf-edge{stroke:#afafaf}.lf-edge:hover{stroke: #3370FF;}'
|
||||
),
|
||||
h('path', {
|
||||
d: path,
|
||||
...style,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<AppAvatar shape="square" style="background: #7F3BF5">
|
||||
<img src="@/assets/icon_document.svg" style="width: 65%" alt="" />
|
||||
<AppAvatar shape="square" class="avatar-blue">
|
||||
<img src="@/assets/icon_docs.svg" style="width: 65%" alt="" />
|
||||
</AppAvatar>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<AppAvatar shape="square" style="background: #14C0FF;">
|
||||
<img src="@/assets/icon_document.svg" style="width: 65%" alt="" />
|
||||
<img src="@/assets/icon_image.svg" style="width: 65%" alt="" />
|
||||
</AppAvatar>
|
||||
</template>
|
||||
<script setup lang="ts"></script>
|
||||
|
|
|
|||
|
|
@ -154,6 +154,8 @@
|
|||
:value-on-clear="0"
|
||||
controls-position="right"
|
||||
class="w-full"
|
||||
:step="1"
|
||||
:step-strictly="true"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回内容" @click.prevent>
|
||||
|
|
|
|||
|
|
@ -7,34 +7,64 @@
|
|||
:destroy-on-close="true"
|
||||
:before-close="close"
|
||||
append-to-body
|
||||
width="600"
|
||||
>
|
||||
<el-form
|
||||
label-position="top"
|
||||
ref="fieldFormRef"
|
||||
:model="form_data"
|
||||
require-asterisk-position="right">
|
||||
require-asterisk-position="right"
|
||||
>
|
||||
<el-form-item label="单次上传最多文件数">
|
||||
<el-slider v-model="form_data.maxFiles" show-input :show-input-controls="false" :min="1" :max="10" />
|
||||
<el-slider
|
||||
v-model="form_data.maxFiles"
|
||||
show-input
|
||||
:show-input-controls="false"
|
||||
:min="1"
|
||||
:max="10"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="每个文件最大(MB)">
|
||||
<el-slider v-model="form_data.fileLimit" show-input :show-input-controls="false" :min="1" :max="100" />
|
||||
<el-slider
|
||||
v-model="form_data.fileLimit"
|
||||
show-input
|
||||
:show-input-controls="false"
|
||||
:min="1"
|
||||
:max="100"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="上传的文件类型">
|
||||
<el-card style="width: 100%" class="mb-8">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
class="card-checkbox cursor w-full mb-8"
|
||||
:class="form_data.document ? 'active' : ''"
|
||||
style="--el-card-padding: 8px 16px"
|
||||
>
|
||||
<div class="flex-between">
|
||||
<p>
|
||||
文档(TXT、MD、DOCX、HTML、CSV、XLSX、XLS、PDF)
|
||||
需要与文档内容提取节点配合使用
|
||||
</p>
|
||||
<div class="flex align-center">
|
||||
<img class="mr-12" src="@/assets/icon_file-doc.svg" alt="" />
|
||||
<div>
|
||||
<p>文档(TXT、MD、DOCX、HTML、CSV、XLSX、XLS、PDF)</p>
|
||||
<el-text class="color-secondary">需要与文档内容提取节点配合使用</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<el-checkbox v-model="form_data.document" />
|
||||
</div>
|
||||
</el-card>
|
||||
<el-card style="width: 100%" class="mb-8">
|
||||
<el-card
|
||||
shadow="hover"
|
||||
class="card-checkbox cursor w-full mb-8"
|
||||
:class="form_data.image ? 'active' : ''"
|
||||
style="--el-card-padding: 8px 16px"
|
||||
>
|
||||
<div class="flex-between">
|
||||
<p>
|
||||
图片(JPG、JPEG、PNG、GIF)
|
||||
所选模型需要支持接收图片
|
||||
</p>
|
||||
<div class="flex align-center">
|
||||
<img class="mr-12" src="@/assets/icon_file-image.svg" alt="" />
|
||||
<div>
|
||||
<p>图片(JPG、JPEG、PNG、GIF)</p>
|
||||
<el-text class="color-secondary">所选模型需要支持接收图片</el-text>
|
||||
</div>
|
||||
</div>
|
||||
<el-checkbox v-model="form_data.image" />
|
||||
</div>
|
||||
</el-card>
|
||||
|
|
@ -43,9 +73,7 @@
|
|||
<template #footer>
|
||||
<span class="dialog-footer">
|
||||
<el-button @click.prevent="close"> 取消 </el-button>
|
||||
<el-button type="primary" @click="submit()" :loading="loading">
|
||||
确定
|
||||
</el-button>
|
||||
<el-button type="primary" @click="submit()" :loading="loading"> 确定 </el-button>
|
||||
</span>
|
||||
</template>
|
||||
</el-dialog>
|
||||
|
|
@ -69,7 +97,6 @@ const form_data = ref({
|
|||
video: false
|
||||
})
|
||||
|
||||
|
||||
function open(data: any) {
|
||||
dialogVisible.value = true
|
||||
nextTick(() => {
|
||||
|
|
@ -96,6 +123,4 @@ defineExpose({
|
|||
})
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
</style>
|
||||
<style scoped lang="scss"></style>
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
:nodeModel="nodeModel"
|
||||
class="w-full"
|
||||
placeholder="请选择文档"
|
||||
v-model="form.document_list"
|
||||
v-model="form_data.document_list"
|
||||
/>
|
||||
</el-form-item>
|
||||
</el-form>
|
||||
|
|
|
|||
|
|
@ -7,7 +7,6 @@
|
|||
:model="form_data"
|
||||
label-position="top"
|
||||
require-asterisk-position="right"
|
||||
class="mb-24"
|
||||
label-width="auto"
|
||||
ref="aiChatNodeFormRef"
|
||||
hide-required-asterisk
|
||||
|
|
@ -132,7 +131,7 @@
|
|||
<template #label>
|
||||
<div class="flex-between">
|
||||
<div>历史聊天记录</div>
|
||||
<el-select v-model="form_data.dialogue_type" class="w-120">
|
||||
<el-select v-model="form_data.dialogue_type" type="small" style="width: 100px;">
|
||||
<el-option label="节点" value="NODE"/>
|
||||
<el-option label="工作流" value="WORKFLOW"/>
|
||||
</el-select>
|
||||
|
|
|
|||
|
|
@ -152,6 +152,8 @@
|
|||
:value-on-clear="0"
|
||||
controls-position="right"
|
||||
class="w-full"
|
||||
:step="1"
|
||||
:step-strictly="true"
|
||||
/>
|
||||
</el-form-item>
|
||||
<el-form-item label="返回内容" @click.prevent>
|
||||
|
|
|
|||
Loading…
Reference in New Issue