20231204 (#1691)
Co-authored-by: jyong <jyong@dify.ai>tags/0.3.33
| 'HOSTED_ANTHROPIC_PAID_MAX_QUANTITY': 100, | 'HOSTED_ANTHROPIC_PAID_MAX_QUANTITY': 100, | ||||
| 'HOSTED_MODERATION_ENABLED': 'False', | 'HOSTED_MODERATION_ENABLED': 'False', | ||||
| 'HOSTED_MODERATION_PROVIDERS': '', | 'HOSTED_MODERATION_PROVIDERS': '', | ||||
| 'TENANT_DOCUMENT_COUNT': 100, | |||||
| 'CLEAN_DAY_SETTING': 30, | 'CLEAN_DAY_SETTING': 30, | ||||
| 'UPLOAD_FILE_SIZE_LIMIT': 15, | 'UPLOAD_FILE_SIZE_LIMIT': 15, | ||||
| 'UPLOAD_FILE_BATCH_LIMIT': 5, | 'UPLOAD_FILE_BATCH_LIMIT': 5, | ||||
| self.MULTIMODAL_SEND_IMAGE_FORMAT = get_env('MULTIMODAL_SEND_IMAGE_FORMAT') | self.MULTIMODAL_SEND_IMAGE_FORMAT = get_env('MULTIMODAL_SEND_IMAGE_FORMAT') | ||||
| # Dataset Configurations. | # Dataset Configurations. | ||||
| self.TENANT_DOCUMENT_COUNT = get_env('TENANT_DOCUMENT_COUNT') | |||||
| self.CLEAN_DAY_SETTING = get_env('CLEAN_DAY_SETTING') | self.CLEAN_DAY_SETTING = get_env('CLEAN_DAY_SETTING') | ||||
| # File upload Configurations. | # File upload Configurations. |
| from controllers.console import api | from controllers.console import api | ||||
| from controllers.console.app.error import AppNotFoundError, ProviderNotInitializeError | from controllers.console.app.error import AppNotFoundError, ProviderNotInitializeError | ||||
| from controllers.console.setup import setup_required | from controllers.console.setup import setup_required | ||||
| from controllers.console.wraps import account_initialization_required | |||||
| from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check | |||||
| from core.model_providers.error import ProviderTokenNotInitError, LLMBadRequestError | from core.model_providers.error import ProviderTokenNotInitError, LLMBadRequestError | ||||
| from core.model_providers.model_factory import ModelFactory | from core.model_providers.model_factory import ModelFactory | ||||
| from core.model_providers.model_provider_factory import ModelProviderFactory | from core.model_providers.model_provider_factory import ModelProviderFactory | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @marshal_with(app_detail_fields) | @marshal_with(app_detail_fields) | ||||
| @cloud_edition_billing_resource_check('apps') | |||||
| def post(self): | def post(self): | ||||
| """Create app""" | """Create app""" | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() |
| from controllers.console.datasets.error import DocumentAlreadyFinishedError, InvalidActionError, DocumentIndexingError, \ | from controllers.console.datasets.error import DocumentAlreadyFinishedError, InvalidActionError, DocumentIndexingError, \ | ||||
| InvalidMetadataError, ArchivedDocumentImmutableError | InvalidMetadataError, ArchivedDocumentImmutableError | ||||
| from controllers.console.setup import setup_required | from controllers.console.setup import setup_required | ||||
| from controllers.console.wraps import account_initialization_required | |||||
| from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check | |||||
| from core.indexing_runner import IndexingRunner | from core.indexing_runner import IndexingRunner | ||||
| from core.model_providers.error import ProviderTokenNotInitError, QuotaExceededError, ModelCurrentlyNotSupportError, \ | from core.model_providers.error import ProviderTokenNotInitError, QuotaExceededError, ModelCurrentlyNotSupportError, \ | ||||
| LLMBadRequestError | LLMBadRequestError | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @marshal_with(documents_and_batch_fields) | @marshal_with(documents_and_batch_fields) | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def post(self, dataset_id): | def post(self, dataset_id): | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @marshal_with(dataset_and_document_fields) | @marshal_with(dataset_and_document_fields) | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def post(self): | def post(self): | ||||
| # The role of the current user in the ta table must be admin or owner | # The role of the current user in the ta table must be admin or owner | ||||
| if current_user.current_tenant.current_role not in ['admin', 'owner']: | if current_user.current_tenant.current_role not in ['admin', 'owner']: | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def patch(self, dataset_id, document_id, action): | def patch(self, dataset_id, document_id, action): | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) | ||||
| document_id = str(document_id) | document_id = str(document_id) | ||||
| if not document.archived: | if not document.archived: | ||||
| raise InvalidActionError('Document is not archived.') | raise InvalidActionError('Document is not archived.') | ||||
| # check document limit | |||||
| if current_app.config['EDITION'] == 'CLOUD': | |||||
| documents_count = DocumentService.get_tenant_documents_count() | |||||
| total_count = documents_count + 1 | |||||
| tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT']) | |||||
| if total_count > tenant_document_count: | |||||
| raise ValueError(f"All your documents have overed limit {tenant_document_count}.") | |||||
| document.archived = False | document.archived = False | ||||
| document.archived_at = None | document.archived_at = None | ||||
| document.archived_by = None | document.archived_by = None | ||||
| return {'result': 'success'}, 204 | return {'result': 'success'}, 204 | ||||
| class DocumentLimitApi(DocumentResource): | |||||
| @setup_required | |||||
| @login_required | |||||
| @account_initialization_required | |||||
| def get(self): | |||||
| """get document limit""" | |||||
| documents_count = DocumentService.get_tenant_documents_count() | |||||
| tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT']) | |||||
| return { | |||||
| 'documents_count': documents_count, | |||||
| 'documents_limit': tenant_document_count | |||||
| }, 200 | |||||
| api.add_resource(GetProcessRuleApi, '/datasets/process-rule') | api.add_resource(GetProcessRuleApi, '/datasets/process-rule') | ||||
| api.add_resource(DatasetDocumentListApi, | api.add_resource(DatasetDocumentListApi, | ||||
| '/datasets/<uuid:dataset_id>/documents') | '/datasets/<uuid:dataset_id>/documents') | ||||
| '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/status/<string:action>') | '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/status/<string:action>') | ||||
| api.add_resource(DocumentPauseApi, '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/pause') | api.add_resource(DocumentPauseApi, '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/pause') | ||||
| api.add_resource(DocumentRecoverApi, '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/resume') | api.add_resource(DocumentRecoverApi, '/datasets/<uuid:dataset_id>/documents/<uuid:document_id>/processing/resume') | ||||
| api.add_resource(DocumentLimitApi, '/datasets/limit') |
| from controllers.console.app.error import ProviderNotInitializeError | from controllers.console.app.error import ProviderNotInitializeError | ||||
| from controllers.console.datasets.error import InvalidActionError, NoFileUploadedError, TooManyFilesError | from controllers.console.datasets.error import InvalidActionError, NoFileUploadedError, TooManyFilesError | ||||
| from controllers.console.setup import setup_required | from controllers.console.setup import setup_required | ||||
| from controllers.console.wraps import account_initialization_required | |||||
| from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check | |||||
| from core.model_providers.error import LLMBadRequestError, ProviderTokenNotInitError | from core.model_providers.error import LLMBadRequestError, ProviderTokenNotInitError | ||||
| from core.model_providers.model_factory import ModelFactory | from core.model_providers.model_factory import ModelFactory | ||||
| from libs.login import login_required | from libs.login import login_required | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def patch(self, dataset_id, segment_id, action): | def patch(self, dataset_id, segment_id, action): | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) | ||||
| dataset = DatasetService.get_dataset(dataset_id) | dataset = DatasetService.get_dataset(dataset_id) | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def post(self, dataset_id, document_id): | def post(self, dataset_id, document_id): | ||||
| # check dataset | # check dataset | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def patch(self, dataset_id, document_id, segment_id): | def patch(self, dataset_id, document_id, segment_id): | ||||
| # check dataset | # check dataset | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('vector_space') | |||||
| def post(self, dataset_id, document_id): | def post(self, dataset_id, document_id): | ||||
| # check dataset | # check dataset | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) |
| from fields.installed_app_fields import installed_app_list_fields | from fields.installed_app_fields import installed_app_list_fields | ||||
| from models.model import App, InstalledApp, RecommendedApp | from models.model import App, InstalledApp, RecommendedApp | ||||
| from services.account_service import TenantService | from services.account_service import TenantService | ||||
| from controllers.console.wraps import cloud_edition_billing_resource_check | |||||
| class InstalledAppsListApi(Resource): | class InstalledAppsListApi(Resource): | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('apps') | |||||
| def post(self): | def post(self): | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() | ||||
| parser.add_argument('app_id', type=str, required=True, help='Invalid app_id') | parser.add_argument('app_id', type=str, required=True, help='Invalid app_id') |
| import services | import services | ||||
| from controllers.console import api | from controllers.console import api | ||||
| from controllers.console.setup import setup_required | from controllers.console.setup import setup_required | ||||
| from controllers.console.wraps import account_initialization_required | |||||
| from controllers.console.wraps import account_initialization_required, cloud_edition_billing_resource_check | |||||
| from libs.helper import TimestampField | from libs.helper import TimestampField | ||||
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| from models.account import Account, TenantAccountJoin | from models.account import Account, TenantAccountJoin | ||||
| @setup_required | @setup_required | ||||
| @login_required | @login_required | ||||
| @account_initialization_required | @account_initialization_required | ||||
| @cloud_edition_billing_resource_check('members') | |||||
| def post(self): | def post(self): | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() | ||||
| parser.add_argument('emails', type=str, required=True, location='json', action='append') | parser.add_argument('emails', type=str, required=True, location='json', action='append') |
| from flask_login import current_user | from flask_login import current_user | ||||
| from controllers.console.workspace.error import AccountNotInitializedError | from controllers.console.workspace.error import AccountNotInitializedError | ||||
| from services.billing_service import BillingService | |||||
| def account_initialization_required(view): | def account_initialization_required(view): | ||||
| return view(*args, **kwargs) | return view(*args, **kwargs) | ||||
| return decorated | return decorated | ||||
| def cloud_edition_billing_resource_check(resource: str, | |||||
| error_msg: str = "You have reached the limit of your subscription."): | |||||
| def interceptor(view): | |||||
| @wraps(view) | |||||
| def decorated(*args, **kwargs): | |||||
| if current_app.config['EDITION'] == 'CLOUD': | |||||
| tenant_id = current_user.current_tenant_id | |||||
| billing_info = BillingService.get_info(tenant_id) | |||||
| members = billing_info['members'] | |||||
| apps = billing_info['apps'] | |||||
| vector_space = billing_info['vector_space'] | |||||
| if resource == 'members' and 0 < members['limit'] <= members['size']: | |||||
| abort(403, error_msg) | |||||
| elif resource == 'apps' and 0 < apps['limit'] <= apps['size']: | |||||
| abort(403, error_msg) | |||||
| elif resource == 'vector_space' and 0 < vector_space['limit'] <= vector_space['size']: | |||||
| abort(403, error_msg) | |||||
| else: | |||||
| return view(*args, **kwargs) | |||||
| return view(*args, **kwargs) | |||||
| return decorated | |||||
| return interceptor | |||||
| from controllers.service_api.app.error import ProviderNotInitializeError | from controllers.service_api.app.error import ProviderNotInitializeError | ||||
| from controllers.service_api.dataset.error import ArchivedDocumentImmutableError, DocumentIndexingError, \ | from controllers.service_api.dataset.error import ArchivedDocumentImmutableError, DocumentIndexingError, \ | ||||
| NoFileUploadedError, TooManyFilesError | NoFileUploadedError, TooManyFilesError | ||||
| from controllers.service_api.wraps import DatasetApiResource | |||||
| from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check | |||||
| from libs.login import current_user | from libs.login import current_user | ||||
| from core.model_providers.error import ProviderTokenNotInitError | from core.model_providers.error import ProviderTokenNotInitError | ||||
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| class DocumentAddByTextApi(DatasetApiResource): | class DocumentAddByTextApi(DatasetApiResource): | ||||
| """Resource for documents.""" | """Resource for documents.""" | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id): | def post(self, tenant_id, dataset_id): | ||||
| """Create document by text.""" | """Create document by text.""" | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() | ||||
| class DocumentUpdateByTextApi(DatasetApiResource): | class DocumentUpdateByTextApi(DatasetApiResource): | ||||
| """Resource for update documents.""" | """Resource for update documents.""" | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id, document_id): | def post(self, tenant_id, dataset_id, document_id): | ||||
| """Update document by text.""" | """Update document by text.""" | ||||
| parser = reqparse.RequestParser() | parser = reqparse.RequestParser() | ||||
| class DocumentAddByFileApi(DatasetApiResource): | class DocumentAddByFileApi(DatasetApiResource): | ||||
| """Resource for documents.""" | """Resource for documents.""" | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id): | def post(self, tenant_id, dataset_id): | ||||
| """Create document by upload file.""" | """Create document by upload file.""" | ||||
| args = {} | args = {} | ||||
| class DocumentUpdateByFileApi(DatasetApiResource): | class DocumentUpdateByFileApi(DatasetApiResource): | ||||
| """Resource for update documents.""" | """Resource for update documents.""" | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id, document_id): | def post(self, tenant_id, dataset_id, document_id): | ||||
| """Update document by upload file.""" | """Update document by upload file.""" | ||||
| args = {} | args = {} |
| from werkzeug.exceptions import NotFound | from werkzeug.exceptions import NotFound | ||||
| from controllers.service_api import api | from controllers.service_api import api | ||||
| from controllers.service_api.app.error import ProviderNotInitializeError | from controllers.service_api.app.error import ProviderNotInitializeError | ||||
| from controllers.service_api.wraps import DatasetApiResource | |||||
| from controllers.service_api.wraps import DatasetApiResource, cloud_edition_billing_resource_check | |||||
| from core.model_providers.error import ProviderTokenNotInitError, LLMBadRequestError | from core.model_providers.error import ProviderTokenNotInitError, LLMBadRequestError | ||||
| from core.model_providers.model_factory import ModelFactory | from core.model_providers.model_factory import ModelFactory | ||||
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| class SegmentApi(DatasetApiResource): | class SegmentApi(DatasetApiResource): | ||||
| """Resource for segments.""" | """Resource for segments.""" | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id, document_id): | def post(self, tenant_id, dataset_id, document_id): | ||||
| """Create single segment.""" | """Create single segment.""" | ||||
| # check dataset | # check dataset | ||||
| SegmentService.delete_segment(segment, document, dataset) | SegmentService.delete_segment(segment, document, dataset) | ||||
| return {'result': 'success'}, 200 | return {'result': 'success'}, 200 | ||||
| @cloud_edition_billing_resource_check('vector_space', 'dataset') | |||||
| def post(self, tenant_id, dataset_id, document_id, segment_id): | def post(self, tenant_id, dataset_id, document_id, segment_id): | ||||
| # check dataset | # check dataset | ||||
| dataset_id = str(dataset_id) | dataset_id = str(dataset_id) |
| from extensions.ext_database import db | from extensions.ext_database import db | ||||
| from models.account import Tenant, TenantAccountJoin, Account | from models.account import Tenant, TenantAccountJoin, Account | ||||
| from models.model import ApiToken, App | from models.model import ApiToken, App | ||||
| from services.billing_service import BillingService | |||||
| def validate_app_token(view=None): | def validate_app_token(view=None): | ||||
| return decorator | return decorator | ||||
| def cloud_edition_billing_resource_check(resource: str, | |||||
| api_token_type: str, | |||||
| error_msg: str = "You have reached the limit of your subscription."): | |||||
| def interceptor(view): | |||||
| def decorated(*args, **kwargs): | |||||
| if current_app.config['EDITION'] == 'CLOUD': | |||||
| api_token = validate_and_get_api_token(api_token_type) | |||||
| billing_info = BillingService.get_info(api_token.tenant_id) | |||||
| members = billing_info['members'] | |||||
| apps = billing_info['apps'] | |||||
| vector_space = billing_info['vector_space'] | |||||
| if resource == 'members' and 0 < members['limit'] <= members['size']: | |||||
| raise Unauthorized(error_msg) | |||||
| elif resource == 'apps' and 0 < apps['limit'] <= apps['size']: | |||||
| raise Unauthorized(error_msg) | |||||
| elif resource == 'vector_space' and 0 < vector_space['limit'] <= vector_space['size']: | |||||
| raise Unauthorized(error_msg) | |||||
| else: | |||||
| return view(*args, **kwargs) | |||||
| return view(*args, **kwargs) | |||||
| return decorated | |||||
| return interceptor | |||||
| def validate_dataset_token(view=None): | def validate_dataset_token(view=None): | ||||
| def decorator(view): | def decorator(view): | ||||
| @wraps(view) | @wraps(view) |
| import os | import os | ||||
| import requests | import requests | ||||
| from services.dataset_service import DatasetService | |||||
| class BillingService: | class BillingService: | ||||
| base_url = os.environ.get('BILLING_API_URL', 'BILLING_API_URL') | base_url = os.environ.get('BILLING_API_URL', 'BILLING_API_URL') | ||||
| billing_info = cls._send_request('GET', '/info', params=params) | billing_info = cls._send_request('GET', '/info', params=params) | ||||
| vector_size = DatasetService.get_tenant_datasets_usage(tenant_id) | |||||
| # Convert bytes to MB | |||||
| billing_info['vector_space']['size'] = int(vector_size / 1024 / 1024) | |||||
| return billing_info | return billing_info | ||||
| @classmethod | @classmethod | ||||
| def get_subscription(cls, plan: str, interval: str, prefilled_email: str = '', user_name: str = '', tenant_id: str = ''): | |||||
| def get_subscription(cls, plan: str, | |||||
| interval: str, | |||||
| prefilled_email: str = '', | |||||
| user_name: str = '', | |||||
| tenant_id: str = ''): | |||||
| params = { | params = { | ||||
| 'plan': plan, | 'plan': plan, | ||||
| 'interval': interval, | 'interval': interval, |
| return AppDatasetJoin.query.filter(AppDatasetJoin.dataset_id == dataset_id) \ | return AppDatasetJoin.query.filter(AppDatasetJoin.dataset_id == dataset_id) \ | ||||
| .order_by(db.desc(AppDatasetJoin.created_at)).all() | .order_by(db.desc(AppDatasetJoin.created_at)).all() | ||||
| @staticmethod | |||||
| def get_tenant_datasets_usage(tenant_id): | |||||
| # get the high_quality datasets | |||||
| dataset_ids = db.session.query(Dataset.id).filter(Dataset.indexing_technique == 'high_quality', | |||||
| Dataset.tenant_id == tenant_id).all() | |||||
| if not dataset_ids: | |||||
| return 0 | |||||
| dataset_ids = [result[0] for result in dataset_ids] | |||||
| document_ids = db.session.query(Document.id).filter(Document.dataset_id.in_(dataset_ids), | |||||
| Document.tenant_id == tenant_id, | |||||
| Document.completed_at.isnot(None), | |||||
| Document.enabled == True, | |||||
| Document.archived == False | |||||
| ).all() | |||||
| if not document_ids: | |||||
| return 0 | |||||
| document_ids = [result[0] for result in document_ids] | |||||
| document_segments = db.session.query(DocumentSegment).filter(DocumentSegment.document_id.in_(document_ids), | |||||
| DocumentSegment.tenant_id == tenant_id, | |||||
| DocumentSegment.completed_at.isnot(None), | |||||
| DocumentSegment.enabled == True, | |||||
| ).all() | |||||
| if not document_segments: | |||||
| return 0 | |||||
| total_words_size = sum(document_segment.word_count * 3 for document_segment in document_segments) | |||||
| total_vector_size = 1536 * 4 * len(document_segments) | |||||
| return total_words_size + total_vector_size | |||||
| class DocumentService: | class DocumentService: | ||||
| DEFAULT_RULES = { | DEFAULT_RULES = { | ||||
| notion_info_list = document_data["data_source"]['info_list']['notion_info_list'] | notion_info_list = document_data["data_source"]['info_list']['notion_info_list'] | ||||
| for notion_info in notion_info_list: | for notion_info in notion_info_list: | ||||
| count = count + len(notion_info['pages']) | count = count + len(notion_info['pages']) | ||||
| documents_count = DocumentService.get_tenant_documents_count() | |||||
| total_count = documents_count + count | |||||
| tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT']) | |||||
| if total_count > tenant_document_count: | |||||
| raise ValueError(f"over document limit {tenant_document_count}.") | |||||
| # if dataset is empty, update dataset data_source_type | # if dataset is empty, update dataset data_source_type | ||||
| if not dataset.data_source_type: | if not dataset.data_source_type: | ||||
| dataset.data_source_type = document_data["data_source"]["type"] | dataset.data_source_type = document_data["data_source"]["type"] | ||||
| notion_info_list = document_data["data_source"]['info_list']['notion_info_list'] | notion_info_list = document_data["data_source"]['info_list']['notion_info_list'] | ||||
| for notion_info in notion_info_list: | for notion_info in notion_info_list: | ||||
| count = count + len(notion_info['pages']) | count = count + len(notion_info['pages']) | ||||
| # check document limit | |||||
| if current_app.config['EDITION'] == 'CLOUD': | |||||
| documents_count = DocumentService.get_tenant_documents_count() | |||||
| total_count = documents_count + count | |||||
| tenant_document_count = int(current_app.config['TENANT_DOCUMENT_COUNT']) | |||||
| if total_count > tenant_document_count: | |||||
| raise ValueError(f"All your documents have overed limit {tenant_document_count}.") | |||||
| embedding_model = None | embedding_model = None | ||||
| dataset_collection_binding_id = None | dataset_collection_binding_id = None | ||||
| retrieval_model = None | retrieval_model = None |