diff --git a/api/controllers/service_api/app/annotation.py b/api/controllers/service_api/app/annotation.py index 00bb9aa463..9f6b1cf52e 100644 --- a/api/controllers/service_api/app/annotation.py +++ b/api/controllers/service_api/app/annotation.py @@ -1,4 +1,5 @@ from typing import Literal +from uuid import UUID from flask import request from flask_restx import Resource @@ -78,10 +79,10 @@ class AnnotationReplyActionStatusApi(Resource): } ) @validate_app_token - def get(self, app_model: App, job_id, action): + def get(self, app_model: App, job_id: UUID, action: str): """Get the status of an annotation reply action job.""" - job_id = str(job_id) - app_annotation_job_key = f"{action}_app_annotation_job_{str(job_id)}" + job_id_str = str(job_id) + app_annotation_job_key = f"{action}_app_annotation_job_{job_id_str}" cache_result = redis_client.get(app_annotation_job_key) if cache_result is None: raise ValueError("The job does not exist.") @@ -89,10 +90,10 @@ class AnnotationReplyActionStatusApi(Resource): job_status = cache_result.decode() error_msg = "" if job_status == "error": - app_annotation_error_key = f"{action}_app_annotation_error_{str(job_id)}" + app_annotation_error_key = f"{action}_app_annotation_error_{job_id_str}" error_msg = redis_client.get(app_annotation_error_key).decode() - return {"job_id": job_id, "job_status": job_status, "error_msg": error_msg}, 200 + return {"job_id": job_id_str, "job_status": job_status, "error_msg": error_msg}, 200 @service_api_ns.route("/apps/annotations") diff --git a/api/controllers/service_api/app/conversation.py b/api/controllers/service_api/app/conversation.py index 64b2038f9c..cd247c7a8e 100644 --- a/api/controllers/service_api/app/conversation.py +++ b/api/controllers/service_api/app/conversation.py @@ -1,5 +1,6 @@ from datetime import datetime from typing import Any, Literal +from uuid import UUID from flask import request from flask_restx import Resource @@ -195,7 +196,7 @@ class ConversationDetailApi(Resource): } ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON)) - def delete(self, app_model: App, end_user: EndUser, c_id): + def delete(self, app_model: App, end_user: EndUser, c_id: UUID): """Delete a specific conversation.""" app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: @@ -224,7 +225,7 @@ class ConversationRenameApi(Resource): } ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON)) - def post(self, app_model: App, end_user: EndUser, c_id): + def post(self, app_model: App, end_user: EndUser, c_id: UUID): """Rename a conversation or auto-generate a name.""" app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: @@ -266,7 +267,7 @@ class ConversationVariablesApi(Resource): service_api_ns.models[ConversationVariableInfiniteScrollPaginationResponse.__name__], ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.QUERY)) - def get(self, app_model: App, end_user: EndUser, c_id): + def get(self, app_model: App, end_user: EndUser, c_id: UUID): """List all variables for a conversation. Conversational variables are only available for chat applications. @@ -312,7 +313,7 @@ class ConversationVariableDetailApi(Resource): service_api_ns.models[ConversationVariableResponse.__name__], ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON)) - def put(self, app_model: App, end_user: EndUser, c_id, variable_id): + def put(self, app_model: App, end_user: EndUser, c_id: UUID, variable_id: UUID): """Update a conversation variable's value. Allows updating the value of a specific conversation variable. @@ -323,13 +324,13 @@ class ConversationVariableDetailApi(Resource): raise NotChatAppError() conversation_id = str(c_id) - variable_id = str(variable_id) + variable_id_str = str(variable_id) payload = ConversationVariableUpdatePayload.model_validate(service_api_ns.payload or {}) try: variable = ConversationService.update_conversation_variable( - app_model, conversation_id, variable_id, end_user, payload.value + app_model, conversation_id, variable_id_str, end_user, payload.value ) return ConversationVariableResponse.model_validate(variable, from_attributes=True).model_dump(mode="json") except services.errors.conversation.ConversationNotExistsError: diff --git a/api/controllers/service_api/app/message.py b/api/controllers/service_api/app/message.py index 0ff0ae5104..d26d4c09b8 100644 --- a/api/controllers/service_api/app/message.py +++ b/api/controllers/service_api/app/message.py @@ -1,4 +1,5 @@ import logging +from uuid import UUID from flask import request from flask_restx import Resource @@ -94,19 +95,19 @@ class MessageFeedbackApi(Resource): } ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.JSON, required=True)) - def post(self, app_model: App, end_user: EndUser, message_id): + def post(self, app_model: App, end_user: EndUser, message_id: UUID): """Submit feedback for a message. Allows users to rate messages as like/dislike and provide optional feedback content. """ - message_id = str(message_id) + message_id_str = str(message_id) payload = MessageFeedbackPayload.model_validate(service_api_ns.payload or {}) try: MessageService.create_feedback( app_model=app_model, - message_id=message_id, + message_id=message_id_str, user=end_user, rating=FeedbackRating(payload.rating) if payload.rating else None, content=payload.content, @@ -159,19 +160,19 @@ class MessageSuggestedApi(Resource): } ) @validate_app_token(fetch_user_arg=FetchUserArg(fetch_from=WhereisUserArg.QUERY, required=True)) - def get(self, app_model: App, end_user: EndUser, message_id): + def get(self, app_model: App, end_user: EndUser, message_id: UUID): """Get suggested follow-up questions for a message. Returns AI-generated follow-up questions based on the message content. """ - message_id = str(message_id) + message_id_str = str(message_id) app_mode = AppMode.value_of(app_model.mode) if app_mode not in {AppMode.CHAT, AppMode.AGENT_CHAT, AppMode.ADVANCED_CHAT}: raise NotChatAppError() try: questions = MessageService.get_suggested_questions_after_answer( - app_model=app_model, user=end_user, message_id=message_id, invoke_from=InvokeFrom.SERVICE_API + app_model=app_model, user=end_user, message_id=message_id_str, invoke_from=InvokeFrom.SERVICE_API ) except MessageNotExistsError: raise NotFound("Message Not Exists.") diff --git a/api/controllers/service_api/dataset/dataset.py b/api/controllers/service_api/dataset/dataset.py index 4745ca1275..4bcf969701 100644 --- a/api/controllers/service_api/dataset/dataset.py +++ b/api/controllers/service_api/dataset/dataset.py @@ -1,4 +1,5 @@ from typing import Any, Literal +from uuid import UUID from flask import request from pydantic import BaseModel, ConfigDict, Field, RootModel, field_validator, model_validator @@ -336,7 +337,7 @@ class DatasetApi(DatasetApiResource): "Dataset retrieved successfully", service_api_ns.models[DatasetDetailWithPartialMembersResponse.__name__], ) - def get(self, _, dataset_id): + def get(self, _, dataset_id: UUID): dataset_id_str = str(dataset_id) dataset = DatasetService.get_dataset(dataset_id_str) if dataset is None: @@ -403,7 +404,7 @@ class DatasetApi(DatasetApiResource): service_api_ns.models[DatasetDetailWithPartialMembersResponse.__name__], ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def patch(self, _, dataset_id): + def patch(self, _, dataset_id: UUID): dataset_id_str = str(dataset_id) dataset = DatasetService.get_dataset(dataset_id_str) if dataset is None: @@ -479,7 +480,7 @@ class DatasetApi(DatasetApiResource): } ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def delete(self, _, dataset_id): + def delete(self, _, dataset_id: UUID): """ Deletes a dataset given its ID. @@ -534,7 +535,7 @@ class DocumentStatusApi(DatasetApiResource): 400: "Bad request - invalid action", } ) - def patch(self, tenant_id, dataset_id, action: Literal["enable", "disable", "archive", "un_archive"]): + def patch(self, tenant_id, dataset_id: UUID, action: Literal["enable", "disable", "archive", "un_archive"]): """ Batch update document status. diff --git a/api/controllers/service_api/dataset/document.py b/api/controllers/service_api/dataset/document.py index 1b9b9d40db..c1d1e1f0a0 100644 --- a/api/controllers/service_api/dataset/document.py +++ b/api/controllers/service_api/dataset/document.py @@ -374,7 +374,7 @@ class DocumentAddByFileApi(DatasetApiResource): @cloud_edition_billing_resource_check("vector_space", "dataset") @cloud_edition_billing_resource_check("documents", "dataset") @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id): + def post(self, tenant_id, dataset_id: UUID): """Create document by upload file.""" dataset = db.session.scalar( select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id).limit(1) @@ -395,7 +395,6 @@ class DocumentAddByFileApi(DatasetApiResource): args["doc_language"] = "English" # get dataset info - dataset_id = str(dataset_id) tenant_id = str(tenant_id) indexing_technique = args.get("indexing_technique") or dataset.indexing_technique @@ -586,17 +585,17 @@ class DocumentListApi(DatasetApiResource): 404: "Dataset not found", } ) - def get(self, tenant_id, dataset_id): - dataset_id = str(dataset_id) + def get(self, tenant_id, dataset_id: UUID): + dataset_id_str = str(dataset_id) tenant_id = str(tenant_id) query_params = DocumentListQuery.model_validate(request.args.to_dict()) dataset = db.session.scalar( - select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id).limit(1) + select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id_str).limit(1) ) if not dataset: raise NotFound("Dataset not found.") - query = select(Document).where(Document.dataset_id == dataset_id, Document.tenant_id == tenant_id) + query = select(Document).where(Document.dataset_id == dataset_id_str, Document.tenant_id == tenant_id) if query_params.status: query = DocumentService.apply_display_status_filter(query, query_params.status) @@ -646,7 +645,7 @@ class DocumentBatchDownloadZipApi(DatasetApiResource): } ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id): + def post(self, tenant_id, dataset_id: UUID): payload = DocumentBatchDownloadZipPayload.model_validate(service_api_ns.payload or {}) upload_files, download_name = DocumentService.prepare_document_batch_download_zip( @@ -681,18 +680,17 @@ class DocumentIndexingStatusApi(DatasetApiResource): 404: "Dataset or documents not found", } ) - def get(self, tenant_id, dataset_id, batch): - dataset_id = str(dataset_id) - batch = str(batch) + def get(self, tenant_id, dataset_id: UUID, batch: str): + dataset_id_str = str(dataset_id) tenant_id = str(tenant_id) # get dataset dataset = db.session.scalar( - select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id).limit(1) + select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id_str).limit(1) ) if not dataset: raise NotFound("Dataset not found.") # get documents - documents = DocumentService.get_batch_documents(dataset_id, batch) + documents = DocumentService.get_batch_documents(dataset_id_str, batch) if not documents: raise NotFound("Documents not found.") documents_status = [] @@ -757,7 +755,7 @@ class DocumentDownloadApi(DatasetApiResource): service_api_ns.models[UrlResponse.__name__], ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def get(self, tenant_id, dataset_id, document_id): + def get(self, tenant_id, dataset_id: UUID, document_id: UUID): dataset = self.get_dataset(str(dataset_id), str(tenant_id)) document = DocumentService.get_document(dataset.id, str(document_id)) @@ -785,13 +783,13 @@ class DocumentApi(DatasetApiResource): 404: "Document not found", } ) - def get(self, tenant_id, dataset_id, document_id): - dataset_id = str(dataset_id) - document_id = str(document_id) + def get(self, tenant_id, dataset_id: UUID, document_id: UUID): + dataset_id_str = str(dataset_id) + document_id_str = str(document_id) - dataset = self.get_dataset(dataset_id, tenant_id) + dataset = self.get_dataset(dataset_id_str, tenant_id) - document = DocumentService.get_document(dataset.id, document_id) + document = DocumentService.get_document(dataset.id, document_id_str) if not document: raise NotFound("Document not found.") @@ -808,15 +806,15 @@ class DocumentApi(DatasetApiResource): has_summary_index = dataset.summary_index_setting and dataset.summary_index_setting.get("enable") is True if has_summary_index and document.need_summary is True: summary_index_status = SummaryIndexService.get_document_summary_index_status( - document_id=document_id, - dataset_id=dataset_id, + document_id=document_id_str, + dataset_id=dataset_id_str, tenant_id=tenant_id, ) if metadata == "only": response = {"id": document.id, "doc_type": document.doc_type, "doc_metadata": document.doc_metadata_details} elif metadata == "without": - dataset_process_rules = DatasetService.get_process_rules(dataset_id) + dataset_process_rules = DatasetService.get_process_rules(dataset_id_str) document_process_rules = document.dataset_process_rule.to_dict() if document.dataset_process_rule else {} data_source_info = document.data_source_detail_dict response = { @@ -851,7 +849,7 @@ class DocumentApi(DatasetApiResource): "need_summary": document.need_summary if document.need_summary is not None else False, } else: - dataset_process_rules = DatasetService.get_process_rules(dataset_id) + dataset_process_rules = DatasetService.get_process_rules(dataset_id_str) document_process_rules = document.dataset_process_rule.to_dict() if document.dataset_process_rule else {} data_source_info = document.data_source_detail_dict response = { @@ -918,21 +916,21 @@ class DocumentApi(DatasetApiResource): } ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def delete(self, tenant_id, dataset_id, document_id): + def delete(self, tenant_id, dataset_id: UUID, document_id: UUID): """Delete document.""" - document_id = str(document_id) - dataset_id = str(dataset_id) + document_id_str = str(document_id) + dataset_id_str = str(dataset_id) tenant_id = str(tenant_id) # get dataset info dataset = db.session.scalar( - select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id).limit(1) + select(Dataset).where(Dataset.tenant_id == tenant_id, Dataset.id == dataset_id_str).limit(1) ) if not dataset: raise ValueError("Dataset does not exist.") - document = DocumentService.get_document(dataset.id, document_id) + document = DocumentService.get_document(dataset.id, document_id_str) # 404 if document not found if document is None: diff --git a/api/controllers/service_api/dataset/hit_testing.py b/api/controllers/service_api/dataset/hit_testing.py index 97a70f5d0e..ba914c4dd4 100644 --- a/api/controllers/service_api/dataset/hit_testing.py +++ b/api/controllers/service_api/dataset/hit_testing.py @@ -1,3 +1,5 @@ +from uuid import UUID + from controllers.common.schema import register_schema_model from controllers.console.datasets.hit_testing_base import DatasetsHitTestingBase, HitTestingPayload from controllers.service_api import service_api_ns @@ -20,7 +22,7 @@ class HitTestingApi(DatasetApiResource, DatasetsHitTestingBase): ) @service_api_ns.expect(service_api_ns.models[HitTestingPayload.__name__]) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id): + def post(self, tenant_id, dataset_id: UUID): """Perform hit testing on a dataset. Tests retrieval performance for the specified dataset. diff --git a/api/controllers/service_api/dataset/metadata.py b/api/controllers/service_api/dataset/metadata.py index 58bdd0f611..293a77fc5e 100644 --- a/api/controllers/service_api/dataset/metadata.py +++ b/api/controllers/service_api/dataset/metadata.py @@ -1,4 +1,5 @@ from typing import Literal +from uuid import UUID from flask_login import current_user from werkzeug.exceptions import NotFound @@ -57,7 +58,7 @@ class DatasetMetadataCreateServiceApi(DatasetApiResource): 201, "Metadata created successfully", service_api_ns.models[DatasetMetadataResponse.__name__] ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id): + def post(self, tenant_id, dataset_id: UUID): """Create metadata for a dataset.""" metadata_args = MetadataArgs.model_validate(service_api_ns.payload or {}) @@ -83,7 +84,7 @@ class DatasetMetadataCreateServiceApi(DatasetApiResource): @service_api_ns.response( 200, "Metadata retrieved successfully", service_api_ns.models[DatasetMetadataListResponse.__name__] ) - def get(self, tenant_id, dataset_id): + def get(self, tenant_id, dataset_id: UUID): """Get all metadata for a dataset.""" dataset_id_str = str(dataset_id) dataset = DatasetService.get_dataset(dataset_id_str) @@ -110,7 +111,7 @@ class DatasetMetadataServiceApi(DatasetApiResource): 200, "Metadata updated successfully", service_api_ns.models[DatasetMetadataResponse.__name__] ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def patch(self, tenant_id, dataset_id, metadata_id): + def patch(self, tenant_id, dataset_id: UUID, metadata_id: UUID): """Update metadata name.""" payload = MetadataUpdatePayload.model_validate(service_api_ns.payload or {}) @@ -136,7 +137,7 @@ class DatasetMetadataServiceApi(DatasetApiResource): ) @service_api_ns.response(204, "Metadata deleted successfully") @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def delete(self, tenant_id, dataset_id, metadata_id): + def delete(self, tenant_id, dataset_id: UUID, metadata_id: UUID): """Delete metadata.""" dataset_id_str = str(dataset_id) metadata_id_str = str(metadata_id) @@ -164,7 +165,7 @@ class DatasetMetadataBuiltInFieldServiceApi(DatasetApiResource): "Built-in fields retrieved successfully", service_api_ns.models[DatasetMetadataBuiltInFieldsResponse.__name__], ) - def get(self, tenant_id, dataset_id): + def get(self, tenant_id, dataset_id: UUID): """Get all built-in metadata fields.""" built_in_fields = MetadataService.get_built_in_fields() return dump_response(DatasetMetadataBuiltInFieldsResponse, {"fields": built_in_fields}), 200 @@ -186,7 +187,7 @@ class DatasetMetadataBuiltInFieldActionServiceApi(DatasetApiResource): 200, "Action completed successfully", service_api_ns.models[DatasetMetadataActionResponse.__name__] ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id, action: Literal["enable", "disable"]): + def post(self, tenant_id, dataset_id: UUID, action: Literal["enable", "disable"]): """Enable or disable built-in metadata field.""" dataset_id_str = str(dataset_id) dataset = DatasetService.get_dataset(dataset_id_str) @@ -221,7 +222,7 @@ class DocumentMetadataEditServiceApi(DatasetApiResource): service_api_ns.models[DatasetMetadataActionResponse.__name__], ) @cloud_edition_billing_rate_limit_check("knowledge", "dataset") - def post(self, tenant_id, dataset_id): + def post(self, tenant_id, dataset_id: UUID): """Update metadata for multiple documents.""" dataset_id_str = str(dataset_id) dataset = DatasetService.get_dataset(dataset_id_str)