You've already forked DataMate
Merge branch 'main' of github.com:ModelEngine-Group/DataMate
This commit is contained in:
2
Makefile
2
Makefile
@@ -497,4 +497,4 @@ load-images:
|
|||||||
exit 1; \
|
exit 1; \
|
||||||
else \
|
else \
|
||||||
echo "Successfully loaded $$count image(s)"; \
|
echo "Successfully loaded $$count image(s)"; \
|
||||||
fi
|
fi
|
||||||
|
|||||||
@@ -21,5 +21,5 @@ public class CollectionTaskPagingQuery extends PagingQuery {
|
|||||||
/**
|
/**
|
||||||
* 任务名称
|
* 任务名称
|
||||||
*/
|
*/
|
||||||
private String name;
|
private String keyword;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -72,7 +72,8 @@ public class CollectionTaskController{
|
|||||||
Page<CollectionTask> page = new Page<>(query.getPage(), query.getSize());
|
Page<CollectionTask> page = new Page<>(query.getPage(), query.getSize());
|
||||||
LambdaQueryWrapper<CollectionTask> wrapper = new LambdaQueryWrapper<CollectionTask>()
|
LambdaQueryWrapper<CollectionTask> wrapper = new LambdaQueryWrapper<CollectionTask>()
|
||||||
.eq(query.getStatus() != null, CollectionTask::getStatus, query.getStatus())
|
.eq(query.getStatus() != null, CollectionTask::getStatus, query.getStatus())
|
||||||
.like(StringUtils.isNotBlank(query.getName()), CollectionTask::getName, query.getName());
|
.like(StringUtils.isNotBlank(query.getKeyword()), CollectionTask::getName, query.getKeyword())
|
||||||
|
.orderByDesc(CollectionTask::getCreatedAt);
|
||||||
return ResponseEntity.ok(CollectionTaskConverter.INSTANCE.toResponse(taskService.getTasks(page, wrapper)));
|
return ResponseEntity.ok(CollectionTaskConverter.INSTANCE.toResponse(taskService.getTasks(page, wrapper)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ services:
|
|||||||
|
|
||||||
milvus:
|
milvus:
|
||||||
container_name: milvus-standalone
|
container_name: milvus-standalone
|
||||||
image: milvusdb/milvus:v2.6.2
|
image: milvusdb/milvus:v2.6.5
|
||||||
command: ["milvus", "run", "standalone"]
|
command: ["milvus", "run", "standalone"]
|
||||||
security_opt:
|
security_opt:
|
||||||
- seccomp:unconfined
|
- seccomp:unconfined
|
||||||
|
|||||||
@@ -111,7 +111,9 @@ export default function useFetchData<T>(
|
|||||||
// 同时执行主要数据获取和额外的轮询函数
|
// 同时执行主要数据获取和额外的轮询函数
|
||||||
const promises = [
|
const promises = [
|
||||||
fetchFunc({
|
fetchFunc({
|
||||||
...filter,
|
...Object.fromEntries(
|
||||||
|
Object.entries(filter).filter(([_, value]) => value != null && value.length > 0)
|
||||||
|
),
|
||||||
...extraParams,
|
...extraParams,
|
||||||
keyword,
|
keyword,
|
||||||
type: getFirstOfArray(filter?.type) || undefined,
|
type: getFirstOfArray(filter?.type) || undefined,
|
||||||
|
|||||||
@@ -1,12 +1,10 @@
|
|||||||
import React, { useState, useEffect } from "react";
|
import React, { useState } from "react";
|
||||||
import {
|
import {
|
||||||
Button,
|
Button,
|
||||||
Table,
|
Table,
|
||||||
Space,
|
Space,
|
||||||
Tag,
|
Tag,
|
||||||
message,
|
message,
|
||||||
Input,
|
|
||||||
Select,
|
|
||||||
Tooltip,
|
Tooltip,
|
||||||
Popconfirm,
|
Popconfirm,
|
||||||
Card,
|
Card,
|
||||||
@@ -16,7 +14,6 @@ import {
|
|||||||
EditOutlined,
|
EditOutlined,
|
||||||
DeleteOutlined,
|
DeleteOutlined,
|
||||||
EyeOutlined,
|
EyeOutlined,
|
||||||
FilterOutlined,
|
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
import type { ColumnsType } from "antd/es/table";
|
import type { ColumnsType } from "antd/es/table";
|
||||||
import {
|
import {
|
||||||
@@ -26,23 +23,38 @@ import {
|
|||||||
import type { AnnotationTemplate } from "../annotation.model";
|
import type { AnnotationTemplate } from "../annotation.model";
|
||||||
import TemplateForm from "./TemplateForm.tsx";
|
import TemplateForm from "./TemplateForm.tsx";
|
||||||
import TemplateDetail from "./TemplateDetail.tsx";
|
import TemplateDetail from "./TemplateDetail.tsx";
|
||||||
|
import {SearchControls} from "@/components/SearchControls.tsx";
|
||||||
const { Search } = Input;
|
import useFetchData from "@/hooks/useFetchData.ts";
|
||||||
const { Option } = Select;
|
import {
|
||||||
|
AnnotationTypeMap,
|
||||||
|
ClassificationMap,
|
||||||
|
DataTypeMap,
|
||||||
|
TemplateTypeMap
|
||||||
|
} from "@/pages/DataAnnotation/annotation.const.tsx";
|
||||||
|
|
||||||
const TemplateList: React.FC = () => {
|
const TemplateList: React.FC = () => {
|
||||||
const [templates, setTemplates] = useState<AnnotationTemplate[]>([]);
|
const filterOptions = [
|
||||||
const [loading, setLoading] = useState(false);
|
{
|
||||||
const [total, setTotal] = useState(0);
|
key: "category",
|
||||||
const [page, setPage] = useState(1);
|
label: "分类",
|
||||||
const [size, setSize] = useState(10);
|
options: [...Object.values(ClassificationMap)],
|
||||||
|
},
|
||||||
// Filters
|
{
|
||||||
const [searchText, setSearchText] = useState("");
|
key: "dataType",
|
||||||
const [categoryFilter, setCategoryFilter] = useState<string | undefined>();
|
label: "数据类型",
|
||||||
const [dataTypeFilter, setDataTypeFilter] = useState<string | undefined>();
|
options: [...Object.values(DataTypeMap)],
|
||||||
const [labelingTypeFilter, setLabelingTypeFilter] = useState<string | undefined>();
|
},
|
||||||
const [builtInFilter, setBuiltInFilter] = useState<boolean | undefined>();
|
{
|
||||||
|
key: "labelingType",
|
||||||
|
label: "标注类型",
|
||||||
|
options: [...Object.values(AnnotationTypeMap)],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
key: "builtIn",
|
||||||
|
label: "模板类型",
|
||||||
|
options: [...Object.values(TemplateTypeMap)],
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
// Modals
|
// Modals
|
||||||
const [isFormVisible, setIsFormVisible] = useState(false);
|
const [isFormVisible, setIsFormVisible] = useState(false);
|
||||||
@@ -50,35 +62,16 @@ const TemplateList: React.FC = () => {
|
|||||||
const [selectedTemplate, setSelectedTemplate] = useState<AnnotationTemplate | undefined>();
|
const [selectedTemplate, setSelectedTemplate] = useState<AnnotationTemplate | undefined>();
|
||||||
const [formMode, setFormMode] = useState<"create" | "edit">("create");
|
const [formMode, setFormMode] = useState<"create" | "edit">("create");
|
||||||
|
|
||||||
useEffect(() => {
|
const {
|
||||||
fetchTemplates();
|
loading,
|
||||||
}, [page, size, categoryFilter, dataTypeFilter, labelingTypeFilter, builtInFilter]);
|
tableData,
|
||||||
|
pagination,
|
||||||
const fetchTemplates = async () => {
|
searchParams,
|
||||||
setLoading(true);
|
setSearchParams,
|
||||||
try {
|
fetchData,
|
||||||
const params: any = {
|
handleFiltersChange,
|
||||||
page,
|
handleKeywordChange,
|
||||||
size,
|
} = useFetchData(queryAnnotationTemplatesUsingGet, undefined, undefined, undefined, undefined, 0);
|
||||||
};
|
|
||||||
|
|
||||||
if (categoryFilter) params.category = categoryFilter;
|
|
||||||
if (dataTypeFilter) params.dataType = dataTypeFilter;
|
|
||||||
if (labelingTypeFilter) params.labelingType = labelingTypeFilter;
|
|
||||||
if (builtInFilter !== undefined) params.builtIn = builtInFilter;
|
|
||||||
|
|
||||||
const response = await queryAnnotationTemplatesUsingGet(params);
|
|
||||||
if (response.code === 200 && response.data) {
|
|
||||||
setTemplates(response.data.content || []);
|
|
||||||
setTotal(response.data.total || 0);
|
|
||||||
}
|
|
||||||
} catch (error) {
|
|
||||||
message.error("获取模板列表失败");
|
|
||||||
console.error(error);
|
|
||||||
} finally {
|
|
||||||
setLoading(false);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const handleCreate = () => {
|
const handleCreate = () => {
|
||||||
setFormMode("create");
|
setFormMode("create");
|
||||||
@@ -102,7 +95,7 @@ const TemplateList: React.FC = () => {
|
|||||||
const response = await deleteAnnotationTemplateByIdUsingDelete(templateId);
|
const response = await deleteAnnotationTemplateByIdUsingDelete(templateId);
|
||||||
if (response.code === 200) {
|
if (response.code === 200) {
|
||||||
message.success("模板删除成功");
|
message.success("模板删除成功");
|
||||||
fetchTemplates();
|
fetchData();
|
||||||
} else {
|
} else {
|
||||||
message.error(response.message || "删除模板失败");
|
message.error(response.message || "删除模板失败");
|
||||||
}
|
}
|
||||||
@@ -114,15 +107,7 @@ const TemplateList: React.FC = () => {
|
|||||||
|
|
||||||
const handleFormSuccess = () => {
|
const handleFormSuccess = () => {
|
||||||
setIsFormVisible(false);
|
setIsFormVisible(false);
|
||||||
fetchTemplates();
|
fetchData();
|
||||||
};
|
|
||||||
|
|
||||||
const handleClearFilters = () => {
|
|
||||||
setCategoryFilter(undefined);
|
|
||||||
setDataTypeFilter(undefined);
|
|
||||||
setLabelingTypeFilter(undefined);
|
|
||||||
setBuiltInFilter(undefined);
|
|
||||||
setSearchText("");
|
|
||||||
};
|
};
|
||||||
|
|
||||||
const getCategoryColor = (category: string) => {
|
const getCategoryColor = (category: string) => {
|
||||||
@@ -143,7 +128,6 @@ const TemplateList: React.FC = () => {
|
|||||||
key: "name",
|
key: "name",
|
||||||
width: 200,
|
width: 200,
|
||||||
ellipsis: true,
|
ellipsis: true,
|
||||||
filteredValue: searchText ? [searchText] : null,
|
|
||||||
onFilter: (value, record) =>
|
onFilter: (value, record) =>
|
||||||
record.name.toLowerCase().includes(value.toString().toLowerCase()) ||
|
record.name.toLowerCase().includes(value.toString().toLowerCase()) ||
|
||||||
(record.description?.toLowerCase().includes(value.toString().toLowerCase()) ?? false),
|
(record.description?.toLowerCase().includes(value.toString().toLowerCase()) ?? false),
|
||||||
@@ -269,78 +253,22 @@ const TemplateList: React.FC = () => {
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const hasActiveFilters = categoryFilter || dataTypeFilter || labelingTypeFilter || builtInFilter !== undefined;
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col gap-4">
|
<div className="flex flex-col gap-4">
|
||||||
{/* Search, Filters and Buttons in one row */}
|
{/* Search, Filters and Buttons in one row */}
|
||||||
<div className="flex items-center justify-between gap-2">
|
<div className="flex items-center justify-between gap-2">
|
||||||
{/* Left side: Search and Filters */}
|
{/* Left side: Search and Filters */}
|
||||||
<div className="flex items-center gap-2 flex-wrap">
|
<div className="flex items-center gap-2 flex-wrap">
|
||||||
<Search
|
<SearchControls
|
||||||
placeholder="搜索模板..."
|
searchTerm={searchParams.keyword}
|
||||||
allowClear
|
onSearchChange={handleKeywordChange}
|
||||||
style={{ width: 300 }}
|
searchPlaceholder="搜索任务名称、描述"
|
||||||
value={searchText}
|
filters={filterOptions}
|
||||||
onChange={(e) => setSearchText(e.target.value)}
|
onFiltersChange={handleFiltersChange}
|
||||||
|
showViewToggle={true}
|
||||||
|
onReload={fetchData}
|
||||||
|
onClearFilters={() => setSearchParams({ ...searchParams, filter: {} })}
|
||||||
/>
|
/>
|
||||||
|
|
||||||
<Select
|
|
||||||
placeholder="分类"
|
|
||||||
allowClear
|
|
||||||
style={{ width: 140 }}
|
|
||||||
value={categoryFilter}
|
|
||||||
onChange={setCategoryFilter}
|
|
||||||
>
|
|
||||||
<Option value="computer-vision">计算机视觉</Option>
|
|
||||||
<Option value="nlp">自然语言处理</Option>
|
|
||||||
<Option value="audio">音频</Option>
|
|
||||||
<Option value="quality-control">质量控制</Option>
|
|
||||||
<Option value="custom">自定义</Option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
placeholder="数据类型"
|
|
||||||
allowClear
|
|
||||||
style={{ width: 120 }}
|
|
||||||
value={dataTypeFilter}
|
|
||||||
onChange={setDataTypeFilter}
|
|
||||||
>
|
|
||||||
<Option value="image">图像</Option>
|
|
||||||
<Option value="text">文本</Option>
|
|
||||||
<Option value="audio">音频</Option>
|
|
||||||
<Option value="video">视频</Option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
placeholder="标注类型"
|
|
||||||
allowClear
|
|
||||||
style={{ width: 140 }}
|
|
||||||
value={labelingTypeFilter}
|
|
||||||
onChange={setLabelingTypeFilter}
|
|
||||||
>
|
|
||||||
<Option value="classification">分类</Option>
|
|
||||||
<Option value="object-detection">目标检测</Option>
|
|
||||||
<Option value="segmentation">分割</Option>
|
|
||||||
<Option value="ner">命名实体识别</Option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
<Select
|
|
||||||
placeholder="模板类型"
|
|
||||||
allowClear
|
|
||||||
style={{ width: 120 }}
|
|
||||||
value={builtInFilter}
|
|
||||||
onChange={setBuiltInFilter}
|
|
||||||
>
|
|
||||||
<Option value={true}>系统内置</Option>
|
|
||||||
<Option value={false}>自定义</Option>
|
|
||||||
</Select>
|
|
||||||
|
|
||||||
{hasActiveFilters && (
|
|
||||||
<Button icon={<FilterOutlined />} onClick={handleClearFilters}>
|
|
||||||
清空筛选
|
|
||||||
</Button>
|
|
||||||
)}
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Right side: Create button */}
|
{/* Right side: Create button */}
|
||||||
@@ -354,20 +282,10 @@ const TemplateList: React.FC = () => {
|
|||||||
<Card>
|
<Card>
|
||||||
<Table
|
<Table
|
||||||
columns={columns}
|
columns={columns}
|
||||||
dataSource={templates}
|
dataSource={tableData}
|
||||||
rowKey="id"
|
rowKey="id"
|
||||||
loading={loading}
|
loading={loading}
|
||||||
pagination={{
|
pagination={pagination}
|
||||||
current: page,
|
|
||||||
pageSize: size,
|
|
||||||
total: total,
|
|
||||||
showSizeChanger: true,
|
|
||||||
showTotal: (total) => `共 ${total} 个模板`,
|
|
||||||
onChange: (page, pageSize) => {
|
|
||||||
setPage(page);
|
|
||||||
setSize(pageSize);
|
|
||||||
},
|
|
||||||
}}
|
|
||||||
scroll={{ x: 1400, y: "calc(100vh - 24rem)" }}
|
scroll={{ x: 1400, y: "calc(100vh - 24rem)" }}
|
||||||
/>
|
/>
|
||||||
</Card>
|
</Card>
|
||||||
|
|||||||
@@ -1,15 +1,10 @@
|
|||||||
import { get, post, put, del, download } from "@/utils/request";
|
import { get, post, put, del } from "@/utils/request";
|
||||||
|
|
||||||
// 标注任务管理相关接口
|
// 标注任务管理相关接口
|
||||||
export function queryAnnotationTasksUsingGet(params?: any) {
|
export function queryAnnotationTasksUsingGet(params?: any) {
|
||||||
return get("/api/annotation/project", params);
|
return get("/api/annotation/project", params);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取应用配置(包含 Label Studio 基础 URL)
|
|
||||||
export function getConfigUsingGet() {
|
|
||||||
return get("/api/annotation/about");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createAnnotationTaskUsingPost(data: any) {
|
export function createAnnotationTaskUsingPost(data: any) {
|
||||||
return post("/api/annotation/project", data);
|
return post("/api/annotation/project", data);
|
||||||
}
|
}
|
||||||
@@ -18,80 +13,11 @@ export function syncAnnotationTaskUsingPost(data: any) {
|
|||||||
return post(`/api/annotation/task/sync`, data);
|
return post(`/api/annotation/task/sync`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryAnnotationTaskByIdUsingGet(mappingId: string | number) {
|
|
||||||
return get(`/api/annotation/project/${mappingId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 根据源 datasetId 查询映射关系(分页)
|
|
||||||
export function queryMappingsBySourceUsingGet(datasetId: string, params?: any) {
|
|
||||||
return get(`/api/annotation/project/by-source/${datasetId}`, params);
|
|
||||||
}
|
|
||||||
export function deleteAnnotationTaskByIdUsingDelete(mappingId: string) {
|
export function deleteAnnotationTaskByIdUsingDelete(mappingId: string) {
|
||||||
// Backend expects mapping UUID as path parameter
|
// Backend expects mapping UUID as path parameter
|
||||||
return del(`/api/annotation/project/${mappingId}`);
|
return del(`/api/annotation/project/${mappingId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 智能预标注相关接口
|
|
||||||
export function preAnnotateUsingPost(data: any) {
|
|
||||||
return post("/api/v1/annotation/pre-annotate", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注数据管理接口
|
|
||||||
export function queryAnnotationDataUsingGet(
|
|
||||||
taskId: string | number,
|
|
||||||
params?: any
|
|
||||||
) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/data`, params);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function submitAnnotationUsingPost(taskId: string | number, data: any) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/annotations`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateAnnotationUsingPut(
|
|
||||||
taskId: string | number,
|
|
||||||
annotationId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return put(
|
|
||||||
`/api/v1/annotation/tasks/${taskId}/annotations/${annotationId}`,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteAnnotationUsingDelete(
|
|
||||||
taskId: string | number,
|
|
||||||
annotationId: string | number
|
|
||||||
) {
|
|
||||||
return del(`/api/v1/annotation/tasks/${taskId}/annotations/${annotationId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注任务执行控制
|
|
||||||
export function startAnnotationTaskUsingPost(taskId: string | number) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/start`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function pauseAnnotationTaskUsingPost(taskId: string | number) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/pause`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function resumeAnnotationTaskUsingPost(taskId: string | number) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/resume`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function completeAnnotationTaskUsingPost(taskId: string | number) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/complete`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注任务统计信息
|
|
||||||
export function getAnnotationTaskStatisticsUsingGet(taskId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/statistics`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAnnotationStatisticsUsingGet(params?: any) {
|
|
||||||
return get("/api/v1/annotation/statistics", params);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标签配置管理
|
// 标签配置管理
|
||||||
export function getTagConfigUsingGet() {
|
export function getTagConfigUsingGet() {
|
||||||
return get("/api/annotation/tags/config");
|
return get("/api/annotation/tags/config");
|
||||||
@@ -106,173 +32,15 @@ export function createAnnotationTemplateUsingPost(data: any) {
|
|||||||
return post("/api/annotation/template", data);
|
return post("/api/annotation/template", data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function queryAnnotationTemplateByIdUsingGet(
|
|
||||||
templateId: string | number
|
|
||||||
) {
|
|
||||||
return get(`/api/v1/annotation/templates/${templateId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateAnnotationTemplateByIdUsingPut(
|
export function updateAnnotationTemplateByIdUsingPut(
|
||||||
templateId: string | number,
|
templateId: string | number,
|
||||||
data: any
|
data: any
|
||||||
) {
|
) {
|
||||||
return put(`/api/v1/annotation/templates/${templateId}`, data);
|
return put(`/api/annotation/template/${templateId}`, data);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteAnnotationTemplateByIdUsingDelete(
|
export function deleteAnnotationTemplateByIdUsingDelete(
|
||||||
templateId: string | number
|
templateId: string | number
|
||||||
) {
|
) {
|
||||||
return del(`/api/v1/annotation/templates/${templateId}`);
|
return del(`/api/annotation/template/${templateId}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 主动学习相关接口
|
|
||||||
export function queryActiveLearningCandidatesUsingGet(
|
|
||||||
taskId: string | number,
|
|
||||||
params?: any
|
|
||||||
) {
|
|
||||||
return get(
|
|
||||||
`/api/v1/annotation/tasks/${taskId}/active-learning/candidates`,
|
|
||||||
params
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function submitActiveLearningFeedbackUsingPost(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return post(
|
|
||||||
`/api/v1/annotation/tasks/${taskId}/active-learning/feedback`,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateActiveLearningModelUsingPost(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return post(
|
|
||||||
`/api/v1/annotation/tasks/${taskId}/active-learning/update-model`,
|
|
||||||
data
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注质量控制
|
|
||||||
export function validateAnnotationsUsingPost(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/validate`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAnnotationQualityReportUsingGet(taskId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/quality-report`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注数据导入导出
|
|
||||||
export function exportAnnotationsUsingPost(taskId: string | number, data: any) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/export`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function importAnnotationsUsingPost(taskId: string | number, data: any) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/import`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function downloadAnnotationsUsingGet(
|
|
||||||
taskId: string | number,
|
|
||||||
filename?: string
|
|
||||||
) {
|
|
||||||
return download(
|
|
||||||
`/api/v1/annotation/tasks/${taskId}/download`,
|
|
||||||
null,
|
|
||||||
filename
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注者管理
|
|
||||||
export function queryAnnotatorsUsingGet(params?: any) {
|
|
||||||
return get("/api/v1/annotation/annotators", params);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function assignAnnotatorUsingPost(taskId: string | number, data: any) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/assign`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAnnotatorStatisticsUsingGet(annotatorId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/annotators/${annotatorId}/statistics`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注配置管理
|
|
||||||
export function getAnnotationConfigUsingGet(taskId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/config`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateAnnotationConfigUsingPut(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return put(`/api/v1/annotation/tasks/${taskId}/config`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注类型和标签管理
|
|
||||||
export function queryAnnotationTypesUsingGet() {
|
|
||||||
return get("/api/v1/annotation/types");
|
|
||||||
}
|
|
||||||
|
|
||||||
export function queryAnnotationLabelsUsingGet(taskId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/labels`);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function createAnnotationLabelUsingPost(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/labels`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function updateAnnotationLabelUsingPut(
|
|
||||||
taskId: string | number,
|
|
||||||
labelId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return put(`/api/v1/annotation/tasks/${taskId}/labels/${labelId}`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function deleteAnnotationLabelUsingDelete(
|
|
||||||
taskId: string | number,
|
|
||||||
labelId: string | number
|
|
||||||
) {
|
|
||||||
return del(`/api/v1/annotation/tasks/${taskId}/labels/${labelId}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 批量操作
|
|
||||||
export function batchAssignAnnotatorsUsingPost(data: any) {
|
|
||||||
return post("/api/v1/annotation/tasks/batch-assign", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function batchUpdateTaskStatusUsingPost(data: any) {
|
|
||||||
return post("/api/v1/annotation/tasks/batch-update-status", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function batchDeleteTasksUsingPost(data: { taskIds: string[] }) {
|
|
||||||
return post("/api/v1/annotation/tasks/batch-delete", data);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注进度跟踪
|
|
||||||
export function getAnnotationProgressUsingGet(taskId: string | number) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/progress`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 标注审核
|
|
||||||
export function submitAnnotationReviewUsingPost(
|
|
||||||
taskId: string | number,
|
|
||||||
data: any
|
|
||||||
) {
|
|
||||||
return post(`/api/v1/annotation/tasks/${taskId}/review`, data);
|
|
||||||
}
|
|
||||||
|
|
||||||
export function getAnnotationReviewResultsUsingGet(
|
|
||||||
taskId: string | number,
|
|
||||||
params?: any
|
|
||||||
) {
|
|
||||||
return get(`/api/v1/annotation/tasks/${taskId}/reviews`, params);
|
|
||||||
}
|
|
||||||
@@ -1,13 +1,9 @@
|
|||||||
import { StickyNote } from "lucide-react";
|
import { StickyNote } from "lucide-react";
|
||||||
import { AnnotationTaskStatus } from "./annotation.model";
|
import {AnnotationTaskStatus, AnnotationType, Classification, DataType, TemplateType} from "./annotation.model";
|
||||||
import {
|
import {
|
||||||
CheckCircleOutlined,
|
CheckCircleOutlined,
|
||||||
ClockCircleOutlined,
|
ClockCircleOutlined,
|
||||||
CloseCircleOutlined,
|
CloseCircleOutlined,
|
||||||
CustomerServiceOutlined,
|
|
||||||
FileTextOutlined,
|
|
||||||
PictureOutlined,
|
|
||||||
VideoCameraOutlined,
|
|
||||||
} from "@ant-design/icons";
|
} from "@ant-design/icons";
|
||||||
|
|
||||||
export const AnnotationTaskStatusMap = {
|
export const AnnotationTaskStatusMap = {
|
||||||
@@ -70,3 +66,75 @@ export function mapAnnotationTask(task: any) {
|
|||||||
statistics: statsArray,
|
statistics: statsArray,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const DataTypeMap = {
|
||||||
|
[DataType.TEXT]: {
|
||||||
|
label: "文本",
|
||||||
|
value: DataType.TEXT
|
||||||
|
},
|
||||||
|
[DataType.IMAGE]: {
|
||||||
|
label: "图片",
|
||||||
|
value: DataType.IMAGE
|
||||||
|
},
|
||||||
|
[DataType.AUDIO]: {
|
||||||
|
label: "音频",
|
||||||
|
value: DataType.AUDIO
|
||||||
|
},
|
||||||
|
[DataType.VIDEO]: {
|
||||||
|
label: "视频",
|
||||||
|
value: DataType.VIDEO
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const ClassificationMap = {
|
||||||
|
[Classification.COMPUTER_VERSION]: {
|
||||||
|
label: "计算机视觉",
|
||||||
|
value: Classification.COMPUTER_VERSION
|
||||||
|
},
|
||||||
|
[Classification.NLP]: {
|
||||||
|
label: "自然语言处理",
|
||||||
|
value: Classification.NLP
|
||||||
|
},
|
||||||
|
[Classification.AUDIO]: {
|
||||||
|
label: "音频",
|
||||||
|
value: Classification.AUDIO
|
||||||
|
},
|
||||||
|
[Classification.QUALITY_CONTROL]: {
|
||||||
|
label: "质量控制",
|
||||||
|
value: Classification.QUALITY_CONTROL
|
||||||
|
},
|
||||||
|
[Classification.CUSTOM]: {
|
||||||
|
label: "自定义",
|
||||||
|
value: Classification.CUSTOM
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const AnnotationTypeMap = {
|
||||||
|
[AnnotationType.CLASSIFICATION]: {
|
||||||
|
label: "分类",
|
||||||
|
value: AnnotationType.CLASSIFICATION
|
||||||
|
},
|
||||||
|
[AnnotationType.OBJECT_DETECTION]: {
|
||||||
|
label: "目标检测",
|
||||||
|
value: AnnotationType.OBJECT_DETECTION
|
||||||
|
},
|
||||||
|
[AnnotationType.SEGMENTATION]: {
|
||||||
|
label: "分割",
|
||||||
|
value: AnnotationType.SEGMENTATION
|
||||||
|
},
|
||||||
|
[AnnotationType.NER]: {
|
||||||
|
label: "命名实体识别",
|
||||||
|
value: AnnotationType.NER
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
export const TemplateTypeMap = {
|
||||||
|
[TemplateType.SYSTEM]: {
|
||||||
|
label: "系统内置",
|
||||||
|
value: TemplateType.SYSTEM
|
||||||
|
},
|
||||||
|
[TemplateType.CUSTOM]: {
|
||||||
|
label: "自定义",
|
||||||
|
value: TemplateType.CUSTOM
|
||||||
|
},
|
||||||
|
}
|
||||||
@@ -78,3 +78,30 @@ export interface AnnotationTemplateListResponse {
|
|||||||
size: number;
|
size: number;
|
||||||
totalPages: number;
|
totalPages: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum DataType {
|
||||||
|
TEXT = "text",
|
||||||
|
IMAGE = "image",
|
||||||
|
AUDIO = "audio",
|
||||||
|
VIDEO = "video",
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum Classification {
|
||||||
|
COMPUTER_VERSION = "computer-vision",
|
||||||
|
NLP = "nlp",
|
||||||
|
AUDIO = "audio",
|
||||||
|
QUALITY_CONTROL = "quality-control",
|
||||||
|
CUSTOM = "custom"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum AnnotationType {
|
||||||
|
CLASSIFICATION = "classification",
|
||||||
|
OBJECT_DETECTION = "object-detection",
|
||||||
|
SEGMENTATION = "segmentation",
|
||||||
|
NER = "ner"
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum TemplateType {
|
||||||
|
SYSTEM = "true",
|
||||||
|
CUSTOM = "false"
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { Input, Button, Radio, Form, InputNumber, App, Select } from "antd";
|
import { Input, Button, Radio, Form, App, Select } from "antd";
|
||||||
import { Link, useNavigate } from "react-router";
|
import { Link, useNavigate } from "react-router";
|
||||||
import { ArrowLeft } from "lucide-react";
|
import { ArrowLeft } from "lucide-react";
|
||||||
import { createTaskUsingPost } from "../collection.apis";
|
import { createTaskUsingPost } from "../collection.apis";
|
||||||
@@ -76,7 +76,7 @@ export default function CollectionTaskCreate() {
|
|||||||
createDataset: false,
|
createDataset: false,
|
||||||
});
|
});
|
||||||
const [scheduleExpression, setScheduleExpression] = useState({
|
const [scheduleExpression, setScheduleExpression] = useState({
|
||||||
type: SyncMode.SCHEDULED,
|
type: "once",
|
||||||
time: "00:00",
|
time: "00:00",
|
||||||
cronExpression: "0 0 0 * * ?",
|
cronExpression: "0 0 0 * * ?",
|
||||||
});
|
});
|
||||||
@@ -388,6 +388,7 @@ export default function CollectionTaskCreate() {
|
|||||||
name="createDataset"
|
name="createDataset"
|
||||||
required
|
required
|
||||||
rules={[{ required: true, message: "请选择是否创建数据集" }]}
|
rules={[{ required: true, message: "请选择是否创建数据集" }]}
|
||||||
|
tooltip={"支持后续在【数据管理】中手动创建数据集并关联至此任务。"}
|
||||||
>
|
>
|
||||||
<Radio.Group
|
<Radio.Group
|
||||||
value={isCreateDataset}
|
value={isCreateDataset}
|
||||||
|
|||||||
@@ -218,6 +218,19 @@ export default function DatasetManagementPage() {
|
|||||||
key: "type",
|
key: "type",
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
title: "状态",
|
||||||
|
dataIndex: "status",
|
||||||
|
key: "status",
|
||||||
|
render: (status: any) => {
|
||||||
|
return (
|
||||||
|
<Tag icon={status?.icon} color={status?.color}>
|
||||||
|
{status?.label}
|
||||||
|
</Tag>
|
||||||
|
);
|
||||||
|
},
|
||||||
|
width: 120,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
title: "大小",
|
title: "大小",
|
||||||
dataIndex: "size",
|
dataIndex: "size",
|
||||||
@@ -230,12 +243,12 @@ export default function DatasetManagementPage() {
|
|||||||
key: "fileCount",
|
key: "fileCount",
|
||||||
width: 100,
|
width: 100,
|
||||||
},
|
},
|
||||||
{
|
// {
|
||||||
title: "创建者",
|
// title: "创建者",
|
||||||
dataIndex: "createdBy",
|
// dataIndex: "createdBy",
|
||||||
key: "createdBy",
|
// key: "createdBy",
|
||||||
width: 120,
|
// width: 120,
|
||||||
},
|
// },
|
||||||
{
|
{
|
||||||
title: "存储路径",
|
title: "存储路径",
|
||||||
dataIndex: "targetLocation",
|
dataIndex: "targetLocation",
|
||||||
@@ -255,26 +268,6 @@ export default function DatasetManagementPage() {
|
|||||||
key: "updatedAt",
|
key: "updatedAt",
|
||||||
width: 180,
|
width: 180,
|
||||||
},
|
},
|
||||||
{
|
|
||||||
title: "描述",
|
|
||||||
dataIndex: "description",
|
|
||||||
key: "description",
|
|
||||||
width: 200,
|
|
||||||
ellipsis: true,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
title: "状态",
|
|
||||||
dataIndex: "status",
|
|
||||||
key: "status",
|
|
||||||
render: (status: any) => {
|
|
||||||
return (
|
|
||||||
<Tag icon={status?.icon} color={status?.color}>
|
|
||||||
{status?.label}
|
|
||||||
</Tag>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
width: 120,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
title: "操作",
|
title: "操作",
|
||||||
key: "actions",
|
key: "actions",
|
||||||
@@ -372,7 +365,7 @@ export default function DatasetManagementPage() {
|
|||||||
<SearchControls
|
<SearchControls
|
||||||
searchTerm={searchParams.keyword}
|
searchTerm={searchParams.keyword}
|
||||||
onSearchChange={handleKeywordChange}
|
onSearchChange={handleKeywordChange}
|
||||||
searchPlaceholder="搜索数据集名称、描述或标签..."
|
searchPlaceholder="搜索数据集名称、描述"
|
||||||
filters={filterOptions}
|
filters={filterOptions}
|
||||||
onFiltersChange={handleFiltersChange}
|
onFiltersChange={handleFiltersChange}
|
||||||
onClearFilters={() => setSearchParams({ ...searchParams, filter: {} })}
|
onClearFilters={() => setSearchParams({ ...searchParams, filter: {} })}
|
||||||
|
|||||||
@@ -21,12 +21,13 @@ export default function WelcomePage() {
|
|||||||
// 检查接口连通性的函数
|
// 检查接口连通性的函数
|
||||||
const checkDeerFlowDeploy = async (): Promise<boolean> => {
|
const checkDeerFlowDeploy = async (): Promise<boolean> => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch('/deer-flow-backend/config', { // 替换为你的实际接口地址
|
const response = await fetch('/deer-flow-backend/config', {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: {
|
headers: {
|
||||||
'Content-Type': 'application/json',
|
'Content-Type': 'application/json',
|
||||||
},
|
},
|
||||||
timeout: 5000, // 5秒超时
|
timeout: 5000, // 5秒超时
|
||||||
|
cache: 'no-store'
|
||||||
});
|
});
|
||||||
|
|
||||||
// 检查 HTTP 状态码在 200-299 范围内
|
// 检查 HTTP 状态码在 200-299 范围内
|
||||||
|
|||||||
@@ -36,6 +36,8 @@ export default function SettingsPage() {
|
|||||||
key: "webhook-config",
|
key: "webhook-config",
|
||||||
icon: <ApiOutlined />,
|
icon: <ApiOutlined />,
|
||||||
label: "Webhook",
|
label: "Webhook",
|
||||||
|
disabled: true,
|
||||||
|
title: "暂未开放"
|
||||||
},
|
},
|
||||||
]}
|
]}
|
||||||
selectedKeys={[activeTab]}
|
selectedKeys={[activeTab]}
|
||||||
|
|||||||
@@ -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
|
```bash
|
||||||
python -m venv .venv
|
git clone git@github.com:ModelEngine-Group/DataMate.git
|
||||||
source .venv/bin/activate
|
```
|
||||||
|
2. 进入项目目录
|
||||||
|
```bash
|
||||||
|
cd runtime/datamate-python
|
||||||
```
|
```
|
||||||
|
|
||||||
3. 安装依赖
|
3. 安装依赖
|
||||||
由于项目使用poetry管理依赖,你可以使用以下命令安装:
|
由于项目使用poetry管理依赖,你可以使用以下命令安装::
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
pip install poetry
|
|
||||||
poetry install
|
poetry install
|
||||||
```
|
```
|
||||||
或者直接使用pip安装(如果poetry不可用):
|
或者直接使用pip安装(如果poetry不可用):
|
||||||
@@ -51,7 +55,11 @@ alembic upgrade head
|
|||||||
- 本地开发(默认 host/port,自动重载):
|
- 本地开发(默认 host/port,自动重载):
|
||||||
|
|
||||||
```bash
|
```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
|
- Swagger UI: http://127.0.0.1:8000/docs
|
||||||
- ReDoc: http://127.0.0.1:8000/redoc (推荐使用)
|
- ReDoc: http://127.0.0.1:8000/redoc (推荐使用)
|
||||||
|
|
||||||
|
## 开发新功能
|
||||||
|
- 安装开发依赖:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
poetry add xxx
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
## 使用(简要)
|
## 使用(简要)
|
||||||
|
|
||||||
- 所有 API 路径以 `/api` 前缀注册(见 `app/main.py` 中 `app.include_router(api_router, prefix="/api")`)。
|
- 所有 API 路径以 `/api` 前缀注册(见 `app/main.py` 中 `app.include_router(api_router, prefix="/api")`)。
|
||||||
|
|||||||
121
runtime/datamate-python/poetry.lock
generated
121
runtime/datamate-python/poetry.lock
generated
@@ -869,79 +869,60 @@ files = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "greenlet"
|
name = "greenlet"
|
||||||
version = "3.2.4"
|
version = "3.3.0"
|
||||||
description = "Lightweight in-process concurrent programming"
|
description = "Lightweight in-process concurrent programming"
|
||||||
optional = false
|
optional = false
|
||||||
python-versions = ">=3.9"
|
python-versions = ">=3.10"
|
||||||
groups = ["main"]
|
groups = ["main"]
|
||||||
markers = "platform_machine == \"aarch64\" or platform_machine == \"ppc64le\" or platform_machine == \"x86_64\" or platform_machine == \"amd64\" or platform_machine == \"AMD64\" or platform_machine == \"win32\" or platform_machine == \"WIN32\""
|
|
||||||
files = [
|
files = [
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:8c68325b0d0acf8d91dde4e6f930967dd52a5302cd4062932a6b2e7c2969f47c"},
|
{file = "greenlet-3.3.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:6f8496d434d5cb2dce025773ba5597f71f5410ae499d5dd9533e0653258cdb3d"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:94385f101946790ae13da500603491f04a76b6e4c059dab271b3ce2e283b2590"},
|
{file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b96dc7eef78fd404e022e165ec55327f935b9b52ff355b067eb4a0267fc1cffb"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f10fd42b5ee276335863712fa3da6608e93f70629c631bf77145021600abc23c"},
|
{file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:73631cd5cccbcfe63e3f9492aaa664d278fda0ce5c3d43aeda8e77317e38efbd"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c8c9e331e58180d0d83c5b7999255721b725913ff6bc6cf39fa2a45841a4fd4b"},
|
{file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:b299a0cb979f5d7197442dccc3aee67fce53500cd88951b7e6c35575701c980b"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:58b97143c9cc7b86fc458f215bd0932f1757ce649e05b640fea2e79b54cedb31"},
|
{file = "greenlet-3.3.0-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7dee147740789a4632cace364816046e43310b59ff8fb79833ab043aefa72fd5"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c2ca18a03a8cfb5b25bc1cbe20f3d9a4c80d8c3b13ba3df49ac3961af0b1018d"},
|
{file = "greenlet-3.3.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:39b28e339fc3c348427560494e28d8a6f3561c8d2bcf7d706e1c624ed8d822b9"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:9fe0a28a7b952a21e2c062cd5756d34354117796c6d9215a87f55e38d15402c5"},
|
{file = "greenlet-3.3.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b3c374782c2935cc63b2a27ba8708471de4ad1abaa862ffdb1ef45a643ddbb7d"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8854167e06950ca75b898b104b63cc646573aa5fef1353d4508ecdd1ee76254f"},
|
{file = "greenlet-3.3.0-cp310-cp310-win_amd64.whl", hash = "sha256:b49e7ed51876b459bd645d83db257f0180e345d3f768a35a85437a24d5a49082"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f47617f698838ba98f4ff4189aef02e7343952df3a615f847bb575c3feb177a7"},
|
{file = "greenlet-3.3.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:e29f3018580e8412d6aaf5641bb7745d38c85228dacf51a73bd4e26ddf2a6a8e"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:af41be48a4f60429d5cad9d22175217805098a9ef7c40bfef44f7669fb9d74d8"},
|
{file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a687205fb22794e838f947e2194c0566d3812966b41c78709554aa883183fb62"},
|
||||||
{file = "greenlet-3.2.4-cp310-cp310-win_amd64.whl", hash = "sha256:73f49b5368b5359d04e18d15828eecc1806033db5233397748f4ca813ff1056c"},
|
{file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:4243050a88ba61842186cb9e63c7dfa677ec146160b0efd73b855a3d9c7fcf32"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:96378df1de302bc38e99c3a9aa311967b7dc80ced1dcc6f171e99842987882a2"},
|
{file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:670d0f94cd302d81796e37299bcd04b95d62403883b24225c6b5271466612f45"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:1ee8fae0519a337f2329cb78bd7a8e128ec0f881073d43f023c7b8d4831d5246"},
|
{file = "greenlet-3.3.0-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6cb3a8ec3db4a3b0eb8a3c25436c2d49e3505821802074969db017b87bc6a948"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:94abf90142c2a18151632371140b3dba4dee031633fe614cb592dbb6c9e17bc3"},
|
{file = "greenlet-3.3.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2de5a0b09eab81fc6a382791b995b1ccf2b172a9fec934747a7a23d2ff291794"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:4d1378601b85e2e5171b99be8d2dc85f594c79967599328f95c1dc1a40f1c633"},
|
{file = "greenlet-3.3.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4449a736606bd30f27f8e1ff4678ee193bc47f6ca810d705981cfffd6ce0d8c5"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0db5594dce18db94f7d1650d7489909b57afde4c580806b8d9203b6e79cdc079"},
|
{file = "greenlet-3.3.0-cp311-cp311-win_amd64.whl", hash = "sha256:7652ee180d16d447a683c04e4c5f6441bae7ba7b17ffd9f6b3aff4605e9e6f71"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2523e5246274f54fdadbce8494458a2ebdcdbc7b802318466ac5606d3cded1f8"},
|
{file = "greenlet-3.3.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b01548f6e0b9e9784a2c99c5651e5dc89ffcbe870bc5fb2e5ef864e9cc6b5dcb"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1987de92fec508535687fb807a5cea1560f6196285a4cde35c100b8cd632cc52"},
|
{file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:349345b770dc88f81506c6861d22a6ccd422207829d2c854ae2af8025af303e3"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:55e9c5affaa6775e2c6b67659f3a71684de4c549b3dd9afca3bc773533d284fa"},
|
{file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:e8e18ed6995e9e2c0b4ed264d2cf89260ab3ac7e13555b8032b25a74c6d18655"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:c9c6de1940a7d828635fbd254d69db79e54619f165ee7ce32fda763a9cb6a58c"},
|
{file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:c024b1e5696626890038e34f76140ed1daf858e37496d33f2af57f06189e70d7"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:03c5136e7be905045160b1b9fdca93dd6727b180feeafda6818e6496434ed8c5"},
|
{file = "greenlet-3.3.0-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:047ab3df20ede6a57c35c14bf5200fcf04039d50f908270d3f9a7a82064f543b"},
|
||||||
{file = "greenlet-3.2.4-cp311-cp311-win_amd64.whl", hash = "sha256:9c40adce87eaa9ddb593ccb0fa6a07caf34015a29bf8d344811665b573138db9"},
|
{file = "greenlet-3.3.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2d9ad37fc657b1102ec880e637cccf20191581f75c64087a549e66c57e1ceb53"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:3b67ca49f54cede0186854a008109d6ee71f66bd57bb36abd6d0a0267b540cdd"},
|
{file = "greenlet-3.3.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:83cd0e36932e0e7f36a64b732a6f60c2fc2df28c351bae79fbaf4f8092fe7614"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:ddf9164e7a5b08e9d22511526865780a576f19ddd00d62f8a665949327fde8bb"},
|
{file = "greenlet-3.3.0-cp312-cp312-win_amd64.whl", hash = "sha256:a7a34b13d43a6b78abf828a6d0e87d3385680eaf830cd60d20d52f249faabf39"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:f28588772bb5fb869a8eb331374ec06f24a83a9c25bfa1f38b6993afe9c1e968"},
|
{file = "greenlet-3.3.0-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:a1e41a81c7e2825822f4e068c48cb2196002362619e2d70b148f20a831c00739"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:5c9320971821a7cb77cfab8d956fa8e39cd07ca44b6070db358ceb7f8797c8c9"},
|
{file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9f515a47d02da4d30caaa85b69474cec77b7929b2e936ff7fb853d42f4bf8808"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c60a6d84229b271d44b70fb6e5fa23781abb5d742af7b808ae3f6efd7c9c60f6"},
|
{file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:7d2d9fd66bfadf230b385fdc90426fcd6eb64db54b40c495b72ac0feb5766c54"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3b3812d8d0c9579967815af437d96623f45c0f2ae5f04e366de62a12d83a8fb0"},
|
{file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30a6e28487a790417d036088b3bcb3f3ac7d8babaa7d0139edbaddebf3af9492"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:abbf57b5a870d30c4675928c37278493044d7c14378350b3aa5d484fa65575f0"},
|
{file = "greenlet-3.3.0-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:087ea5e004437321508a8d6f20efc4cfec5e3c30118e1417ea96ed1d93950527"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:20fb936b4652b6e307b8f347665e2c615540d4b42b3b4c8a321d8286da7e520f"},
|
{file = "greenlet-3.3.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ab97cf74045343f6c60a39913fa59710e4bd26a536ce7ab2397adf8b27e67c39"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:ee7a6ec486883397d70eec05059353b8e83eca9168b9f3f9a361971e77e0bcd0"},
|
{file = "greenlet-3.3.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5375d2e23184629112ca1ea89a53389dddbffcf417dad40125713d88eb5f96e8"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:326d234cbf337c9c3def0676412eb7040a35a768efc92504b947b3e9cfc7543d"},
|
{file = "greenlet-3.3.0-cp313-cp313-win_amd64.whl", hash = "sha256:9ee1942ea19550094033c35d25d20726e4f1c40d59545815e1128ac58d416d38"},
|
||||||
{file = "greenlet-3.2.4-cp312-cp312-win_amd64.whl", hash = "sha256:a7d4e128405eea3814a12cc2605e0e6aedb4035bf32697f72deca74de4105e02"},
|
{file = "greenlet-3.3.0-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:60c2ef0f578afb3c8d92ea07ad327f9a062547137afe91f38408f08aacab667f"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-macosx_11_0_universal2.whl", hash = "sha256:1a921e542453fe531144e91e1feedf12e07351b1cf6c9e8a3325ea600a715a31"},
|
{file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0a5d554d0712ba1de0a6c94c640f7aeba3f85b3a6e1f2899c11c2c0428da9365"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cd3c8e693bff0fff6ba55f140bf390fa92c994083f838fece0f63be121334945"},
|
{file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3a898b1e9c5f7307ebbde4102908e6cbfcb9ea16284a3abe15cab996bee8b9b3"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:710638eb93b1fa52823aa91bf75326f9ecdfd5e0466f00789246a5280f4ba0fc"},
|
{file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:dcd2bdbd444ff340e8d6bdf54d2f206ccddbb3ccfdcd3c25bf4afaa7b8f0cf45"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:c5111ccdc9c88f423426df3fd1811bfc40ed66264d35aa373420a34377efc98a"},
|
{file = "greenlet-3.3.0-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5773edda4dc00e173820722711d043799d3adb4f01731f40619e07ea2750b955"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d76383238584e9711e20ebe14db6c88ddcedc1829a9ad31a584389463b5aa504"},
|
{file = "greenlet-3.3.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ac0549373982b36d5fd5d30beb8a7a33ee541ff98d2b502714a09f1169f31b55"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:23768528f2911bcd7e475210822ffb5254ed10d71f4028387e5a99b4c6699671"},
|
{file = "greenlet-3.3.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d198d2d977460358c3b3a4dc844f875d1adb33817f0613f663a656f463764ccc"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:00fadb3fedccc447f517ee0d3fd8fe49eae949e1cd0f6a611818f4f6fb7dc83b"},
|
{file = "greenlet-3.3.0-cp314-cp314-win_amd64.whl", hash = "sha256:73f51dd0e0bdb596fb0417e475fa3c5e32d4c83638296e560086b8d7da7c4170"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:d25c5091190f2dc0eaa3f950252122edbbadbb682aa7b1ef2f8af0f8c0afefae"},
|
{file = "greenlet-3.3.0-cp314-cp314t-macosx_11_0_universal2.whl", hash = "sha256:d6ed6f85fae6cdfdb9ce04c9bf7a08d666cfcfb914e7d006f44f840b46741931"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e343822feb58ac4d0a1211bd9399de2b3a04963ddeec21530fc426cc121f19b"},
|
{file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d9125050fcf24554e69c4cacb086b87b3b55dc395a8b3ebe6487b045b2614388"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:ca7f6f1f2649b89ce02f6f229d7c19f680a6238af656f61e0115b24857917929"},
|
{file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:87e63ccfa13c0a0f6234ed0add552af24cc67dd886731f2261e46e241608bee3"},
|
||||||
{file = "greenlet-3.2.4-cp313-cp313-win_amd64.whl", hash = "sha256:554b03b6e73aaabec3745364d6239e9e012d64c68ccd0b8430c64ccc14939a8b"},
|
{file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_s390x.manylinux_2_28_s390x.whl", hash = "sha256:2662433acbca297c9153a4023fe2161c8dcfdcc91f10433171cf7e7d94ba2221"},
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-macosx_11_0_universal2.whl", hash = "sha256:49a30d5fda2507ae77be16479bdb62a660fa51b1eb4928b524975b3bde77b3c0"},
|
{file = "greenlet-3.3.0-cp314-cp314t-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3c6e9b9c1527a78520357de498b0e709fb9e2f49c3a513afd5a249007261911b"},
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:299fd615cd8fc86267b47597123e3f43ad79c9d8a22bebdce535e53550763e2f"},
|
{file = "greenlet-3.3.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:286d093f95ec98fdd92fcb955003b8a3d054b4e2cab3e2707a5039e7b50520fd"},
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:c17b6b34111ea72fc5a4e4beec9711d2226285f0386ea83477cbb97c30a3f3a5"},
|
{file = "greenlet-3.3.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6c10513330af5b8ae16f023e8ddbfb486ab355d04467c4679c5cfe4659975dd9"},
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:b4a1870c51720687af7fa3e7cda6d08d801dae660f75a76f3845b642b4da6ee1"},
|
{file = "greenlet-3.3.0.tar.gz", hash = "sha256:a82bb225a4e9e4d653dd2fb7b8b2d36e4fb25bc0165422a11e48b88e9e6f78fb"},
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:061dc4cf2c34852b052a8620d40f36324554bc192be474b9e9770e8c042fd735"},
|
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44358b9bf66c8576a9f57a590d5f5d6e72fa4228b763d0e43fee6d3b06d3a337"},
|
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:2917bdf657f5859fbf3386b12d68ede4cf1f04c90c3a6bc1f013dd68a22e2269"},
|
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:015d48959d4add5d6c9f6c5210ee3803a830dce46356e3bc326d6776bde54681"},
|
|
||||||
{file = "greenlet-3.2.4-cp314-cp314-win_amd64.whl", hash = "sha256:e37ab26028f12dbb0ff65f29a8d3d44a765c61e729647bf2ddfbbed621726f01"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:b6a7c19cf0d2742d0809a4c05975db036fdff50cd294a93632d6a310bf9ac02c"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:27890167f55d2387576d1f41d9487ef171849ea0359ce1510ca6e06c8bece11d"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.whl", hash = "sha256:18d9260df2b5fbf41ae5139e1be4e796d99655f023a636cd0e11e6406cca7d58"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.whl", hash = "sha256:671df96c1f23c4a0d4077a325483c1503c96a1b7d9db26592ae770daa41233d4"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:16458c245a38991aa19676900d48bd1a6f2ce3e16595051a4db9d012154e8433"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-manylinux_2_24_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9913f1a30e4526f432991f89ae263459b1c64d1608c0d22a5c79c287b3c70df"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:b90654e092f928f110e0007f572007c9727b5265f7632c2fa7415b4689351594"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:81701fd84f26330f0d5f4944d4e92e61afe6319dcd9775e39396e39d7c3e5f98"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:28a3c6b7cd72a96f61b0e4b2a36f681025b60ae4779cc73c1535eb5f29560b10"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:52206cd642670b0b320a1fd1cbfd95bca0e043179c1d8a045f2c6109dfe973be"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-win32.whl", hash = "sha256:65458b409c1ed459ea899e939f0e1cdb14f58dbc803f2f93c5eab5694d32671b"},
|
|
||||||
{file = "greenlet-3.2.4-cp39-cp39-win_amd64.whl", hash = "sha256:d2e685ade4dafd447ede19c31277a224a239a0a1a4eca4e6390efedf20260cfb"},
|
|
||||||
{file = "greenlet-3.2.4.tar.gz", hash = "sha256:0dca0d95ff849f9a364385f36ab49f50065d76964944638be9691e1832e9f86d"},
|
|
||||||
]
|
]
|
||||||
|
|
||||||
[package.extras]
|
[package.extras]
|
||||||
@@ -4440,4 +4421,4 @@ cffi = ["cffi (>=1.17,<2.0) ; platform_python_implementation != \"PyPy\" and pyt
|
|||||||
[metadata]
|
[metadata]
|
||||||
lock-version = "2.1"
|
lock-version = "2.1"
|
||||||
python-versions = ">=3.12,<4.0.0"
|
python-versions = ">=3.12,<4.0.0"
|
||||||
content-hash = "26fa6096f5efdd91a8d5b17a2f5efd68cd5f26e4dcdd516a39b77708c36b45e8"
|
content-hash = "a442f98c90b802cff40751935117a051530a05eaf63faa3cc99558ac8f44cdc1"
|
||||||
|
|||||||
@@ -29,9 +29,15 @@ dependencies = [
|
|||||||
"langchain-openai (>=1.1.0,<2.0.0)",
|
"langchain-openai (>=1.1.0,<2.0.0)",
|
||||||
"openai (>=2.8.1,<3.0.0)",
|
"openai (>=2.8.1,<3.0.0)",
|
||||||
"jsonschema (>=4.25.1,<5.0.0)",
|
"jsonschema (>=4.25.1,<5.0.0)",
|
||||||
|
"greenlet (>=3.3.0,<4.0.0)",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
[build-system]
|
[build-system]
|
||||||
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
requires = ["poetry-core>=2.0.0,<3.0.0"]
|
||||||
build-backend = "poetry.core.masonry.api"
|
build-backend = "poetry.core.masonry.api"
|
||||||
|
|
||||||
|
[tool.poetry]
|
||||||
|
packages = [
|
||||||
|
{ include = "app" }
|
||||||
|
]
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
FROM node:18-alpine AS builder
|
FROM node:20-alpine AS builder
|
||||||
|
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
|
|||||||
@@ -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"]
|
|
||||||
Reference in New Issue
Block a user