deepdata: core product code (backend, frontend, runtime, deepflow module)

This commit is contained in:
figmar
2026-08-30 19:23:38 +08:00
commit bd3db30be9
1405 changed files with 271727 additions and 0 deletions
@@ -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"
)