diff --git a/apps/homepage/api/home_page_api.py b/apps/homepage/api/home_page_api.py index 22f5b852ca5..3af906681e3 100644 --- a/apps/homepage/api/home_page_api.py +++ b/apps/homepage/api/home_page_api.py @@ -400,28 +400,3 @@ def get_parameters(): description=_("Workspace ID"), ), ] - - -def system_parameters(api_class): - """系统管理端点参数:workspace_id 由 PATH 必填改为可选 query 参数(传了查指定工作空间,缺省查全局)""" - params = api_class.get_parameters() - return [ - ( - OpenApiParameter( - name="workspace_id", - type=OpenApiTypes.STR, - location=OpenApiParameter.QUERY, - required=False, - description=_("Workspace ID (optional; omit to query across all workspaces)"), - ) - if _param_name(p) == "workspace_id" - else p - ) - for p in params - ] - - -def _param_name(param): - if isinstance(param, dict): - return param.get("name") - return getattr(param, "name", None) diff --git a/apps/homepage/serializers/homepage.py b/apps/homepage/serializers/homepage.py index 1d5ccf0b52e..539577d3575 100644 --- a/apps/homepage/serializers/homepage.py +++ b/apps/homepage/serializers/homepage.py @@ -44,7 +44,6 @@ from models_provider.models import Model from system_manage.models import WorkspaceUserResourcePermission from tools.models import Tool, ToolType -from users.serializers.user import get_workspace_list_by_user _PERM_WITH_ROLE = ["VIEW", "MANAGE", "ROLE"] _PERM_DEFAULT = ["VIEW", "MANAGE"] @@ -111,613 +110,6 @@ def get_end_time(date_time): return timezone.make_aware(naive, timezone.get_default_timezone()) -def _get_authorized_resource_query_set(auth, user_id, model, auth_target_type, read_permission, workspace_id=None): - """返回当前用户授权可访问的资源 QuerySet。 - workspace_id 缺省 => 跨所有授权工作空间(全局);给出 => 仅该工作空间""" - permission_list = _PERM_WITH_ROLE if hasPermission(auth, read_permission) else _PERM_DEFAULT - if workspace_id: - # 指定工作空间:复用现有单工作空间授权逻辑 - if is_workspace_manage(auth, workspace_id): - return QuerySet(model).filter(workspace_id=workspace_id) - if is_extends_workspace_manage(auth, workspace_id): - if has_extends_workspace_manage_permission(auth, read_permission, workspace_id): - return QuerySet(model).filter(workspace_id=workspace_id) - if not has_all_permission(auth, read_permission, workspace_id): - return QuerySet(model).none() - return QuerySet(model).filter( - id__in=QuerySet(WorkspaceUserResourcePermission) - .filter( - workspace_id=workspace_id, - user_id=user_id, - auth_target_type=auth_target_type, - permission_list__overlap=permission_list, - ) - .exclude(target="default") - .annotate(target_uuid=Cast("target", output_field=UUIDField())) - .values_list("target_uuid", flat=True) - ) - # 全局:跨所有授权工作空间,单条查询 - manage_ws_ids = [ - w["id"] - for w in get_workspace_list_by_user(user_id) - if is_workspace_manage(auth, w["id"]) - or ( - is_extends_workspace_manage(auth, w["id"]) - and has_extends_workspace_manage_permission(auth, read_permission, w["id"]) - ) - ] - perm_ids = ( - QuerySet(WorkspaceUserResourcePermission) - .filter(user_id=user_id, auth_target_type=auth_target_type, permission_list__overlap=permission_list) - .exclude(target="default") - .annotate(target_uuid=Cast("target", output_field=UUIDField())) - .values_list("target_uuid", flat=True) - ) - return QuerySet(model).filter(Q(workspace_id__in=manage_ws_ids) | Q(id__in=perm_ids)) - - -def _get_authorized_application_query_set(auth, user_id, workspace_id=None): - return _get_authorized_resource_query_set( - auth, user_id, Application, "APPLICATION", PermissionConstants.APPLICATION_READ.value, workspace_id - ) - - -class SystemHomePageSerializer(serializers.Serializer): - """系统管理首页:跨所有授权工作空间的资源数据(不绑定单个工作空间)""" - - class Application(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - query_set = _get_authorized_application_query_set(auth, self.data["user_id"], self.data.get("workspace_id")) - result = query_set.aggregate( - total=Count("id"), - publish_count=Count("id", filter=Q(is_publish=True)), - un_publish_count=Count("id", filter=Q(is_publish=False)), - ) - return { - "total": result["total"], - "publish_count": result["publish_count"], - "un_publish_count": result["un_publish_count"], - } - - class Knowledge(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - query_set = _get_authorized_resource_query_set( - auth, - self.data["user_id"], - Knowledge, - "KNOWLEDGE", - PermissionConstants.KNOWLEDGE_READ.value, - self.data.get("workspace_id"), - ) - result = query_set.aggregate( - total=Count("id", distinct=True), - document_count=Count("document", distinct=True), - failure_count=Count( - "document", - filter=Q(document__status__contains="3"), - distinct=True, - ), - ) - return { - "total": result["total"] or 0, - "document_count": result["document_count"] or 0, - "failure_count": result["failure_count"] or 0, - } - - class Tool(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - query_set = _get_authorized_resource_query_set( - auth, - self.data["user_id"], - Tool, - "TOOL", - PermissionConstants.TOOL_READ.value, - self.data.get("workspace_id"), - ) - result = query_set.aggregate( - total=Count("id"), - custom_count=Count("id", filter=Q(tool_type=ToolType.CUSTOM)), - skill_count=Count("id", filter=Q(tool_type=ToolType.SKILL)), - mcp_count=Count("id", filter=Q(tool_type=ToolType.MCP)), - workflow_count=Count("id", filter=Q(tool_type=ToolType.WORKFLOW)), - data_source_count=Count("id", filter=Q(tool_type=ToolType.DATA_SOURCE)), - ) - return { - "total": result["total"] or 0, - "custom_count": result["custom_count"] or 0, - "skill_count": result["skill_count"] or 0, - "mcp_count": result["mcp_count"] or 0, - "workflow_count": result["workflow_count"] or 0, - "data_source_count": result["data_source_count"] or 0, - } - - class Model(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - query_set = _get_authorized_resource_query_set( - auth, - self.data["user_id"], - Model, - "MODEL", - PermissionConstants.MODEL_READ.value, - self.data.get("workspace_id"), - ) - result = query_set.aggregate( - total=Count("id"), - embedding_count=Count("id", filter=Q(model_type=ModelTypeConst.EMBEDDING.name)), - llm_count=Count("id", filter=Q(model_type=ModelTypeConst.LLM.name)), - ) - return { - "total": result["total"] or 0, - "embedding_count": result["embedding_count"] or 0, - "llm_count": result["llm_count"] or 0, - } - - class TokensAggregation(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - query = ChatRecord.objects.filter( - create_time__gte=get_start_time(data["start_time"]), - create_time__lte=get_end_time(data["end_time"]), - chat__application_id__in=_get_authorized_application_query_set( - auth, data["user_id"], data.get("workspace_id") - ), - ) - return query.aggregate( - total_tokens=Coalesce(Sum(F("message_tokens") + F("answer_tokens"), output_field=IntegerField()), 0) - )["total_tokens"] - - class ChatRecordAggregation(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def aggregation(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - query = ChatRecord.objects.filter( - create_time__gte=get_start_time(data["start_time"]), - create_time__lte=get_end_time(data["end_time"]), - chat__application_id__in=_get_authorized_application_query_set( - auth, data["user_id"], data.get("workspace_id") - ), - ) - return query.aggregate(total_count=Count("id"))["total_count"] - - class ApplicationTokensRanking(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Application Name")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def get_queryset(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - record_time_filter = ( - Q(chat__is_deleted=False) - & Q(chat__chatrecord__create_time__gte=get_start_time(data["start_time"])) - & Q(chat__chatrecord__create_time__lte=get_end_time(data["end_time"])) - ) - token_expr = ExpressionWrapper( - F("chat__chatrecord__message_tokens") + F("chat__chatrecord__answer_tokens"), - output_field=BigIntegerField(), - ) - queryset = _get_authorized_application_query_set(auth, data["user_id"], data.get("workspace_id")) - if data.get("name"): - queryset = queryset.filter(name__contains=data["name"]) - return queryset.annotate( - total_tokens=Coalesce( - Sum(token_expr, filter=record_time_filter), Value(0), output_field=BigIntegerField() - ), - chat_record_count_total=Count( - "chat__chatrecord__id", filter=record_time_filter, output_field=IntegerField() - ), - chat_user_count=Count( - "chat__chat_user_id", - filter=(record_time_filter & Q(chat__chat_user_id__isnull=False) & ~Q(chat__chat_user_id="")), - distinct=True, - ), - ).order_by("-total_tokens") - - def ranking(self, auth, current_page, page_size, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - queryset = self.get_queryset(auth, with_valid=False) - return page_search( - current_page, - page_size, - queryset, - lambda a: { - "id": a.id, - "name": a.name, - "total_tokens": a.total_tokens, - "chat_record_count": a.chat_record_count_total, - "chat_user_count": a.chat_user_count, - }, - ) - - def export(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - tokens_total = SystemHomePageSerializer.TokensAggregation(data=self.data).aggregation(auth) - queryset = self.get_queryset(auth, with_valid=False) - workbook = openpyxl.Workbook(write_only=True) - worksheet = workbook.create_sheet(title="Sheet1") - headers = [ - gettext("ranking"), - gettext("Application Name"), - gettext("Token consumption"), - gettext("proportion"), - gettext("number of questions"), - gettext("active users"), - gettext("Average tokens per request"), - ] - worksheet.append(headers) - index = 0 - for item in queryset: - index += 1 - total_tokens = item.total_tokens - chat_record_count_total = item.chat_record_count_total - row = [ - index, - item.name, - total_tokens, - total_tokens / tokens_total if tokens_total else 0, - item.chat_user_count, - chat_record_count_total, - total_tokens / chat_record_count_total if chat_record_count_total else 0, - ] - worksheet.append(row) - response = HttpResponse(content_type="application/vnd.ms-excel") - response["Content-Disposition"] = f'attachment; filename="data.xlsx"' - workbook.save(response) - return response - - class ApplicationQuestionRanking(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("Application Name")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def get_queryset(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - record_time_filter = ( - Q(chat__is_deleted=False) - & Q(chat__chatrecord__create_time__gte=get_start_time(data["start_time"])) - & Q(chat__chatrecord__create_time__lte=get_end_time(data["end_time"])) - ) - queryset = _get_authorized_application_query_set(auth, data["user_id"], data.get("workspace_id")) - if data.get("name"): - queryset = queryset.filter(name__contains=data["name"]) - return queryset.annotate( - chat_record_count_total=Coalesce( - Count("chat__chatrecord__id", filter=record_time_filter), Value(0), output_field=BigIntegerField() - ), - chat_user_count=Count( - "chat__chat_user_id", - filter=(record_time_filter & Q(chat__chat_user_id__isnull=False) & ~Q(chat__chat_user_id="")), - distinct=True, - ), - ).order_by("-chat_record_count_total") - - def ranking(self, auth, current_page, page_size, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - queryset = self.get_queryset(auth, with_valid=False) - return page_search( - current_page, - page_size, - queryset, - lambda a: { - "id": a.id, - "name": a.name, - "chat_record_count": a.chat_record_count_total, - "chat_user_count": a.chat_user_count, - }, - ) - - def export(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - chat_record_number = SystemHomePageSerializer.ChatRecordAggregation(data=self.data).aggregation(auth)[ - "total_count" - ] - queryset = self.get_queryset(auth, with_valid=False) - workbook = openpyxl.Workbook(write_only=True) - worksheet = workbook.create_sheet(title="Sheet1") - headers = [ - gettext("ranking"), - gettext("Application Name"), - gettext("number of questions"), - gettext("proportion"), - gettext("active users"), - gettext("Average Number of Conversation Turns per Person"), - ] - worksheet.append(headers) - index = 0 - for item in queryset: - index += 1 - row = [ - index, - item.name, - item.chat_record_count_total, - item.chat_record_count_total / chat_record_number if chat_record_number != 0 else 0, - item.chat_user_count, - item.chat_user_count / item.chat_record_count_total if item.chat_record_count_total != 0 else 0, - ] - worksheet.append(row) - response = HttpResponse(content_type="application/vnd.ms-excel") - response["Content-Disposition"] = f'attachment; filename="data.xlsx"' - workbook.save(response) - return response - - class ApplicationUserTokenRanking(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - name = serializers.CharField(required=False, allow_null=True, allow_blank=True, label=_("User Name")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def get_queryset(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - start_time = get_start_time(data["start_time"]) - end_time = get_end_time(data["end_time"]) - name = data.get("name") - - base_queryset = Chat.objects.filter( - is_deleted=False, - chat_user_id__isnull=False, - ).exclude(chat_user_id="") - - if name: - base_queryset = base_queryset.filter(asker__username__contains=name) - - base_queryset = base_queryset.filter( - application_id__in=_get_authorized_application_query_set( - auth, data["user_id"], data.get("workspace_id") - ) - ) - - asker_map = self._build_asker_map(base_queryset) - - record_time_filter = Q( - chatrecord__create_time__gte=start_time, - chatrecord__create_time__lte=end_time, - ) - - queryset = ( - base_queryset.filter(record_time_filter) - .values("chat_user_id", "chat_user_type") - .annotate( - total_tokens=Coalesce( - Sum(TOKEN_EXPR, filter=record_time_filter), - Value(0), - output_field=BigIntegerField(), - ), - chat_record_count=Count( - "chatrecord__id", - filter=record_time_filter, - distinct=True, - ), - ) - .order_by("-total_tokens") - ) - return queryset, asker_map - - def ranking(self, auth, current_page, page_size, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - queryset, asker_map = self.get_queryset(auth, with_valid=False) - return page_search( - current_page, - page_size, - queryset, - lambda item: { - "chat_user_id": item["chat_user_id"], - "chat_user_type": item["chat_user_type"], - "asker": asker_map.get((item["chat_user_id"], item["chat_user_type"])), - "total_tokens": item["total_tokens"], - "chat_record_count": item["chat_record_count"], - }, - ) - - def export(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - token_count = SystemHomePageSerializer.TokensAggregation(data=self.data).aggregation(auth) - queryset, asker_map = self.get_queryset(auth, with_valid=False) - workbook = openpyxl.Workbook(write_only=True) - worksheet = workbook.create_sheet(title="Sheet1") - headers = [ - gettext("ranking"), - gettext("User Name"), - gettext("Token consumption"), - gettext("proportion"), - gettext("number of questions"), - gettext("Average tokens per request"), - ] - worksheet.append(headers) - index = 0 - for item in queryset: - index += 1 - user_info = asker_map.get((item["chat_user_id"], item["chat_user_type"])) or {} - username = user_info.get("username", "") - total_tokens = item.get("total_tokens", 0) - chat_record_count = item.get("chat_record_count", 0) - row = [ - index, - username, - total_tokens, - total_tokens / token_count if token_count else 0, - chat_record_count, - total_tokens / chat_record_count if chat_record_count else 0, - ] - worksheet.append(row) - response = HttpResponse(content_type="application/vnd.ms-excel") - response["Content-Disposition"] = f'attachment; filename="data.xlsx"' - workbook.save(response) - return response - - @staticmethod - def _build_asker_map(base_queryset): - latest_rows = ( - base_queryset.annotate( - _rn=Window( - expression=RowNumber(), - partition_by=[F("chat_user_id"), F("chat_user_type")], - order_by=F("create_time").desc(), - ) - ) - .filter(_rn=1) - .values("chat_user_id", "chat_user_type", "asker") - ) - - return {(row["chat_user_id"], row["chat_user_type"]): row["asker"] for row in latest_rows} - - class ApplicationMonitoring(serializers.Serializer): - workspace_id = serializers.CharField(required=False, allow_null=True, label=_("Workspace ID")) - user_id = serializers.UUIDField(required=True, label=_("User ID")) - application_id = serializers.UUIDField(required=False, allow_null=True, label=_("Application ID")) - start_time = serializers.DateField(format="%Y-%m-%d", label=_("Start time")) - end_time = serializers.DateField(format="%Y-%m-%d", label=_("End time")) - - def get_customer_count_trend(self, application_queryset, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - start_time = get_start_time(self.data.get("start_time")) - end_time = get_end_time(self.data.get("end_time")) - query_set = QuerySet(ApplicationChatUserStats).filter( - create_time__gte=start_time, create_time__lte=end_time - ) - application_id = self.data.get("application_id") - if application_id: - query_set = query_set.filter(application_id=application_id) - else: - query_set = query_set.filter(application_id__in=application_queryset) - return native_search( - {"default_sql": query_set}, - select_string=get_file_content( - os.path.join(PROJECT_DIR, "apps", "application", "sql", "customer_count_trend.sql") - ), - ) - - def get_chat_record_aggregate_trend(self, auth, with_valid=True): - if with_valid: - self.is_valid(raise_exception=True) - data = self.data - start_time = get_start_time(data["start_time"]) - end_time = get_end_time(data["end_time"]) - application_id = data.get("application_id") - application_query_set = _get_authorized_application_query_set( - auth, data["user_id"], data.get("workspace_id") - ) - chat_record_aggregate_trend = native_search( - { - "default_sql": QuerySet( - model=get_dynamics_model( - { - "application_chat.application_id": models.UUIDField(), - "application_chat_record.create_time": models.DateTimeField(), - } - ) - ).filter( - **{ - **( - {"application_chat.application_id": application_id} - if application_id - else {"application_chat.application_id__in": application_query_set} - ), - "application_chat_record.create_time__gte": start_time, - "application_chat_record.create_time__lte": end_time, - } - ) - }, - select_string=get_file_content( - os.path.join(PROJECT_DIR, "apps", "application", "sql", "chat_record_count_trend.sql") - ), - ) - customer_count_trend = self.get_customer_count_trend(application_query_set, with_valid=False) - return self.merge_customer_chat_record(chat_record_aggregate_trend, customer_count_trend) - - def merge_customer_chat_record(self, chat_record_aggregate_trend: List[Dict], customer_count_trend: List[Dict]): - - return [ - { - **self.find( - chat_record_aggregate_trend, - lambda c: c.get("day").strftime("%Y-%m-%d") == day, - { - "star_num": 0, - "trample_num": 0, - "tokens_num": 0, - "chat_record_count": 0, - "customer_num": 0, - "day": day, - }, - ), - **self.find( - customer_count_trend, - lambda c: c.get("day").strftime("%Y-%m-%d") == day, - {"customer_added_count": 0}, - ), - } - for day in self.get_days_between_dates(self.data.get("start_time"), self.data.get("end_time")) - ] - - @staticmethod - def find(source_list, condition, default): - value_list = [row for row in source_list if condition(row)] - if len(value_list) > 0: - return value_list[0] - return default - - @staticmethod - def get_days_between_dates(start_date, end_date): - start_date = datetime.datetime.strptime(start_date, "%Y-%m-%d") - end_date = datetime.datetime.strptime(end_date, "%Y-%m-%d") - days = [] - current_date = start_date - while current_date <= end_date: - days.append(current_date.strftime("%Y-%m-%d")) - current_date += datetime.timedelta(days=1) - return days - - class HomePageSerializer(serializers.Serializer): class ChatRecordAggregation(serializers.Serializer): workspace_id = serializers.CharField(required=False, label=_("Workspace ID")) diff --git a/apps/homepage/urls.py b/apps/homepage/urls.py index 6026bee5417..e4fa7d33d76 100644 --- a/apps/homepage/urls.py +++ b/apps/homepage/urls.py @@ -20,18 +20,4 @@ path("workspace//homepage/question_ranking/export",views.HomePageAPI.ApplicationQuestionRankingExport.as_view()), path("workspace//homepage/tokens_ranking/export",views.HomePageAPI.ApplicationTokensRankingExport.as_view()), path("workspace//homepage/user_tokens_ranking/export",views.HomePageAPI.UserTokensRankingExport.as_view()), - - path("system/homepage/application/aggregation",views.SystemHomePageAPI.ApplicationAggregation.as_view()), - path("system/homepage/knowledge/aggregation",views.SystemHomePageAPI.KnowledgeAggregation.as_view()), - path("system/homepage/tool/aggregation",views.SystemHomePageAPI.ToolAggregation.as_view()), - path("system/homepage/model/aggregation",views.SystemHomePageAPI.ModelAggregation.as_view()), - path("system/homepage/tokens/aggregation",views.SystemHomePageAPI.TokensAggregation.as_view()), - path("system/homepage/chat_record/aggregation",views.SystemHomePageAPI.ChatRecordAggregation.as_view()), - path("system/homepage/application/tokens_ranking//",views.SystemHomePageAPI.ApplicationTokensRanking.as_view()), - path("system/homepage/application/question_ranking//",views.SystemHomePageAPI.ApplicationQuestionRanking.as_view()), - path("system/homepage/application/user_tokens_ranking//",views.SystemHomePageAPI.UserTokensRanking.as_view()), - path("system/homepage/monitoring/aggregation",views.SystemHomePageAPI.ApplicationMonitoring.as_view()), - path("system/homepage/question_ranking/export",views.SystemHomePageAPI.ApplicationQuestionRankingExport.as_view()), - path("system/homepage/tokens_ranking/export",views.SystemHomePageAPI.ApplicationTokensRankingExport.as_view()), - path("system/homepage/user_tokens_ranking/export",views.SystemHomePageAPI.UserTokensRankingExport.as_view()) ] diff --git a/apps/homepage/views/homepage.py b/apps/homepage/views/homepage.py index fc9bddbdc72..0a869e0374e 100644 --- a/apps/homepage/views/homepage.py +++ b/apps/homepage/views/homepage.py @@ -14,10 +14,8 @@ from common import result from common.auth import TokenAuth from common.auth.authentication import has_permissions -from common.auth.constants.compare_constants import CompareConstants from common.auth.constants.permission_constants import PermissionConstants from common.auth.constants.role_constants import RoleConstants -from common.auth.struct.aggregate_permission import AggregatePermission, ViewPermission from homepage.api.home_page_api import ( ApplicationTokensRankingAPI, ApplicationQuestionRankingAPI, @@ -29,9 +27,8 @@ ApplicationMonitoringAPI, TokensAggregationAPI, RankingBaseExportAPI, - system_parameters, ) -from homepage.serializers.homepage import HomePageSerializer, SystemHomePageSerializer +from homepage.serializers.homepage import HomePageSerializer from django.utils.translation import gettext_lazy as _ @@ -395,404 +392,3 @@ def get(self, request: Request, workspace_id: str): request.auth ) ) - - -class SystemHomePageAPI(APIView): - authentication_classes = [TokenAuth] - - class ApplicationAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide application data aggregation across all workspaces"), - summary=_("System application aggregation"), - operation_id="system_homepage_application_aggregation", - parameters=system_parameters(ApplicationAggregationAPI), - responses=ApplicationAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.Application( - data={"user_id": request.user.id, "workspace_id": request.query_params.get("workspace_id") or None} - ).aggregation(request.auth) - ) - - class KnowledgeAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide knowledge data aggregation across all workspaces"), - summary=_("System knowledge aggregation"), - operation_id="system_homepage_knowledge_aggregation", - parameters=system_parameters(KnowledgeAggregationAPI), - responses=KnowledgeAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.Knowledge( - data={"user_id": request.user.id, "workspace_id": request.query_params.get("workspace_id") or None} - ).aggregation(request.auth) - ) - - class ToolAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide tool data aggregation across all workspaces"), - summary=_("System tool aggregation"), - operation_id="system_homepage_tool_aggregation", - parameters=system_parameters(ToolAggregationAPI), - responses=ToolAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.Tool( - data={"user_id": request.user.id, "workspace_id": request.query_params.get("workspace_id") or None} - ).aggregation(request.auth) - ) - - class ModelAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide model data aggregation across all workspaces"), - summary=_("System model aggregation"), - operation_id="system_homepage_model_aggregation", - parameters=system_parameters(ModelAggregationAPI), - responses=ModelAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.Model( - data={"user_id": request.user.id, "workspace_id": request.query_params.get("workspace_id") or None} - ).aggregation(request.auth) - ) - - class TokensAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide tokens aggregation across all workspaces"), - summary=_("System tokens aggregation"), - operation_id="system_homepage_tokens_aggregation", - parameters=system_parameters(TokensAggregationAPI), - responses=TokensAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.TokensAggregation( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).aggregation(request.auth) - ) - - class ChatRecordAggregation(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide chat record aggregation across all workspaces"), - summary=_("System chat record aggregation"), - operation_id="system_homepage_chat_record_aggregation", - parameters=system_parameters(TokensAggregationAPI), - responses=TokensAggregationAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.ChatRecordAggregation( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).aggregation(request.auth) - ) - - class ApplicationTokensRanking(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top applications by token consumption across all workspaces"), - summary=_("System application tokens ranking"), - operation_id="system_homepage_application_tokens_ranking", - parameters=system_parameters(ApplicationTokensRankingAPI), - responses=ApplicationTokensRankingAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request, current_page: int, page_size: int): - return result.success( - SystemHomePageSerializer.ApplicationTokensRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).ranking(request.auth, current_page, page_size) - ) - - class ApplicationQuestionRanking(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top applications by question count across all workspaces"), - summary=_("System application question ranking"), - operation_id="system_homepage_application_question_ranking", - parameters=system_parameters(ApplicationQuestionRankingAPI), - responses=ApplicationQuestionRankingAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request, current_page: int, page_size: int): - return result.success( - SystemHomePageSerializer.ApplicationQuestionRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).ranking(request.auth, current_page, page_size) - ) - - class UserTokensRanking(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top users by token consumption across all workspaces"), - summary=_("System user tokens ranking"), - operation_id="system_homepage_user_tokens_ranking", - parameters=system_parameters(UserTokensRankingAPI), - responses=UserTokensRankingAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request, current_page: int, page_size: int): - return result.success( - SystemHomePageSerializer.ApplicationUserTokenRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).ranking(request.auth, current_page, page_size) - ) - - class UserTokensRankingExport(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top users by token consumption export across all workspaces"), - summary=_("System user tokens ranking export"), - operation_id="system_homepage_user_tokens_ranking_export", - parameters=system_parameters(RankingBaseExportAPI), - responses=RankingBaseExportAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_EXPORT.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return SystemHomePageSerializer.ApplicationUserTokenRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).export(request.auth) - - class ApplicationQuestionRankingExport(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top applications by question count export across all workspaces"), - summary=_("System application question ranking export"), - operation_id="system_homepage_application_question_ranking_export", - parameters=system_parameters(RankingBaseExportAPI), - responses=RankingBaseExportAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_EXPORT.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return SystemHomePageSerializer.ApplicationQuestionRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).export(request.auth) - - class ApplicationTokensRankingExport(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide top applications by token consumption export across all workspaces"), - summary=_("System application tokens ranking export"), - operation_id="system_homepage_application_tokens_ranking_export", - parameters=system_parameters(RankingBaseExportAPI), - responses=RankingBaseExportAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_EXPORT.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return SystemHomePageSerializer.ApplicationTokensRanking( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "name": request.query_params.get("name"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).export(request.auth) - - class ApplicationMonitoring(APIView): - authentication_classes = [TokenAuth] - - @extend_schema( - methods=["GET"], - description=_("System-wide dialogue monitoring trends across all workspaces"), - summary=_("System application monitoring"), - operation_id="system_homepage_application_monitoring", - parameters=system_parameters(ApplicationMonitoringAPI), - responses=ApplicationMonitoringAPI.get_response(), - tags=[_("System home page")], # type: ignore - ) - @has_permissions( - RoleConstants.ADMIN, - ViewPermission( - roles=[RoleConstants.EXTENDS_ADMIN], - permissions=[PermissionConstants.SYSTEM_HOMEPAGE_READ.value], - compare=CompareConstants.AND, - ), - ) - def get(self, request: Request): - return result.success( - SystemHomePageSerializer.ApplicationMonitoring( - data={ - "user_id": request.user.id, - "workspace_id": request.query_params.get("workspace_id") or None, - "application_id": request.query_params.get("application_id"), - "start_time": request.query_params.get("start_time"), - "end_time": request.query_params.get("end_time"), - } - ).get_chat_record_aggregate_trend(request.auth) - )