From c55280b61e41a9ab3027d64295620b8eefb94d3a Mon Sep 17 00:00:00 2001 From: Dallas98 <990259227@qq.com> Date: Mon, 8 Dec 2025 10:43:40 +0800 Subject: [PATCH 1/5] feat(synthesis): add evaluation task creation functionality and UI enhancements --- .../components/SynthesisTaskTab.tsx | 226 +++++++++++++++--- 1 file changed, 198 insertions(+), 28 deletions(-) diff --git a/frontend/src/pages/SynthesisTask/components/SynthesisTaskTab.tsx b/frontend/src/pages/SynthesisTask/components/SynthesisTaskTab.tsx index 8a43e3b38..15662c566 100644 --- a/frontend/src/pages/SynthesisTask/components/SynthesisTaskTab.tsx +++ b/frontend/src/pages/SynthesisTask/components/SynthesisTaskTab.tsx @@ -1,15 +1,12 @@ -import { useState, useEffect, ElementType } from "react"; -import { Card, Button, Badge, Table, Modal, message, Tooltip } from "antd"; +import { useState, useEffect } from "react"; +import { Card, Button, Table, Modal, message, Tooltip, Form, Input, Select } from "antd"; import { Plus, ArrowUp, ArrowDown, - Pause, - Play, - CheckCircle, Sparkles, } from "lucide-react"; -import { DeleteOutlined, EyeOutlined } from "@ant-design/icons"; +import { FolderOpenOutlined, DeleteOutlined, EyeOutlined, ExperimentOutlined } from "@ant-design/icons"; import { Link, useNavigate } from "react-router"; import { SearchControls } from "@/components/SearchControls"; import { formatDateTime } from "@/utils/unit"; @@ -19,6 +16,9 @@ import { archiveSynthesisTaskToDatasetUsingPost, } from "@/pages/SynthesisTask/synthesis-api"; import { createDatasetUsingPost } from "@/pages/DataManagement/dataset.api"; +import { createEvaluationTaskUsingPost } from "@/pages/DataEvaluation/evaluation.api"; +import { queryModelListUsingGet } from "@/pages/SettingsPage/settings.apis"; +import { ModelI } from "@/pages/SettingsPage/ModelAccess"; interface SynthesisTask { id: string; @@ -61,6 +61,13 @@ export default function SynthesisTaskTab() { const [pageSize, setPageSize] = useState(10); const [total, setTotal] = useState(0); const [loading, setLoading] = useState(false); + const [evalModalVisible, setEvalModalVisible] = useState(false); + const [currentEvalTask, setCurrentEvalTask] = useState(null); + const [evalLoading, setEvalLoading] = useState(false); + const [models, setModels] = useState([]); + const [modelLoading, setModelLoading] = useState(false); + + const [evalForm] = Form.useForm(); // 获取任务列表 const loadTasks = async () => { @@ -94,18 +101,6 @@ export default function SynthesisTaskTab() { // eslint-disable-next-line }, [searchQuery, filterStatus, page, pageSize]); - // 状态徽章 - const getStatusBadge = (status: string) => { - const statusConfig: Record = { - pending: { label: "等待中", color: "#F59E0B", icon: Pause }, - running: { label: "运行中", color: "#3B82F6", icon: Play }, - completed: { label: "已完成", color: "#10B981", icon: CheckCircle }, - failed: { label: "失败", color: "#EF4444", icon: Pause }, - paused: { label: "已暂停", color: "#E5E7EB", icon: Pause }, - }; - return statusConfig[status] ?? statusConfig["pending"]; - }; - // 类型映射 const typeMap: Record = { QA: "问答对生成", @@ -176,19 +171,28 @@ export default function SynthesisTaskTab() { key: "actions", fixed: "right" as const, render: (_: unknown, task: SynthesisTask) => ( -
+
+ /> - - -
- }> - setSelectedDataIds(keys as string[]), - }} - columns={Object.keys(synthesisData[0] || {}).map((key) => ({ - title: key, - dataIndex: key, - key, - render: (_: unknown, record: SynthesisDataItem) => ( - handleUpdateField(record.id, key, e.target.value)} - placeholder={`请输入${key}`} - /> - ), - }))} - /> - - )} ); } diff --git a/runtime/datamate-python/app/module/generation/interface/generation_api.py b/runtime/datamate-python/app/module/generation/interface/generation_api.py index 7dd516582..b37c09747 100644 --- a/runtime/datamate-python/app/module/generation/interface/generation_api.py +++ b/runtime/datamate-python/app/module/generation/interface/generation_api.py @@ -120,7 +120,7 @@ async def list_synthesis_tasks( name: str | None = None, db: AsyncSession = Depends(get_db) ): - """分页列出所有数据合成任务""" + """分页列出所有数据合成任务,默认按创建时间倒序""" query = select(DataSynthesisInstance) if synthesis_type: query = query.filter(DataSynthesisInstance.synthesis_type == synthesis_type) @@ -129,6 +129,9 @@ async def list_synthesis_tasks( if name: query = query.filter(DataSynthesisInstance.name.like(f"%{name}%")) + # 默认按创建时间倒序排列 + query = query.order_by(DataSynthesisInstance.created_at.desc()) + count_q = select(func.count()).select_from(query.subquery()) total = (await db.execute(count_q)).scalar_one() From 6e5fae004415c919163bca736c9c96c61801eaba Mon Sep 17 00:00:00 2001 From: Dallas98 <990259227@qq.com> Date: Wed, 10 Dec 2025 11:48:56 +0800 Subject: [PATCH 5/5] docs: update README and Makefile for clarity and new development instructions --- Makefile | 2 +- runtime/datamate-python/README.md | 36 +++++++++++++------ .../images/label-studio-adapter/Dockerfile | 27 -------------- 3 files changed, 27 insertions(+), 38 deletions(-) delete mode 100644 scripts/images/label-studio-adapter/Dockerfile diff --git a/Makefile b/Makefile index 46b12ecbb..e44ca5b6b 100644 --- a/Makefile +++ b/Makefile @@ -497,4 +497,4 @@ load-images: exit 1; \ else \ echo "Successfully loaded $$count image(s)"; \ - fi \ No newline at end of file + fi diff --git a/runtime/datamate-python/README.md b/runtime/datamate-python/README.md index d806bbeac..dd1994456 100644 --- a/runtime/datamate-python/README.md +++ b/runtime/datamate-python/README.md @@ -1,6 +1,6 @@ -# Label Studio Adapter (DataMate) +# DataMate Python Service (DataMate) -这是 DataMate 的 Label Studio Adapter 服务,负责将 DataMate 的项目与 Label Studio 同步并提供对外的 HTTP API(基于 FastAPI)。 +这是 DataMate 的 Python 服务,负责DataMate的数据合成、数据标注、数据评估等功能。 ## 简要说明 @@ -11,19 +11,23 @@ ## 快速开始(开发) -1. 克隆仓库并进入项目目录 -2. 创建并激活虚拟环境: +### 前置条件 +- Python 3.11+ +- poetry 包管理器 + +1. 克隆仓库 +```bash +git clone git@github.com:ModelEngine-Group/DataMate.git +``` +2. 进入项目目录 ```bash -python -m venv .venv -source .venv/bin/activate +cd runtime/datamate-python ``` 3. 安装依赖 -由于项目使用poetry管理依赖,你可以使用以下命令安装: - +由于项目使用poetry管理依赖,你可以使用以下命令安装:: ```bash -pip install poetry poetry install ``` 或者直接使用pip安装(如果poetry不可用): @@ -51,7 +55,11 @@ alembic upgrade head - 本地开发(默认 host/port,自动重载): ```bash -uvicorn app.main:app --reload +set -a && source .env && set +a && poetry run uvicorn app.main:app --port 18000 --log-level debug --reload +``` +或者 +```bash +poetry run python -m app.main ``` - 指定主机与端口并打开调试日志: @@ -83,6 +91,14 @@ HOST=0.0.0.0 PORT=8000 uvicorn app.main:app --reload - Swagger UI: http://127.0.0.1:8000/docs - ReDoc: http://127.0.0.1:8000/redoc (推荐使用) +## 开发新功能 +- 安装开发依赖: + +```bash +poetry add xxx +``` + + ## 使用(简要) - 所有 API 路径以 `/api` 前缀注册(见 `app/main.py` 中 `app.include_router(api_router, prefix="/api")`)。 diff --git a/scripts/images/label-studio-adapter/Dockerfile b/scripts/images/label-studio-adapter/Dockerfile deleted file mode 100644 index b240214f7..000000000 --- a/scripts/images/label-studio-adapter/Dockerfile +++ /dev/null @@ -1,27 +0,0 @@ -FROM python:3.11-slim - -WORKDIR /app - -# 安装系统依赖 -RUN apt-get update && apt-get install -y \ - gcc \ - && rm -rf /var/lib/apt/lists/* - -# 复制requirements文件 -COPY runtime/label-studio-adapter/requirements.txt . - -# 安装Python依赖 -RUN pip install --no-cache-dir -r requirements.txt - -# 复制应用代码 -COPY runtime/label-studio-adapter . - -# 复制并设置 entrypoint 脚本权限 -COPY runtime/label-studio-adapter/deploy/docker-entrypoint.sh /docker-entrypoint.sh -RUN chmod +x /docker-entrypoint.sh - -# 暴露端口 -EXPOSE 8088 - -# 使用 entrypoint 脚本启动 -ENTRYPOINT ["/docker-entrypoint.sh"] \ No newline at end of file