-
Notifications
You must be signed in to change notification settings - Fork 29
Enable custom AI Instance Segmentation jobs #8849
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 24 commits
4e6c661
59ecc38
a35e8fc
2be6e63
475175e
bbd0657
0c1dda0
0a8bd90
e4b3441
9b7d33e
15850d0
f516eb3
11dfad2
9a4dfde
e10df97
b9d429f
377ddf6
2473f91
fd71ced
a5afc38
433a5b5
95c78ed
77c0faf
682287f
ed811da
461dbb5
0f80b11
2c2495c
ca08d0f
5028633
578f68b
ffac159
3c69584
2fad242
0d90fad
72478d8
831f0a9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -277,11 +277,17 @@ function JobListView() { | |
: null} | ||
</span> | ||
); | ||
} else if (job.type === APIJobType.TRAIN_NEURON_MODEL || APIJobType.DEPRECATED_TRAIN_MODEL) { | ||
const numberOfTrainingAnnotations = job.trainingAnnotations.length; | ||
} else if ( | ||
job.type === APIJobType.TRAIN_NEURON_MODEL || | ||
job.type === APIJobType.TRAIN_INSTANCE_MODEL || | ||
job.type === APIJobType.DEPRECATED_TRAIN_MODEL | ||
) { | ||
const numberOfTrainingAnnotations = job.trainingAnnotations?.length || 0; | ||
const modelName = | ||
job.type === APIJobType.TRAIN_NEURON_MODEL ? "neuron model" : "instance model"; | ||
|
||
return ( | ||
<span> | ||
{`Train neuron model on ${numberOfTrainingAnnotations} ${Utils.pluralize("annotation", numberOfTrainingAnnotations)}. `} | ||
{`Train ${modelName} on ${numberOfTrainingAnnotations} ${Utils.pluralize("annotation", numberOfTrainingAnnotations)}. `} | ||
{getShowTrainingDataLink(job.trainingAnnotations)} | ||
</span> | ||
Comment on lines
+299
to
301
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🛠️ Refactor suggestion Guard “Show Training Data” link against empty arrays If trainingAnnotations is an empty array, getShowTrainingDataLink will access index 0 and throw. Gate the link on count > 0. Apply this diff: - {getShowTrainingDataLink(job.trainingAnnotations)}
+ {numberOfTrainingAnnotations > 0 &&
+ getShowTrainingDataLink(job.trainingAnnotations)} Alternatively, harden getShowTrainingDataLink itself to return null when length === 0: export const getShowTrainingDataLink = (trainingAnnotations?: { annotationId: string }[]) => {
if (!trainingAnnotations || trainingAnnotations.length === 0) return null;
return trainingAnnotations.length > 1
? /* multi-annotation modal link */
: /* single annotation link */;
}; 🤖 Prompt for AI Agents
|
||
); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -19,10 +19,8 @@ import type { Key } from "react"; | |
import type { Vector3 } from "viewer/constants"; | ||
import { getMagInfo, getSegmentationLayerByName } from "viewer/model/accessors/dataset_accessor"; | ||
import { formatUserName } from "viewer/model/accessors/user_accessor"; | ||
import { | ||
type AnnotationInfoForAITrainingJob, | ||
TrainAiModelTab, | ||
} from "viewer/view/jobs/train_ai_model"; | ||
import { TrainAiModelForm } from "viewer/view/action-bar/ai_job_modals/forms/train_ai_model_form"; | ||
import type { AnnotationInfoForAITrainingJob } from "viewer/view/action-bar/ai_job_modals/utils"; | ||
|
||
import { Link } from "react-router-dom"; | ||
import type { APIAnnotation, AiModel } from "types/api_types"; | ||
|
@@ -173,7 +171,7 @@ function TrainNewAiJobModal({ onClose }: { onClose: () => void }) { | |
footer={null} | ||
maskClosable={false} | ||
> | ||
<TrainAiModelTab | ||
<TrainAiModelForm | ||
getMagsForSegmentationLayer={getMagsForSegmentationLayer} | ||
onClose={onClose} | ||
annotationInfos={annotationInfosForAiJob} | ||
|
@@ -187,9 +185,10 @@ function TrainNewAiJobModal({ onClose }: { onClose: () => void }) { | |
|
||
const renderActionsForModel = (model: AiModel, onChangeSharedOrganizations: () => void) => { | ||
const organizationSharingButton = model.isOwnedByUsersOrganization ? ( | ||
<Button type="link" onClick={onChangeSharedOrganizations} icon={<TeamOutlined />}> | ||
<a onClick={onChangeSharedOrganizations}> | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why did you change this from button type link to an actual link? Shouldn't it have looks the same? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. |
||
<TeamOutlined className="icon-margin-right" /> | ||
Manage Access | ||
</Button> | ||
</a> | ||
) : null; | ||
hotzenklotz marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (model.trainingJob == null) { | ||
return organizationSharingButton; | ||
|
@@ -205,16 +204,15 @@ const renderActionsForModel = (model: AiModel, onChangeSharedOrganizations: () = | |
{trainingJobState === "SUCCESS" ? <Row>{organizationSharingButton}</Row> : null} | ||
{voxelyticsWorkflowHash != null ? ( | ||
/* margin left is needed as organizationSharingButton is a button with a 16 margin */ | ||
<Row style={{ marginLeft: 16 }}> | ||
<FileTextOutlined | ||
className="icon-margin-right" | ||
style={{ color: "var(--ant-color-primary)" }} | ||
/> | ||
<Link to={`/workflows/${voxelyticsWorkflowHash}`}>Voxelytics Report</Link> | ||
<Row> | ||
<Link to={`/workflows/${voxelyticsWorkflowHash}`}> | ||
<FileTextOutlined className="icon-margin-right" /> | ||
Voxelytics Report | ||
</Link> | ||
</Row> | ||
) : null} | ||
{trainingAnnotations != null ? ( | ||
<Row style={{ marginLeft: 16, display: "inline-block" }}> | ||
<Row> | ||
<EyeOutlined | ||
className="icon-margin-right" | ||
style={{ color: "var(--ant-color-primary)" }} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Serialize category as string to match frontend contract
publicWrites currently passes an Option[AiModelCategory]. Unless an implicit Writes exists for AiModelCategory, this will either not compile or produce unexpected JSON. The frontend expects a string union.
Apply:
📝 Committable suggestion
🤖 Prompt for AI Agents