|
10 | 10 | import hashlib
|
11 | 11 | import json
|
12 | 12 | import os
|
| 13 | +import pickle |
13 | 14 | import re
|
14 | 15 | import uuid
|
15 | 16 | from functools import reduce
|
|
19 | 20 | from django.core import cache, validators
|
20 | 21 | from django.core import signing
|
21 | 22 | from django.db import transaction, models
|
22 |
| -from django.db.models import QuerySet, Q |
| 23 | +from django.db.models import QuerySet |
23 | 24 | from django.http import HttpResponse
|
24 | 25 | from django.template import Template, Context
|
25 |
| -from rest_framework import serializers |
| 26 | +from rest_framework import serializers, status |
26 | 27 |
|
27 | 28 | from application.flow.workflow_manage import Flow
|
28 | 29 | from application.models import Application, ApplicationDatasetMapping, ApplicationTypeChoices, WorkFlowVersion
|
|
34 | 35 | from common.db.search import get_dynamics_model, native_search, native_page_search
|
35 | 36 | from common.db.sql_execute import select_list
|
36 | 37 | from common.exception.app_exception import AppApiException, NotFound404, AppUnauthorizedFailed
|
37 |
| -from common.field.common import UploadedImageField |
| 38 | +from common.field.common import UploadedImageField, UploadedFileField |
38 | 39 | from common.models.db_model_manage import DBModelManage
|
| 40 | +from common.response import result |
39 | 41 | from common.util.common import valid_license, password_encrypt
|
40 | 42 | from common.util.field_message import ErrMessage
|
41 | 43 | from common.util.file_util import get_file_content
|
42 | 44 | from dataset.models import DataSet, Document, Image
|
43 | 45 | from dataset.serializers.common_serializers import list_paragraph, get_embedding_model_by_dataset_id_list
|
44 | 46 | from embedding.models import SearchMode
|
45 |
| -from function_lib.serializers.function_lib_serializer import FunctionLibSerializer |
| 47 | +from function_lib.models.function import FunctionLib, PermissionType |
| 48 | +from function_lib.serializers.function_lib_serializer import FunctionLibSerializer, FunctionLibModelSerializer |
46 | 49 | from setting.models import AuthOperate
|
47 | 50 | from setting.models.model_management import Model
|
48 | 51 | from setting.models_provider import get_model_credential
|
|
54 | 57 | chat_cache = cache.caches['chat_cache']
|
55 | 58 |
|
56 | 59 |
|
| 60 | +class MKInstance: |
| 61 | + def __init__(self, application: dict, function_lib_list: List[dict], version: str): |
| 62 | + self.application = application |
| 63 | + self.function_lib_list = function_lib_list |
| 64 | + self.version = version |
| 65 | + |
| 66 | + |
57 | 67 | class ModelDatasetAssociation(serializers.Serializer):
|
58 | 68 | user_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("用户id"))
|
59 | 69 | model_id = serializers.CharField(required=False, allow_null=True, allow_blank=True,
|
@@ -662,6 +672,72 @@ def edit(self, with_valid=True):
|
662 | 672 | get_application_access_token(application_access_token.access_token, False)
|
663 | 673 | return {**ApplicationSerializer.Query.reset_application(ApplicationSerializerModel(application).data)}
|
664 | 674 |
|
| 675 | + class Import(serializers.Serializer): |
| 676 | + file = UploadedFileField(required=True, error_messages=ErrMessage.image("文件")) |
| 677 | + user_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("用户id")) |
| 678 | + |
| 679 | + @valid_license(model=Application, count=5, |
| 680 | + message='社区版最多支持 5 个应用,如需拥有更多应用,请联系我们(https://fit2cloud.com/)。') |
| 681 | + @transaction.atomic |
| 682 | + def import_(self, with_valid=True): |
| 683 | + if with_valid: |
| 684 | + self.is_valid() |
| 685 | + user_id = self.data.get('user_id') |
| 686 | + mk_instance_bytes = self.data.get('file').read() |
| 687 | + mk_instance = pickle.loads(mk_instance_bytes) |
| 688 | + application = mk_instance.application |
| 689 | + function_lib_list = mk_instance.function_lib_list |
| 690 | + if len(function_lib_list) > 0: |
| 691 | + function_lib_id_list = [function_lib.get('id') for function_lib in function_lib_list] |
| 692 | + exits_function_lib_id_list = [str(function_lib.id) for function_lib in |
| 693 | + QuerySet(FunctionLib).filter(id__in=function_lib_id_list)] |
| 694 | + # 获取到需要插入的函数 |
| 695 | + function_lib_list = [function_lib for function_lib in function_lib_list if |
| 696 | + not exits_function_lib_id_list.__contains__(function_lib.get('id'))] |
| 697 | + application_model = self.to_application(application, user_id) |
| 698 | + function_lib_model_list = [self.to_function_lib(f, user_id) for f in function_lib_list] |
| 699 | + application_model.save() |
| 700 | + QuerySet(FunctionLib).bulk_create(function_lib_model_list) if len(function_lib_model_list) > 0 else None |
| 701 | + return True |
| 702 | + |
| 703 | + @staticmethod |
| 704 | + def to_application(application, user_id): |
| 705 | + work_flow = application.get('work_flow') |
| 706 | + for node in work_flow.get('nodes', []): |
| 707 | + if node.get('type') == 'search-dataset-node': |
| 708 | + node.get('properties', {}).get('node_data', {})['dataset_id_list'] = [] |
| 709 | + return Application(id=uuid.uuid1(), user_id=user_id, name=application.get('name'), |
| 710 | + desc=application.get('desc'), |
| 711 | + prologue=application.get('prologue'), dialogue_number=application.get('dialogue_number'), |
| 712 | + dataset_setting=application.get('dataset_setting'), |
| 713 | + model_params_setting=application.get('model_params_setting'), |
| 714 | + tts_model_params_setting=application.get('tts_model_params_setting'), |
| 715 | + problem_optimization=application.get('problem_optimization'), |
| 716 | + icon=application.get('icon'), |
| 717 | + work_flow=work_flow, |
| 718 | + type=application.get('type'), |
| 719 | + problem_optimization_prompt=application.get('problem_optimization_prompt'), |
| 720 | + tts_model_enable=application.get('tts_model_enable'), |
| 721 | + stt_model_enable=application.get('stt_model_enable'), |
| 722 | + tts_type=application.get('tts_type'), |
| 723 | + clean_time=application.get('clean_time'), |
| 724 | + file_upload_enable=application.get('file_upload_enable'), |
| 725 | + file_upload_setting=application.get('file_upload_setting'), |
| 726 | + ) |
| 727 | + |
| 728 | + @staticmethod |
| 729 | + def to_function_lib(function_lib, user_id): |
| 730 | + """ |
| 731 | +
|
| 732 | + @param user_id: 用户id |
| 733 | + @param function_lib: 函数库 |
| 734 | + @return: |
| 735 | + """ |
| 736 | + return FunctionLib(id=function_lib.get('id'), user_id=user_id, name=function_lib.get('name'), |
| 737 | + code=function_lib.get('code'), input_field_list=function_lib.get('input_field_list'), |
| 738 | + is_active=function_lib.get('is_active'), |
| 739 | + permission_type=PermissionType.PRIVATE) |
| 740 | + |
665 | 741 | class Operate(serializers.Serializer):
|
666 | 742 | application_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("应用id"))
|
667 | 743 | user_id = serializers.UUIDField(required=True, error_messages=ErrMessage.uuid("用户id"))
|
@@ -708,6 +784,31 @@ def delete(self, with_valid=True):
|
708 | 784 | QuerySet(Application).filter(id=self.data.get('application_id')).delete()
|
709 | 785 | return True
|
710 | 786 |
|
| 787 | + def export(self, with_valid=True): |
| 788 | + try: |
| 789 | + if with_valid: |
| 790 | + self.is_valid() |
| 791 | + application_id = self.data.get('application_id') |
| 792 | + application = QuerySet(Application).filter(id=application_id).first() |
| 793 | + function_lib_id_list = [node.get('properties', {}).get('node_data', {}).get('function_lib_id') for node |
| 794 | + in |
| 795 | + application.work_flow.get('nodes', []) if |
| 796 | + node.get('type') == 'function-lib-node'] |
| 797 | + function_lib_list = [] |
| 798 | + if len(function_lib_id_list) > 0: |
| 799 | + function_lib_list = QuerySet(FunctionLib).filter(id__in=function_lib_id_list) |
| 800 | + application_dict = ApplicationSerializerModel(application).data |
| 801 | + |
| 802 | + mk_instance = MKInstance(application_dict, |
| 803 | + [FunctionLibModelSerializer(function_lib).data for function_lib in |
| 804 | + function_lib_list], 'v1') |
| 805 | + application_pickle = pickle.dumps(mk_instance) |
| 806 | + response = HttpResponse(content_type='text/plain', content=application_pickle) |
| 807 | + response['Content-Disposition'] = f'attachment; filename="{application.name}.mk"' |
| 808 | + return response |
| 809 | + except Exception as e: |
| 810 | + return result.error(str(e), response_status=status.HTTP_500_INTERNAL_SERVER_ERROR) |
| 811 | + |
711 | 812 | @transaction.atomic
|
712 | 813 | def publish(self, instance, with_valid=True):
|
713 | 814 | if with_valid:
|
|
0 commit comments