Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/tame-groups-open.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"braintrust": patch
---

Preserve dataset filters as arrays of clauses when creating experiments, allowing the experiment to store the original unnormalized filter form.
14 changes: 10 additions & 4 deletions js/src/logger.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -484,7 +484,7 @@ function mockInitGitMetadata() {
).mockResolvedValue([]);
}

test("init forwards dataset _internal_btql to experiment register", async () => {
test("init preserves dataset _internal_btql before experiment register", async () => {
const state = await _exportsForTestingOnly.simulateLoginForTests();

try {
Expand All @@ -504,7 +504,6 @@ test("init forwards dataset _internal_btql to experiment register", async () =>
},
],
};

let experimentRegisterBody: unknown;
vi.spyOn(state.appConn(), "post_json")
.mockResolvedValueOnce({
Expand Down Expand Up @@ -564,7 +563,7 @@ test("init forwards dataset _internal_btql to experiment register", async () =>
}
});

test("dataset fetch forwards _internal_btql filter arrays to btql", async () => {
test("dataset fetch normalizes _internal_btql filter arrays before btql", async () => {
const state = await _exportsForTestingOnly.simulateLoginForTests();

try {
Expand All @@ -584,6 +583,13 @@ test("dataset fetch forwards _internal_btql filter arrays to btql", async () =>
],
limit: 5,
};
const normalizedDatasetFilter = {
filter: {
op: "and",
children: datasetFilter.filter,
},
limit: 5,
};

vi.spyOn(state.appConn(), "post_json").mockResolvedValue({
project: {
Expand Down Expand Up @@ -623,7 +629,7 @@ test("dataset fetch forwards _internal_btql filter arrays to btql", async () =>
expect(btqlBody).toEqual(
expect.objectContaining({
query: expect.objectContaining({
filter: datasetFilter.filter,
filter: normalizedDatasetFilter.filter,
limit: 5,
}),
}),
Expand Down
34 changes: 33 additions & 1 deletion js/src/logger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3510,6 +3510,35 @@ function getExperimentDatasetFilter({
return isObject(datasetFilter) ? datasetFilter : undefined;
}

function normalizeInternalBtqlFilter(
internalBtql?: Record<string, unknown>,
): Record<string, unknown> | undefined {
if (internalBtql === undefined) {
return undefined;
}

const filter = internalBtql["filter"];
if (!Array.isArray(filter)) {
return internalBtql;
}

const { filter: _filter, ...internalBtqlWithoutFilter } = internalBtql;
if (filter.length === 0) {
return internalBtqlWithoutFilter;
}

return {
...internalBtqlWithoutFilter,
filter:
filter.length === 1
? filter[0]
: {
op: "and",
children: filter,
},
};
}

function getInternalBtqlLimit(
internalBtql?: Record<string, unknown>,
): number | undefined {
Expand Down Expand Up @@ -6087,8 +6116,11 @@ export class ObjectFetcher<RecordType> implements AsyncIterable<
const internalLimit = getInternalBtqlLimit(this._internal_btql);
const limit =
batchSize !== undefined ? batchSize : (internalLimit ?? batchLimit);
const normalizedInternalBtql = normalizeInternalBtqlFilter(
this._internal_btql,
);
const internalBtqlWithoutReservedQueryKeys = Object.fromEntries(
Object.entries(this._internal_btql ?? {}).filter(
Object.entries(normalizedInternalBtql ?? {}).filter(
([key]) =>
key !== "cursor" &&
key !== "limit" &&
Expand Down
Loading