Skip to content

Conversation

riturajFi
Copy link

@riturajFi riturajFi commented Aug 29, 2025

Details

Summary

Introduced a new API for updating an experiment’s name and metadata.

Changes

  • Added API support for updating experiment details (name & metadata).
  • Integrated the feature into the front-end.
  • Extended the Python SDK to support updates.
  • Extended the TypeScript SDK to support updates.
Screencast.from.2025-09-01.20-23-22.webm

Change checklist

  • User facing
  • Documentation update

Issues

Testing

Documentation

@riturajFi riturajFi requested a review from a team as a code owner August 29, 2025 06:24
@riturajFi riturajFi marked this pull request as draft August 29, 2025 06:29
@riturajFi riturajFi marked this pull request as ready for review September 1, 2025 17:19
@riturajFi
Copy link
Author

Hi @yaricom @Lothiraldan @dsblank @vincentkoc , would like this PR to be reviewd

@vincentkoc vincentkoc requested a review from Copilot September 2, 2025 03:49
@vincentkoc
Copy link
Collaborator

@riturajFi can you please address the linter and test failures please before team can review. Thanks for your contribution.

@vincentkoc vincentkoc changed the title Feature/update experiment name metadata [issue-2572] [FE] Update experiment name metadata in UI Sep 2, 2025
Copy link
Contributor

@Copilot Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

This PR introduces functionality to update experiment names and metadata across all Opik applications. The feature enables users to modify existing experiments through API endpoints, frontend UI, and SDK methods.

Key changes:

  • Added API endpoint for updating experiment name and metadata with validation and change detection
  • Created interactive frontend dialog with Monaco editor for JSON metadata editing
  • Extended both Python and TypeScript SDKs with update methods

Reviewed Changes

Copilot reviewed 20 out of 21 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
apps/opik-backend/src/main/java/com/comet/opik/api/resources/v1/priv/ExperimentsResource.java REST endpoint for experiment updates with change detection
apps/opik-backend/src/main/java/com/comet/opik/domain/ExperimentService.java Business logic for planning and applying experiment updates
apps/opik-backend/src/main/java/com/comet/opik/domain/ExperimentDAO.java Database operations for updating experiment name and metadata
apps/opik-frontend/src/components/shared/UpdateExperimentDialog/UpdateExperimentDialog.tsx React dialog component with Monaco editor for experiment editing
apps/opik-frontend/src/api/datasets/useExperimentUpdate.ts Frontend mutation hook for experiment updates
sdks/python/src/opik/api_objects/opik_client.py Python SDK method for updating experiments
sdks/typescript/src/opik/client/Client.ts TypeScript SDK method for updating experiments
sdks/typescript/tests/experiment/client-experiment.test.ts Unit and integration tests for TypeScript SDK
Files not reviewed (1)
  • apps/opik-frontend/package-lock.json: Language not supported

datasetName: "test-dataset",
});

console.log(JSON.stringify(created))
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Debug console.log statement should be removed from test code. Use proper test logging or assertions instead.

Suggested change
console.log(JSON.stringify(created))

Copilot uses AI. Check for mistakes.

try {
parsedMetadata = metadata ? JSON.parse(metadata) : {};
} catch (e) {
alert("Invalid JSON in metadata");
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using browser alert() for error messages is not consistent with the application's UI patterns. Use the toast notification system instead, similar to other components in the codebase.

Copilot uses AI. Check for mistakes.

Comment on lines +15 to +21
export function UpdateExperimentDialog({
open,
setOpen,
onConfirm,
latestName,
latestMetadata
}) {
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Function parameters lack TypeScript type definitions. Define an interface for the props to ensure type safety and better developer experience.

Suggested change
export function UpdateExperimentDialog({
open,
setOpen,
onConfirm,
latestName,
latestMetadata
}) {
interface UpdateExperimentDialogProps {
open: boolean;
setOpen: (open: boolean) => void;
onConfirm: () => void;
latestName: string;
latestMetadata: any;
}
export function UpdateExperimentDialog({
open,
setOpen,
onConfirm,
latestName,
latestMetadata
}: UpdateExperimentDialogProps) {

Copilot uses AI. Check for mistakes.

-------------------
id: str
newName: Optional[str]
newMetadata: Optional[str]
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring parameter type annotation is incorrect. newMetadata should be Optional[Dict[str, Any]] not Optional[str] to match the actual parameter type.

Suggested change
newMetadata: Optional[str]
newMetadata: Optional[Dict[str, Any]]

Copilot uses AI. Check for mistakes.

@@ -43,9 +53,17 @@ const ExperimentRowActionsCell: React.FunctionComponent<
onConfirm={deleteExperimentsHandler}
title="Delete experiment"
description="Deleting an experiment will remove all samples in the experiment. Related traces won’t be affected. This action can’t be undone. Are you sure you want to continue?"
confirmText="Delete experiment"
confirmText="Delete experiments"
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confirm text should be "Delete experiment" (singular) since the action deletes only one experiment, not multiple experiments.

Suggested change
confirmText="Delete experiments"
confirmText="Delete experiment"

Copilot uses AI. Check for mistakes.

Comment on lines +529 to +537
ObjectMapper mapper = new ObjectMapper();
JsonNode meta;

try {
meta = mapper.readTree(plan.targetMetadata());
} catch (JsonProcessingException e) {
log.error("Invalid metadata JSON stored for experiment {}: {}", id, plan.targetMetadata(), e);
meta = mapper.createObjectNode().put("raw", plan.targetMetadata());
}
Copy link
Preview

Copilot AI Sep 2, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Inconsistent indentation after the blocking call. The ObjectMapper instantiation should be aligned with the surrounding code block.

Suggested change
ObjectMapper mapper = new ObjectMapper();
JsonNode meta;
try {
meta = mapper.readTree(plan.targetMetadata());
} catch (JsonProcessingException e) {
log.error("Invalid metadata JSON stored for experiment {}: {}", id, plan.targetMetadata(), e);
meta = mapper.createObjectNode().put("raw", plan.targetMetadata());
}
ObjectMapper mapper = new ObjectMapper();
JsonNode meta;
try {
meta = mapper.readTree(plan.targetMetadata());
} catch (JsonProcessingException e) {
log.error("Invalid metadata JSON stored for experiment {}: {}", id, plan.targetMetadata(), e);
meta = mapper.createObjectNode().put("raw", plan.targetMetadata());
}

Copilot uses AI. Check for mistakes.

Copy link
Member

@andrescrz andrescrz left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hi @riturajFi

Thanks a lot for your contribution.

I left a review on the backend part, with the general guidelines to follow in this service.

The main question here is how to handle the ClickHouse updates, which isn't straight forward and probably one of the reasons why we haven't implemented this ourselves yet.

I'll discuss and double check the approach with the team for that, but for now, the best option is to handle the update with a INSERT + SELECT query (see examples in this DAO already) and document that the endpoint is only meant for the UI and doesn't handle concurrent scenarios for the SDK (already the case).

Other members of the team will review the FE and SDK parts. In the meantime, please remove changes on the auto-generated code.

Thank you very much for all this work!

Comment on lines +611 to +620
private static final String UPDATE_BY_ID = """
ALTER TABLE experiments
UPDATE
name = :name,
metadata = :metadata,
last_updated_by = :last_updated_by
WHERE id = :id
AND workspace_id = :workspace_id
;
""";
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Per architectural reasons, we don't do mutations in ClickHouse, as they're not performant:

Regarding entities stored in CH, only spans and traces are PATCHED. The approach is to query and re-insert only the data that changes, in this case it'd be name and metadata. In this approach is tricky to keep data consistency for concurrent SDK flows. But maybe is reasonable to just document that this endpoint is for UI purposes only.

Another alternative is lightweight updates:

But considering that is a Beta feature, has some performance implications, and it'd have the same concurrency issues, I'd go with the previous approach.

@@ -484,4 +488,59 @@ public Response findFeedbackScoreNames(@QueryParam("experiment_ids") String expe

return Response.ok(feedbackScoreNames).build();
}

@POST
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be a PATCH operation.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You need tests for this new endpoint. Please follow the conventions in the code base.

@@ -484,4 +488,59 @@ public Response findFeedbackScoreNames(@QueryParam("experiment_ids") String expe

return Response.ok(feedbackScoreNames).build();
}

@POST
@Path("/update/{id}")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After updating to PATCH, the verb should be removed from the path. It isn't a good REST practice.


@POST
@Path("/update/{id}")
public Response updateExperimentById(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor: let's rename the method to update.

@@ -0,0 +1,13 @@
package com.comet.opik.domain;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Move to package com.comet.opik.api;

import com.fasterxml.jackson.databind.annotation.JsonNaming;

@JsonIgnoreProperties(ignoreUnknown = true)
@JsonNaming(PropertyNamingStrategies.SnakeCaseStrategy.class)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add @Builder(toBuilder = true).


import io.reactivex.rxjava3.annotations.Nullable;

public record ExperimentUpdatePlan(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This won't be needed.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have an automation for everything under sdks/python/src/opik/rest_api/ folder, please remove these changes. They'll be auto-generated.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same for the typescript SDK, we have an automation for everything under rest_api folder, please remove these changes. They'll be auto-generated.

@riturajFi
Copy link
Author

Great insights @andrescrz ! Will do the changes right away!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FR]: Add support for updating experiments
3 participants