mirror of
https://github.com/1Panel-dev/MaxKB.git
synced 2025-12-26 01:33:05 +00:00
fix: refactoring embedded application logic
This commit is contained in:
parent
de97de64b2
commit
cc3813e97e
|
|
@ -21,6 +21,7 @@ from django.core import cache, validators
|
|||
from django.core import signing
|
||||
from django.db import transaction, models
|
||||
from django.db.models import QuerySet
|
||||
from django.db.models.expressions import RawSQL
|
||||
from django.http import HttpResponse
|
||||
from django.template import Template, Context
|
||||
from rest_framework import serializers, status
|
||||
|
|
@ -46,13 +47,15 @@ from dataset.serializers.common_serializers import list_paragraph, get_embedding
|
|||
from embedding.models import SearchMode
|
||||
from function_lib.models.function import FunctionLib, PermissionType
|
||||
from function_lib.serializers.function_lib_serializer import FunctionLibSerializer, FunctionLibModelSerializer
|
||||
from setting.models import AuthOperate
|
||||
from setting.models import AuthOperate, TeamMemberPermission
|
||||
from setting.models.model_management import Model
|
||||
from setting.models_provider import get_model_credential
|
||||
from setting.models_provider.tools import get_model_instance_by_model_user_id
|
||||
from setting.serializers.provider_serializers import ModelSerializer
|
||||
from smartdoc.conf import PROJECT_DIR
|
||||
from users.models import User
|
||||
from django.db.models import Value
|
||||
from django.db.models.fields.json import KeyTextTransform
|
||||
|
||||
chat_cache = cache.caches['chat_cache']
|
||||
|
||||
|
|
@ -1110,12 +1113,38 @@ class ApplicationSerializer(serializers.Serializer):
|
|||
self.is_valid(raise_exception=True)
|
||||
user_id = self.data.get('user_id')
|
||||
application_id = self.data.get('application_id')
|
||||
application = Application.objects.filter(user_id=user_id).exclude(id=application_id)
|
||||
application = QuerySet(Application).get(id=application_id)
|
||||
|
||||
application_user_id = user_id if user_id == str(application.user_id) else None
|
||||
|
||||
if application_user_id is not None:
|
||||
all_applications = Application.objects.filter(user_id=application_user_id).exclude(id=application_id)
|
||||
else:
|
||||
all_applications = Application.objects.none()
|
||||
|
||||
# 获取团队共享的应用
|
||||
shared_applications = Application.objects.filter(
|
||||
id__in=TeamMemberPermission.objects.filter(
|
||||
auth_target_type='APPLICATION',
|
||||
operate__contains=RawSQL("ARRAY['USE']", []),
|
||||
member_id__team_id=application.user_id,
|
||||
member_id__user_id=user_id
|
||||
).values('target')
|
||||
)
|
||||
all_applications = all_applications.union(shared_applications)
|
||||
|
||||
# 把应用的type为WORK_FLOW的应用放到最上面 然后再按名称排序
|
||||
serialized_data = ApplicationSerializerModel(application, many=True).data
|
||||
serialized_data = ApplicationSerializerModel(all_applications, many=True).data
|
||||
application = sorted(serialized_data, key=lambda x: (x['type'] != 'WORK_FLOW', x['name']))
|
||||
return list(application)
|
||||
|
||||
def get_application(self, app_id, with_valid=True):
|
||||
if with_valid:
|
||||
self.is_valid(raise_exception=True)
|
||||
application = QuerySet(Application).filter(id=self.data.get("application_id")).first()
|
||||
return ApplicationSerializer.Operate(data={'user_id': application.user_id, 'application_id': app_id}).one(
|
||||
with_valid=True)
|
||||
|
||||
class ApplicationKeySerializerModel(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = ApplicationApiKey
|
||||
|
|
|
|||
|
|
@ -25,6 +25,8 @@ urlpatterns = [
|
|||
path('application/<str:application_id>/function_lib/<str:function_lib_id>',
|
||||
views.Application.FunctionLib.Operate.as_view()),
|
||||
path('application/<str:application_id>/application', views.Application.Application.as_view()),
|
||||
path('application/<str:application_id>/application/<str:app_id>',
|
||||
views.Application.Application.Operate.as_view()),
|
||||
path('application/<str:application_id>/model_params_form/<str:model_id>',
|
||||
views.Application.ModelParamsForm.as_view()),
|
||||
path('application/<str:application_id>/hit_test', views.Application.HitTest.as_view()),
|
||||
|
|
|
|||
|
|
@ -288,6 +288,25 @@ class Application(APIView):
|
|||
data={'application_id': application_id,
|
||||
'user_id': request.user.id}).application_list())
|
||||
|
||||
class Operate(APIView):
|
||||
authentication_classes = [TokenAuth]
|
||||
|
||||
@action(methods=["GET"], detail=False)
|
||||
@swagger_auto_schema(operation_summary="获取应用数据",
|
||||
operation_id="获取应用数据",
|
||||
tags=["应用"],
|
||||
)
|
||||
@has_permissions(ViewPermission(
|
||||
[RoleConstants.ADMIN, RoleConstants.USER],
|
||||
[lambda r, keywords: Permission(group=Group.APPLICATION, operate=Operate.USE,
|
||||
dynamic_tag=keywords.get('application_id'))],
|
||||
compare=CompareConstants.AND))
|
||||
def get(self, request: Request, application_id: str, app_id: str):
|
||||
return result.success(
|
||||
ApplicationSerializer.Operate(
|
||||
data={'application_id': application_id,
|
||||
'user_id': request.user.id}).get_application(app_id))
|
||||
|
||||
class Profile(APIView):
|
||||
authentication_classes = [TokenAuth]
|
||||
|
||||
|
|
@ -433,7 +452,6 @@ class Application(APIView):
|
|||
)
|
||||
|
||||
@action(methods=['POST'], detail=False)
|
||||
|
||||
@swagger_auto_schema(operation_summary="创建应用",
|
||||
operation_id="创建应用",
|
||||
request_body=ApplicationApi.Create.get_request_body_api(),
|
||||
|
|
|
|||
|
|
@ -349,6 +349,14 @@ const getFunctionLib: (
|
|||
) => Promise<Result<any>> = (application_id, function_lib_id, loading) => {
|
||||
return get(`${prefix}/${application_id}/function_lib/${function_lib_id}`, undefined, loading)
|
||||
}
|
||||
|
||||
const getApplicationById: (
|
||||
application_id: String,
|
||||
app_id: String,
|
||||
loading?: Ref<boolean>
|
||||
) => Promise<Result<any>> = (application_id, app_id, loading) => {
|
||||
return get(`${prefix}/${application_id}/application/${app_id}`, undefined, loading)
|
||||
}
|
||||
/**
|
||||
* 获取模型参数表单
|
||||
* @param application_id 应用id
|
||||
|
|
@ -567,5 +575,6 @@ export default {
|
|||
getApplicationList,
|
||||
uploadFile,
|
||||
exportApplication,
|
||||
importApplication
|
||||
importApplication,
|
||||
getApplicationById
|
||||
}
|
||||
|
|
|
|||
|
|
@ -79,7 +79,7 @@
|
|||
<el-alert
|
||||
v-if="node_status != 200"
|
||||
class="mb-16"
|
||||
title="该函数不可用"
|
||||
:title="props.nodeModel.type === 'application-node' ? '该应用不可用' : '该函数不可用'"
|
||||
type="error"
|
||||
show-icon
|
||||
:closable="false"
|
||||
|
|
|
|||
|
|
@ -148,6 +148,8 @@ import NodeContainer from '@/workflow/common/NodeContainer.vue'
|
|||
import { ref, computed, onMounted } from 'vue'
|
||||
import NodeCascader from '@/workflow/common/NodeCascader.vue'
|
||||
import type { FormInstance } from 'element-plus'
|
||||
import applicationApi from '@/api/application'
|
||||
import { isWorkFlow } from '@/utils/application'
|
||||
|
||||
const form = {
|
||||
question_reference_address: ['start-node', 'question'],
|
||||
|
|
@ -158,6 +160,10 @@ const form = {
|
|||
audio_list: ['start-node', 'audio']
|
||||
}
|
||||
|
||||
const {
|
||||
params: { id }
|
||||
} = app.config.globalProperties.$route as any
|
||||
|
||||
const applicationNodeFormRef = ref<FormInstance>()
|
||||
|
||||
const form_data = computed({
|
||||
|
|
@ -174,6 +180,85 @@ const form_data = computed({
|
|||
}
|
||||
})
|
||||
|
||||
function handleFileUpload(type: string, isEnabled: boolean) {
|
||||
const listKey = `${type}_list`
|
||||
if (isEnabled) {
|
||||
if (!props.nodeModel.properties.node_data[listKey]) {
|
||||
set(props.nodeModel.properties.node_data, listKey, [])
|
||||
}
|
||||
} else {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
delete props.nodeModel.properties.node_data[listKey]
|
||||
}
|
||||
}
|
||||
|
||||
const update_field = () => {
|
||||
if (!props.nodeModel.properties.node_data.application_id) {
|
||||
set(props.nodeModel.properties, 'status', 500)
|
||||
return
|
||||
}
|
||||
applicationApi
|
||||
.getApplicationById(id, props.nodeModel.properties.node_data.application_id)
|
||||
.then((ok) => {
|
||||
const old_api_input_field_list = props.nodeModel.properties.node_data.api_input_field_list
|
||||
const old_user_input_field_list = props.nodeModel.properties.node_data.user_input_field_list
|
||||
|
||||
if (isWorkFlow(ok.data.type)) {
|
||||
const nodeData = ok.data.work_flow.nodes[0].properties.node_data
|
||||
const new_api_input_field_list = ok.data.work_flow.nodes[0].properties.api_input_field_list
|
||||
const new_user_input_field_list =
|
||||
ok.data.work_flow.nodes[0].properties.user_input_field_list
|
||||
const merge_api_input_field_list = new_api_input_field_list.map((item: any) => {
|
||||
const find_field = old_api_input_field_list.find(
|
||||
(old_item: any) => old_item.variable == item.variable
|
||||
)
|
||||
if (find_field) {
|
||||
return { ...item, default_value: JSON.parse(JSON.stringify(find_field.default_value)) }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
set(
|
||||
props.nodeModel.properties.node_data,
|
||||
'api_input_field_list',
|
||||
merge_api_input_field_list
|
||||
)
|
||||
const merge_user_input_field_list = new_user_input_field_list.map((item: any) => {
|
||||
const find_field = old_user_input_field_list.find(
|
||||
(old_item: any) => old_item.field == item.field
|
||||
)
|
||||
if (find_field) {
|
||||
return { ...item, default_value: JSON.parse(JSON.stringify(find_field.default_value)) }
|
||||
} else {
|
||||
return item
|
||||
}
|
||||
})
|
||||
console.log(merge_user_input_field_list)
|
||||
set(
|
||||
props.nodeModel.properties.node_data,
|
||||
'user_input_field_list',
|
||||
merge_user_input_field_list
|
||||
)
|
||||
const fileUploadSetting = nodeData.file_upload_setting
|
||||
// 如果是true,说明有文件上传
|
||||
if (fileUploadSetting) {
|
||||
handleFileUpload('document', fileUploadSetting.document)
|
||||
handleFileUpload('image', fileUploadSetting.image)
|
||||
handleFileUpload('audio', fileUploadSetting.audio)
|
||||
} else {
|
||||
;['document_list', 'image_list', 'audio_list'].forEach((list) => {
|
||||
// eslint-disable-next-line vue/no-mutating-props
|
||||
delete props.nodeModel.properties.node_data[list]
|
||||
})
|
||||
}
|
||||
set(props.nodeModel.properties, 'status', ok.data.id ? 200 : 500)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
set(props.nodeModel.properties, 'status', 500)
|
||||
})
|
||||
}
|
||||
|
||||
const props = defineProps<{ nodeModel: any }>()
|
||||
|
||||
const validate = () => {
|
||||
|
|
@ -183,6 +268,7 @@ const validate = () => {
|
|||
}
|
||||
|
||||
onMounted(() => {
|
||||
update_field()
|
||||
set(props.nodeModel, 'validate', validate)
|
||||
})
|
||||
</script>
|
||||
|
|
|
|||
Loading…
Reference in New Issue