Conversation
The disk store sorted result files by file name, so the numeric branches
of IterationNameComparer never matched ("10.json" parses as neither an
int nor a double) and iterations came back as 1, 10, 11, 2. Sort by the
iteration name instead, order the names in the Azure store the same way,
and make the comparer culture independent so that a name such as "1.5"
does not parse as 15 where "." is the group separator.
| </ItemGroup> | ||
|
|
||
| <ItemGroup> | ||
| <InternalsVisibleTo Include="Microsoft.Extensions.AI.Evaluation.Reporting.Azure" /> |
There was a problem hiding this comment.
We have avoided InternalsVisibleTo relationships between the product assemblies as much as possible to avoid unintentional coupling. Instead, we have preferred using linked source files for shared utilities. Is there a reason we cannot do the same here?
Please see this discussion for how we resolved the same issue in another PR: #7718 (comment)
| (string path, _) = GetResultPath(executionName, scenarioName); | ||
| DataLakeDirectoryClient subClient = client.GetSubDirectoryClient(path); | ||
|
|
||
| var iterationNames = new List<string>(); |
There was a problem hiding this comment.
minor suggestion to match other similar usages above
| var iterationNames = new List<string>(); | |
| List<string> iterationNames = []; |
The Azure store needs the comparer, and making it visible with InternalsVisibleTo also made every other internal type of the Reporting assembly visible, which collided with the converter sources that project already link-compiles and broke the build with CS0436. Link the comparer in the same way those converters and PathValidation are already linked, and disambiguate the unit test with the extern alias the test project is already set up for. Order the Azure iteration names with OrderBy rather than List.Sort so that both stores use a stable sort, and match the surrounding collection expression style.
|
Thanks — both suggestions applied, and the first one turned out to be more than a style issue.
One more change while I was in there: the Azure store now orders with Two things worth flagging for review rather than hiding in the diff:
Verified locally: |
|
CI update: Build Ubuntu now passes — the Build Windows still fails, but not on the code: the followed by |
Why
IEvaluationResultStore.GetIterationNamesAsyncandReadResultsAsyncreturn iterations in the wrong order when iteration names are numbers, which is what the docs onScenarioRun.IterationNamesuggest using ("an integer index that is incremented with each loop iteration"):DiskBasedResultStore.EnumerateResultFilessorts withIterationNameComparer, which compares numerically, but it passes the file name ("10.json"). Neitherint.TryParsenordouble.TryParsematches that, so every comparison fell through to the ordinal branch and the comparer's numeric branches were dead code. The report and everything else that consumes the store sees the wrong order; nothing downstream re-sorts.AzureStorageResultStorenever ordered iteration names at all, so it has the same symptom.How
DiskBasedResultStoresorts byPath.GetFileNameWithoutExtension(f.Name), which is the iteration name it already uses when yielding (GetIterationNamesAsync). This fixesReadResultsAsynctoo, since both go throughEnumerateResultFiles.AzureStorageResultStore.GetIterationNamesAsyncorders with the same comparer, so both stores answer in the same order. ItsReadResultsAsyncwalks scenarios recursively and is left alone.IterationNameComparernow parses withCultureInfo.InvariantCultureand withoutAllowThousands. Iteration names are written verbatim into file and blob paths, so"1.5"is a legal name, and with the current-culture parse it compares as 15 wherever.is the group separator (de, tr, es, it, pt-BR ...) - putting"2"before"1.5". The disk store never reached this branch before this change, so the fix would otherwise have introduced the misordering."01"and"1"have a deterministic order rather than whatever the file system enumerated first.Test Plan
Microsoft.Extensions.AI.Evaluation.Reporting.Tests: 144 passed, 0 failed, 24 skipped (the Azure ones, which need a configured storage account).ResultStoreTester.IterationNamesAreOrderedNumericallywrites iterations"1"through"11"and asserts the order they come back in. Without the fix it fails at the second element withExpected: "2", Actual: "10".IterationNameComparerTestscovers the int, double and ordinal branches, the"01"/"1"tie, and pins the culture behaviour by comparing"1.5"against"2"underde-DE.The Azure store change is not covered by a run here - those tests are skipped without a storage account - but it uses the same comparer as the disk store on a materialized list.
Microsoft Reviewers: Open in CodeFlow