597 lines
31 KiB
Python
597 lines
31 KiB
Python
from __future__ import annotations
|
|
|
|
from typing import Any
|
|
|
|
import json
|
|
|
|
from fastapi import Depends, File, Form, Query, UploadFile
|
|
from fastapi.responses import JSONResponse, StreamingResponse
|
|
|
|
from fastapi_common.fastapi_common_security.security import verify_access_token
|
|
from fastapi_common.fastapi_common_web.controller import BaseController
|
|
from fastapi_common.fastapi_common_web.domain.responses import Result
|
|
|
|
from fastapi_modules.fastapi_leaudit.domian.Dto.ragChatDto import (
|
|
RagConversationRenameDTO,
|
|
RagChatSendMessageDTO,
|
|
RagMessageFeedbackDTO,
|
|
RagStopMessageDTO,
|
|
)
|
|
from fastapi_modules.fastapi_leaudit.domian.Dto.ragDatasetDto import (
|
|
RagDatasetBatchDocumentDeleteDTO,
|
|
RagDatasetUpdateDTO,
|
|
)
|
|
from fastapi_modules.fastapi_leaudit.domian.vo.ragChatVo import (
|
|
RagAppParametersVO,
|
|
RagChatAppListVO,
|
|
RagChatAppVO,
|
|
RagConversationPageVO,
|
|
RagConversationRenameVO,
|
|
RagMessagePageVO,
|
|
RagOperationResultVO,
|
|
)
|
|
from fastapi_modules.fastapi_leaudit.domian.vo.ragDatasetVo import (
|
|
RagDatasetBatchDeleteResultVO,
|
|
RagDatasetDetailVO,
|
|
RagDatasetDocumentItemVO,
|
|
RagDatasetDocumentPageVO,
|
|
RagDatasetPageVO,
|
|
RagDatasetRetrieveResponseVO,
|
|
RagDatasetSegmentItemVO,
|
|
RagDatasetSegmentPageVO,
|
|
RagDatasetUploadDocumentVO,
|
|
)
|
|
from fastapi_modules.fastapi_leaudit.services.impl.permissionServiceImpl import PermissionServiceImpl
|
|
from fastapi_modules.fastapi_leaudit.services.impl.ragChatServiceImpl import RagChatServiceImpl
|
|
from fastapi_modules.fastapi_leaudit.services.impl.ragDatasetServiceImpl import RagDatasetServiceImpl
|
|
from fastapi_modules.fastapi_leaudit.services.permissionService import IPermissionService
|
|
from fastapi_modules.fastapi_leaudit.services.ragChatService import IRagChatService
|
|
from fastapi_modules.fastapi_leaudit.services.ragDatasetService import IRagDatasetService
|
|
|
|
|
|
class RagChatController(BaseController):
|
|
_PERMISSIONS = {
|
|
"chat_use": "rag:chat:use",
|
|
"conversation_read": "rag:conversation:read",
|
|
"conversation_update": "rag:conversation:update",
|
|
"conversation_delete": "rag:conversation:delete",
|
|
"message_feedback": "rag:message:feedback",
|
|
"app_read": "rag:app:read",
|
|
"dataset_read": "rag:dataset:read",
|
|
"dataset_manage": "rag:dataset:manage",
|
|
"dataset_create": "rag:dataset:create",
|
|
"dataset_update": "rag:dataset:update",
|
|
"dataset_delete": "rag:dataset:delete",
|
|
}
|
|
|
|
@staticmethod
|
|
def _tenant_context(payload: dict[str, Any]) -> dict[str, str | None]:
|
|
return {
|
|
"UserArea": payload.get("area"),
|
|
"UserRole": payload.get("user_role"),
|
|
"TenantCode": payload.get("tenant_code"),
|
|
"TenantName": payload.get("tenant_name"),
|
|
}
|
|
|
|
def __init__(self):
|
|
super().__init__(prefix="/v3/rag", tags=["RAG 聊天"])
|
|
self.RagChatService: IRagChatService = RagChatServiceImpl()
|
|
self.RagDatasetService: IRagDatasetService = RagDatasetServiceImpl()
|
|
self.PermissionService: IPermissionService = PermissionServiceImpl()
|
|
|
|
@self.router.get("/apps", response_model=Result[RagChatAppListVO])
|
|
async def GetApps(payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["app_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天应用权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.GetApps(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/apps/default", response_model=Result[RagChatAppVO | None])
|
|
async def GetDefaultApp(payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["app_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看默认聊天应用权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.GetDefaultApp(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/datasets/my", response_model=Result[RagDatasetPageVO])
|
|
async def GetMyDatasets(payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.GetMyDatasets(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/datasets/admin", response_model=Result[RagDatasetPageVO])
|
|
async def GetAdminDatasets(
|
|
area: str | None = Query(None),
|
|
tenant_code: str | None = Query(None, description="租户编码,支持逗号分隔"),
|
|
onlyEnabled: bool | None = Query(None),
|
|
page: int = Query(1, ge=1),
|
|
pageSize: int = Query(20, ge=1, le=200),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_manage"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有管理知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.GetAdminDatasets(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
Area=area,
|
|
TenantFilterCode=tenant_code,
|
|
OnlyEnabled=onlyEnabled,
|
|
Page=page,
|
|
PageSize=pageSize,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.post("/datasets/admin", response_model=Result[RagDatasetDetailVO])
|
|
async def CreateAdminDataset(Body: dict[str, Any], payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_create"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有创建知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.CreateAdminDataset(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.put("/datasets/admin/{DatasetId}", response_model=Result[RagDatasetDetailVO | None])
|
|
async def UpdateAdminDataset(DatasetId: int, Body: dict[str, Any], payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有更新知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.UpdateAdminDataset(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.delete("/datasets/admin/{DatasetId}", response_model=Result[RagOperationResultVO])
|
|
async def DeleteAdminDataset(DatasetId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.DeleteAdminDataset(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/datasets/{DatasetId}", response_model=Result[RagDatasetDetailVO | None])
|
|
async def GetDatasetDetail(DatasetId: int, payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.GetDatasetDetail(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.patch("/datasets/{DatasetId}", response_model=Result[RagDatasetDetailVO | None])
|
|
async def UpdateDataset(DatasetId: int, Body: RagDatasetUpdateDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.UpdateDataset(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/datasets/{DatasetId}/documents", response_model=Result[RagDatasetDocumentPageVO])
|
|
async def GetDatasetDocuments(
|
|
DatasetId: int,
|
|
page: int = Query(1, ge=1),
|
|
limit: int = Query(20, ge=1, le=100),
|
|
keyword: str | None = Query(None),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库文档权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.GetDatasetDocuments(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
Page=page,
|
|
Limit=limit,
|
|
Keyword=keyword,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/datasets/{DatasetId}/documents/{DocumentId}", response_model=Result[RagDatasetDocumentItemVO | None])
|
|
async def GetDatasetDocumentDetail(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库文档权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagDatasetService.GetDatasetDocumentDetail(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.post("/datasets/{DatasetId}/documents", response_model=Result[RagDatasetUploadDocumentVO])
|
|
async def UploadDatasetDocument(
|
|
DatasetId: int,
|
|
file: UploadFile = File(...),
|
|
data: str | None = Form(None),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有上传知识库文档权限", "data": None})
|
|
process_config = json.loads(data) if data else None
|
|
file_bytes = await file.read()
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.UploadDatasetDocument(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
FileName=file.filename or "document",
|
|
ContentType=file.content_type,
|
|
Content=file_bytes,
|
|
ProcessConfig=process_config,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.post("/datasets/{DatasetId}/documents/{DocumentId}/update-by-file", response_model=Result[RagDatasetUploadDocumentVO])
|
|
async def UpdateDatasetDocumentByFile(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
file: UploadFile = File(...),
|
|
data: str | None = Form(None),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有重处理知识库文档权限", "data": None})
|
|
process_config = json.loads(data) if data else None
|
|
file_bytes = await file.read()
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.UpdateDatasetDocumentByFile(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
FileName=file.filename or "document",
|
|
ContentType=file.content_type,
|
|
Content=file_bytes,
|
|
ProcessConfig=process_config,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.get("/datasets/{DatasetId}/documents/{DocumentId}/indexing-status")
|
|
async def GetDatasetDocumentIndexingStatus(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库处理进度权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.GetDatasetDocumentIndexingStatus(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
)
|
|
return Result.success(data=result["data"])
|
|
|
|
@self.router.patch("/datasets/{DatasetId}/documents/status/{Action}", response_model=Result[RagOperationResultVO])
|
|
async def BatchUpdateDatasetDocumentStatus(
|
|
DatasetId: int,
|
|
Action: str,
|
|
Body: dict[str, Any],
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改知识库文档状态权限", "data": None})
|
|
enabled = Action == "enable"
|
|
if Action not in {"enable", "disable"}:
|
|
return JSONResponse(status_code=400, content={"code": 400, "msg": "当前仅支持启用和禁用", "data": None})
|
|
document_ids = Body.get("document_ids") or []
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.BatchUpdateDatasetDocumentStatus(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentIds=[int(item) for item in document_ids],
|
|
Enabled=enabled,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.get("/datasets/{DatasetId}/documents/{DocumentId}/segments", response_model=Result[RagDatasetSegmentPageVO])
|
|
async def GetDatasetDocumentSegments(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
page: int = Query(1, ge=1),
|
|
limit: int = Query(20, ge=1, le=200),
|
|
keyword: str | None = Query(None),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库分段权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.GetDatasetDocumentSegments(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
Page=page,
|
|
Limit=limit,
|
|
Keyword=keyword,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.delete("/datasets/{DatasetId}/documents/{DocumentId}", response_model=Result[RagOperationResultVO])
|
|
async def DeleteDatasetDocument(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库文档权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.DeleteDatasetDocument(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.post("/datasets/{DatasetId}/documents/batch-delete", response_model=Result[RagDatasetBatchDeleteResultVO])
|
|
async def BatchDeleteDatasetDocuments(
|
|
DatasetId: int,
|
|
Body: RagDatasetBatchDocumentDeleteDTO,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库文档权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.BatchDeleteDatasetDocuments(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentIds=Body.document_ids,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.post("/datasets/{DatasetId}/retrieve", response_model=Result[RagDatasetRetrieveResponseVO])
|
|
async def RetrieveDataset(
|
|
DatasetId: int,
|
|
Body: dict[str, Any],
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有检索知识库权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.RetrieveDataset(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
Query=str(Body.get("query") or ""),
|
|
RetrievalModel=Body.get("retrieval_model") if isinstance(Body.get("retrieval_model"), dict) else None,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.get("/datasets/{DatasetId}/documents/{DocumentId}/segments/{SegmentId}", response_model=Result[RagDatasetSegmentItemVO | None])
|
|
async def GetDatasetDocumentSegmentDetail(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
SegmentId: str,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看知识库分段权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.GetDatasetDocumentSegmentDetail(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
SegmentId=SegmentId,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.post("/datasets/{DatasetId}/documents/{DocumentId}/segments/{SegmentId}", response_model=Result[RagDatasetSegmentItemVO | None])
|
|
async def UpdateDatasetDocumentSegment(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
SegmentId: str,
|
|
Body: dict[str, Any],
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改知识库分段权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.UpdateDatasetDocumentSegment(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
SegmentId=SegmentId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.delete("/datasets/{DatasetId}/documents/{DocumentId}/segments/{SegmentId}", response_model=Result[RagOperationResultVO])
|
|
async def DeleteDatasetDocumentSegment(
|
|
DatasetId: int,
|
|
DocumentId: int,
|
|
SegmentId: str,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["dataset_delete"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除知识库分段权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
result = await self.RagDatasetService.DeleteDatasetDocumentSegment(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
DatasetId=DatasetId,
|
|
DocumentId=DocumentId,
|
|
SegmentId=SegmentId,
|
|
)
|
|
return Result.success(data=result)
|
|
|
|
@self.router.get("/chat/parameters", response_model=Result[RagAppParametersVO])
|
|
async def GetAppParameters(
|
|
appId: int | None = Query(None, description="聊天应用ID"),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"], self._PERMISSIONS["app_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天配置权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.GetAppParameters(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
AppId=appId,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.post("/chat/messages")
|
|
async def SendMessage(Body: RagChatSendMessageDTO, payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有使用 RAG 对话权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
stream = self.RagChatService.SendMessage(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
UserName=payload.get("username") or str(payload.get("user_id")),
|
|
**tenant_context,
|
|
Query=Body.query,
|
|
ConversationId=Body.conversationId,
|
|
AppId=Body.appId,
|
|
)
|
|
return StreamingResponse(
|
|
stream,
|
|
media_type="text/event-stream",
|
|
headers={"Cache-Control": "no-cache", "X-Accel-Buffering": "no", "Connection": "keep-alive"},
|
|
)
|
|
|
|
@self.router.post("/chat/messages/{MessageId}/stop", response_model=Result[RagOperationResultVO])
|
|
async def StopMessage(
|
|
MessageId: str,
|
|
Body: RagStopMessageDTO | None = None,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["chat_use"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有停止 RAG 对话权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.StopMessage(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
MessageId=MessageId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/chat/conversations", response_model=Result[RagConversationPageVO])
|
|
async def GetConversations(
|
|
appId: int | None = Query(None, description="聊天应用ID"),
|
|
page: int = Query(1, ge=1),
|
|
pageSize: int = Query(20, ge=1, le=100),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天会话权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.GetConversations(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
AppId=appId,
|
|
Page=page,
|
|
PageSize=pageSize,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.get("/chat/conversations/{ConversationId}/messages", response_model=Result[RagMessagePageVO])
|
|
async def GetConversationMessages(
|
|
ConversationId: str,
|
|
page: int = Query(1, ge=1),
|
|
pageSize: int = Query(20, ge=1, le=100),
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_read"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有查看聊天消息权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.GetConversationMessages(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
ConversationId=ConversationId,
|
|
Page=page,
|
|
PageSize=pageSize,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.patch("/chat/conversations/{ConversationId}", response_model=Result[RagConversationRenameVO])
|
|
async def RenameConversation(
|
|
ConversationId: str,
|
|
Body: RagConversationRenameDTO,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_update"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有修改聊天会话权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.RenameConversation(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
ConversationId=ConversationId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.delete("/chat/conversations/{ConversationId}", response_model=Result[RagOperationResultVO])
|
|
async def DeleteConversation(ConversationId: str, payload: dict[str, Any] = Depends(verify_access_token)):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["conversation_delete"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有删除聊天会话权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.DeleteConversation(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
ConversationId=ConversationId,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
@self.router.post("/chat/messages/{MessageId}/feedback", response_model=Result[RagOperationResultVO])
|
|
async def UpdateFeedback(
|
|
MessageId: str,
|
|
Body: RagMessageFeedbackDTO,
|
|
payload: dict[str, Any] = Depends(verify_access_token),
|
|
):
|
|
if not await self._check_permission(int(payload["user_id"]), [self._PERMISSIONS["message_feedback"]]):
|
|
return JSONResponse(status_code=403, content={"code": 403, "msg": "当前用户没有反馈聊天消息权限", "data": None})
|
|
tenant_context = self._tenant_context(payload)
|
|
data = await self.RagChatService.UpdateFeedback(
|
|
CurrentUserId=int(payload["user_id"]),
|
|
**tenant_context,
|
|
MessageId=MessageId,
|
|
Body=Body,
|
|
)
|
|
return Result.success(data=data)
|
|
|
|
async def _check_permission(self, user_id: int, permission_keys: list[str]) -> bool:
|
|
return await self.PermissionService.HasAnyPermission(UserId=user_id, PermissionKeys=permission_keys)
|