Repository navigation
feat(experiments): accept a caller-supplied experiment_id in run_experiment - #2026
Conversation
…riment Co-authored-by: hassieb.pakzad <hassieb.pakzad@clickhouse.com>
|
@claude review |
Codex Review SummaryThis comment shows the latest Codex review activity on this pull request.
ℹ️ About Codex in GitHubYour team has set up Codex to review pull requests in this repo. Reviews are triggered when you
Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings. |
There was a problem hiding this comment.
Claude Code Review
No review was started: this request came from a bot account. Manual reviews can only be requested by someone with write access to this repository. Ask a maintainer to comment @claude review, or have your automation post the comment from a user account with write access.
Tip: disable this comment in your organization's Code Review settings.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 2d0ddcf1e6
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| run_evaluators: List[RunEvaluatorFunction] = [], | ||
| max_concurrency: int = 50, | ||
| metadata: Optional[Dict[str, str]] = None, | ||
| experiment_id: Optional[str] = None, |
There was a problem hiding this comment.
Update ExperimentResult's experiment-ID contract
When callers supply this argument, the public ExperimentResult reference remains contradictory: langfuse/experiment.py:332-335 still states that dataset IDs are always derived and local IDs are always random, although the returned ID can now be caller-supplied in either case. Update that generated-reference docstring so users relying on the result type see the new contract.
AGENTS.md reference: AGENTS.md:L130-L134
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
LGTM. This adds an opt-in experiment_id parameter that is passed through cleanly, and nothing changes when it is left out.
What was reviewed:
- How
experiment_idis passed fromLangfuse.run_experiment,DatasetClient.run_experimentandRunnerContext.run_experimentdown to_run_experiment_async. All of these signatures are keyword-only (*), so putting the parameter before_dataset_versioncannot break positional callers. - The supplied id replaces
_create_experiment_idonly when it is given. The same value is then used for span attributes,dataset_run_idon run-level scores, and the result. Blank or non-string ids raise an error before any item runs. - The experiment URL now escapes the id with
urllib.parse.quote(..., safe=''). I also looked at the earlier candidate about a missing length check on the id and ruled it out: the value is caller-controlled and its own docs say to create it withcreate_trace_id.
Extended reasoning...
The change touches the experiment runner in langfuse/_client/client.py, two pass-through wrappers (datasets.py, experiment.py) and the unit tests. It adds one optional keyword-only parameter, and the default code path is the same as before. It touches no auth, crypto or permission code. The only CODEOWNERS rule covers .github/, which this PR does not change. The change is small and self-contained, comes with dedicated tests, and the bug hunt found no issues.
What does this PR do?
Adds an optional
experiment_idparameter toLangfuse.run_experiment,DatasetClient.run_experimentandRunnerContext.run_experiment. All calls that pass the same id record their items and scores in one experiment. This lets pipelines that split items across workers, or resume after an interruption, build a single experiment. Before this, that only worked for Langfuse dataset items, through the id derived fromrun_name. For local data, every call got a random id.Semantics:
langfuse.experiment.idon every item, fordataset_run_idon run-level scores, and (URL-encoded) inexperiment_url. Dataset items still record their dataset and item ids. Silently ignoring an explicit argument on dataset data would be more surprising, and the server has no experiment entity to conflict with: it only groups events by the id string.ValueErrorbefore any item runs. The server drops blank experiment ids.The docstring explains how to create a reusable id:
Langfuse.create_trace_id()for a random id that callers store and share.Langfuse.create_trace_id(seed="...")for a deterministic id that every worker derives independently. The JS SDK'screateTraceId(seed)returns the same value, since both hash the seed with SHA-256 and take the first 16 bytes as hex.It also notes that
run_evaluatorsonly see the items of their own call, so each call adds its own run-level scores.The JS SDK is getting the same parameter as
experimentId, with the same semantics, in a parallel PR.Type of change
Verification
TestCallerSuppliedExperimentIdcover:DatasetClientandRunnerContextcreate_trace_id(seed=...)→e5bd20a8dacf6fc3f5982073d88d782band ran 2 and 1 local items.GET /api/public/experimentsreturned a single experiment with that id anditemCount: 3.GET /api/public/experiment-itemsreturned 3 items.Stringcolumn), scoredatasetRunId(z.string(), no lookup) and the experiments UI routes (z.string()).Checklist
code_review.md..env.templateif needed.

Confidence Score: 5/5
The PR appears safe to merge; no actionable issues were found.Summary
Adds optional
experiment_idsupport toLangfuse.run_experiment,DatasetClient.run_experiment, andRunnerContext.run_experiment.No actionable issues found. Tests were inspected, not executed.
Reviews (1) · Last reviewed commit: "feat(experiments): accept a caller-suppl..." · Reviewed by Greptile