deepdata: core product code (backend, frontend, runtime, deepflow module)
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
"""
|
||||
Operator Market API Interfaces
|
||||
算子市场 API 接口层
|
||||
"""
|
||||
from .operator_routes import router as operator_router
|
||||
from .category_routes import router as category_router
|
||||
|
||||
|
||||
__all__ = ["operator_router", "category_router"]
|
||||
@@ -0,0 +1,65 @@
|
||||
"""
|
||||
Category API Routes
|
||||
分类 API 路由
|
||||
"""
|
||||
|
||||
from typing import Optional
|
||||
from fastapi import APIRouter, Depends, Header
|
||||
|
||||
from app.db.models.operator import Category, CategoryRelation, Operator
|
||||
from app.db.session import get_db
|
||||
from app.module.operator.repository import (
|
||||
CategoryRepository,
|
||||
CategoryRelationRepository,
|
||||
)
|
||||
from app.module.operator.repository.operator_repository import OperatorRepository
|
||||
from app.module.operator.schema import CategoryTreePagedResponse
|
||||
from app.module.operator.schema.category import PaginatedCategoryTree
|
||||
from app.module.operator.service import CategoryService
|
||||
from app.module.shared.schema import StandardResponse
|
||||
|
||||
router = APIRouter(prefix="/categories", tags=["Category"])
|
||||
|
||||
|
||||
def get_category_service() -> CategoryService:
|
||||
"""获取分类服务实例"""
|
||||
return CategoryService(
|
||||
category_repo=CategoryRepository(Category()),
|
||||
category_relation_repo=CategoryRelationRepository(CategoryRelation()),
|
||||
operator_repo=OperatorRepository(Operator()),
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/tree",
|
||||
response_model=StandardResponse[PaginatedCategoryTree],
|
||||
summary="获取分类树",
|
||||
description="获取算子树状分类结构,包含分组维度(如语言、模态)及资源统计数量。支持locale参数返回对应语言的分类名称.",
|
||||
tags=["mcp"],
|
||||
)
|
||||
async def get_category_tree(
|
||||
service: CategoryService = Depends(get_category_service),
|
||||
db=Depends(get_db),
|
||||
accept_language: Optional[str] = Header(None, alias="Accept-Language"),
|
||||
):
|
||||
"""获取分类树"""
|
||||
# 解析语言参数
|
||||
lang = None
|
||||
if accept_language:
|
||||
# Accept-Language: zh-CN,zh;q=0.0 -> 取 zh
|
||||
lang = accept_language.split(",")[0].split("-")[0].strip()
|
||||
|
||||
result = await service.get_all_categories(db, locale=lang)
|
||||
|
||||
return StandardResponse(
|
||||
code="0",
|
||||
message="success",
|
||||
data=PaginatedCategoryTree(
|
||||
page=0,
|
||||
size=len(result.categories),
|
||||
total_elements=len(result.categories),
|
||||
total_pages=1,
|
||||
star_count=result.star_count,
|
||||
content=result.categories,
|
||||
),
|
||||
)
|
||||
@@ -0,0 +1,256 @@
|
||||
"""
|
||||
Operator API Routes
|
||||
算子 API 路由
|
||||
"""
|
||||
from typing import Optional
|
||||
|
||||
from fastapi import APIRouter, Depends, UploadFile, Form, File, Body, Header
|
||||
from fastapi.responses import FileResponse
|
||||
|
||||
from app.core.logging import get_logger
|
||||
from app.db.models.operator import Operator, CategoryRelation, OperatorRelease
|
||||
from app.db.session import get_db
|
||||
from app.module.operator.parsers import ParserHolder
|
||||
from app.module.operator.repository import (
|
||||
OperatorRepository,
|
||||
CategoryRelationRepository,
|
||||
OperatorReleaseRepository,
|
||||
)
|
||||
from app.module.operator.schema import (
|
||||
OperatorDto,
|
||||
OperatorUpdateDto,
|
||||
OperatorListRequest,
|
||||
)
|
||||
from app.module.operator.service import OperatorService
|
||||
from app.module.shared.chunk_upload_repository import ChunkUploadRepository
|
||||
from app.module.shared.file_service import FileService
|
||||
from app.module.shared.schema import StandardResponse, PaginatedData
|
||||
|
||||
logger = get_logger(__name__)
|
||||
|
||||
router = APIRouter(prefix="/operators", tags=["Operator"])
|
||||
|
||||
|
||||
def get_operator_service() -> OperatorService:
|
||||
"""获取算子服务实例"""
|
||||
return OperatorService(
|
||||
operator_repo=OperatorRepository(Operator()),
|
||||
category_relation_repo=CategoryRelationRepository(CategoryRelation()),
|
||||
operator_release_repo=OperatorReleaseRepository(OperatorRelease()),
|
||||
parser_holder=ParserHolder(),
|
||||
file_service=FileService(ChunkUploadRepository()),
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/list",
|
||||
response_model=StandardResponse[PaginatedData[OperatorDto]],
|
||||
summary="查询算子列表",
|
||||
description="根据参数查询算子列表(支持分页、分类过滤、关键词搜索)",
|
||||
tags=['mcp']
|
||||
)
|
||||
async def list_operators(
|
||||
request: OperatorListRequest,
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
):
|
||||
"""查询算子列表"""
|
||||
operators = await service.get_operators(
|
||||
page=request.page,
|
||||
size=request.size,
|
||||
categories=request.categories,
|
||||
keyword=request.keyword,
|
||||
is_star=request.is_star,
|
||||
db=db
|
||||
)
|
||||
|
||||
count = await service.count_operators(
|
||||
categories=request.categories,
|
||||
keyword=request.keyword,
|
||||
is_star=request.is_star,
|
||||
db=db
|
||||
)
|
||||
|
||||
total_pages = (count + request.size - 1) // request.size
|
||||
|
||||
return StandardResponse(
|
||||
code="0",
|
||||
message="success",
|
||||
data=PaginatedData(
|
||||
page=request.page,
|
||||
size=request.size,
|
||||
total_elements=count,
|
||||
total_pages=total_pages,
|
||||
content=operators,
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/{operator_id}",
|
||||
response_model=StandardResponse[OperatorDto],
|
||||
summary="获取算子详情",
|
||||
description="根据 ID 获取算子详细信息"
|
||||
)
|
||||
async def get_operator(
|
||||
operator_id: str,
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
accept_language: Optional[str] = Header(None, alias="Accept-Language"),
|
||||
):
|
||||
"""获取算子详情"""
|
||||
# 解析语言参数
|
||||
lang = None
|
||||
if accept_language:
|
||||
# Accept-Language: zh-CN,zh;q=0.0 -> 取 zh
|
||||
lang = accept_language.split(",")[0].split("-")[0].strip()
|
||||
|
||||
operator = await service.get_operator_by_id(operator_id, db, locale=lang)
|
||||
operator.file_name = None
|
||||
return StandardResponse(code="0", message="success", data=operator)
|
||||
|
||||
|
||||
@router.put(
|
||||
"/{operator_id}",
|
||||
response_model=StandardResponse[OperatorDto],
|
||||
summary="更新算子",
|
||||
description="更新算子信息"
|
||||
)
|
||||
async def update_operator(
|
||||
operator_id: str,
|
||||
request: OperatorUpdateDto,
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""更新算子"""
|
||||
operator = await service.update_operator(operator_id, request, db)
|
||||
await db.commit()
|
||||
return StandardResponse(code="0", message="success", data=operator)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/create",
|
||||
response_model=StandardResponse[OperatorDto],
|
||||
summary="创建算子",
|
||||
description="创建新算子"
|
||||
)
|
||||
async def create_operator(
|
||||
request: OperatorDto,
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db)
|
||||
):
|
||||
"""创建算子"""
|
||||
operator = await service.create_operator(request, db)
|
||||
await db.commit()
|
||||
return StandardResponse(code="0", message="success", data=operator)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload",
|
||||
response_model=StandardResponse[OperatorDto],
|
||||
summary="上传算子",
|
||||
description="上传算子文件并解析元数据"
|
||||
)
|
||||
async def upload_operator(
|
||||
request: dict = Body(...),
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
):
|
||||
"""上传算子"""
|
||||
file_name = request.get("fileName")
|
||||
if not file_name:
|
||||
from fastapi import HTTPException
|
||||
raise HTTPException(status_code=422, detail="fileName is required")
|
||||
operator = await service.upload_operator(file_name, db)
|
||||
return StandardResponse(code="0", message="success", data=operator)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload/pre-upload",
|
||||
response_model=StandardResponse[str],
|
||||
summary="预上传",
|
||||
description="获取预上传 ID,用于分块上传"
|
||||
)
|
||||
async def pre_upload(
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
):
|
||||
"""预上传"""
|
||||
req_id = await service.pre_upload(db)
|
||||
await db.commit()
|
||||
return StandardResponse(
|
||||
code="0",
|
||||
message="success",
|
||||
data=req_id,
|
||||
)
|
||||
|
||||
|
||||
@router.post(
|
||||
"/upload/chunk",
|
||||
response_model=StandardResponse[dict],
|
||||
summary="分块上传",
|
||||
description="分块上传算子文件"
|
||||
)
|
||||
async def chunk_upload(
|
||||
req_id: str = Form(..., alias="reqId", description="预上传ID"),
|
||||
file_no: int = Form(1, alias="fileNo", description="文件编号"),
|
||||
file_name: str = Form(..., alias="fileName", description="文件名"),
|
||||
total_chunk_num: int = Form(1, alias="totalChunkNum", description="总分块数"),
|
||||
chunk_no: int = Form(1, alias="chunkNo", description="当前分块号"),
|
||||
file: UploadFile = File(...),
|
||||
check_sum_hex: Optional[str] = Form(None, alias="checkSumHex", description="校验和"),
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
):
|
||||
"""分块上传"""
|
||||
file_content = await file.read()
|
||||
result = await service.chunk_upload(
|
||||
req_id=req_id,
|
||||
file_no=file_no,
|
||||
file_name=file_name,
|
||||
total_chunk_num=total_chunk_num,
|
||||
chunk_no=chunk_no,
|
||||
check_sum_hex=check_sum_hex,
|
||||
file_content=file_content,
|
||||
db=db
|
||||
)
|
||||
await db.commit()
|
||||
return StandardResponse(code="0", message="success", data=result.dict())
|
||||
|
||||
|
||||
@router.delete(
|
||||
"/{operator_id}",
|
||||
response_model=StandardResponse[None],
|
||||
summary="删除算子",
|
||||
description="删除算子"
|
||||
)
|
||||
async def delete_operator(
|
||||
operator_id: str,
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
db = Depends(get_db),
|
||||
):
|
||||
"""删除算子"""
|
||||
await service.delete_operator(operator_id, db)
|
||||
await db.commit()
|
||||
return StandardResponse(code="0", message="success", data=None)
|
||||
|
||||
|
||||
@router.get(
|
||||
"/examples/download",
|
||||
response_class=FileResponse,
|
||||
summary="下载示例算子",
|
||||
description="下载示例算子文件"
|
||||
)
|
||||
async def download_example_operator(
|
||||
service: OperatorService = Depends(get_operator_service),
|
||||
):
|
||||
"""下载示例算子"""
|
||||
from app.module.operator.constants import EXAMPLE_OPERATOR_PATH
|
||||
|
||||
example_path = EXAMPLE_OPERATOR_PATH
|
||||
file_path = service.download_example_operator(example_path)
|
||||
return FileResponse(
|
||||
path=str(file_path),
|
||||
filename=file_path.name,
|
||||
media_type="application/octet-stream"
|
||||
)
|
||||
Reference in New Issue
Block a user