feat(eval): add batch-evaluation evaluate - #1965
Conversation
1b4b5a0 to
2252051
Compare
2252051 to
b3ff3a2
Compare
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## refactor #1965 +/- ##
============================================
- Coverage 96.79% 96.63% -0.17%
============================================
Files 306 307 +1
Lines 17051 17243 +192
============================================
+ Hits 16505 16662 +157
- Misses 546 581 +35 ☔ View full report in Codecov by Harness. 🚀 New features to boost your workflow:
|
b3ff3a2 to
dc0bcf6
Compare
dc0bcf6 to
0dba42a
Compare
5f08b10 to
1390aa5
Compare
| @@ -0,0 +1,20 @@ | |||
| { | |||
| "batchEvaluationId": "golden_batch_evaluate-0c95e0cf8b", | |||
| "batchEvaluationArn": "arn:aws:bedrock-agentcore:us-west-2:725476964917:batch-evaluate/golden_batch_evaluate-0c95e0cf8b", | |||
There was a problem hiding this comment.
these tests are using the wrong account 685197708687
There was a problem hiding this comment.
I'll use 685197708687 to record these.
Hweinstock
left a comment
There was a problem hiding this comment.
mostly some questions about how we're using comments in the code. I am of the opinion we should reserve them for details the code can't express, and make the code as readable as possible.
I found most of the comments distracting/confusing, and wonder if it would have the same effect on agents (especially if the information becomes stale).
|
|
||
| jobs: | ||
| call: | ||
| # Fork PRs never receive repo secrets/OIDC from GitHub, so the reusable's |
There was a problem hiding this comment.
is this intentionally part of this PR? feels unrelated to batch evals?
There was a problem hiding this comment.
No this was a artifact for another PR
| // startBatchEvaluation submits the async, service-side job. Core translates the | ||
| // resolved SessionSourceValue into the dataSourceConfig union: the agent arm | ||
| // resolves the harness/runtime id to a log group (reusing agentDataSource), the | ||
| // online-eval arm points at a config ARN, and the raw arm passes JSON through. |
There was a problem hiding this comment.
I'm not sure I follow this comment, is it describing the function below? If so, should we localize that info to avoid drift?
There was a problem hiding this comment.
I'm just going to remove it because the code explains itself.
| ): Promise<DataPlaneDataSourceConfig> { | ||
| if (source.origin === "raw") return source.dataSourceConfig; | ||
|
|
||
| // SessionWindow is already { startTime, endTime } — the SDK's SessionFilterConfig shape. |
There was a problem hiding this comment.
I feel like the code expresses this more concisely than the comment by the fact that we didn't need to transform it before passing to SDK.
I tend to think comments should be reserved for pieces of information that the code cannot or fails to express.
There was a problem hiding this comment.
I'll remove this commnet
| } | ||
|
|
||
| const qualifier = source.endpoint ?? DEFAULT_ENDPOINT_QUALIFIER; | ||
| const { runtimeId, runtimeName } = await resolveAgentToRuntime( |
There was a problem hiding this comment.
couldn't this be a runtime or a harness? I thought we could pass harnessId to eval apis?
There was a problem hiding this comment.
async function resolveAgentToRuntime(
agent: string,
clients: AwsClients,
options: CoreOptions,
): Promise<{ runtimeId: string; runtimeName: string }> {
const control = clients.control(toClientConfig(options));
try {
const runtime = await control.send(new GetAgentRuntimeCommand({ agentRuntimeId: agent }));
if (runtime.agentRuntimeName) {
return { runtimeId: agent, runtimeName: runtime.agentRuntimeName };
}
} catch (error) {
if ((error as Error).name !== "ResourceNotFoundException") throw error;
}
const harness = await control.send(new GetHarnessCommand({ harnessId: agent }));
const environment = harness.harness?.environment;
const runtimeEnv =
environment && "agentCoreRuntimeEnvironment" in environment
? environment.agentCoreRuntimeEnvironment
: undefined;
if (!runtimeEnv?.agentRuntimeId || !runtimeEnv?.agentRuntimeName) {
throw new InputValidationError(`"${agent}" does not exist as a runtime or a harness`, {
meta: { agent },
});
}
return { runtimeId: runtimeEnv.agentRuntimeId, runtimeName: runtimeEnv.agentRuntimeName };
}
As shown above, the function can return both an harness id/name or a runtime id/name. I'll rename this reflect this.
| import { coreOptsFromCtx, parseJsonFlag } from "../../../utils"; | ||
| import type { SessionSourceValue, SessionWindow } from "../../types"; | ||
|
|
||
| // createEvaluateBatchEvaluationHandler wires `batch-evaluation evaluate`: an |
There was a problem hiding this comment.
Do you feel that this comment expresses something that the code is unable to?
There was a problem hiding this comment.
Removing this code comment too.
| }, | ||
| }); | ||
|
|
||
| type SourceFlags = { |
There was a problem hiding this comment.
is there a nice way we can derive this from the flags to avoid drift?
There was a problem hiding this comment.
Discussed in person this is actually meant to match this API shape, not the flag shape: https://docs.aws.amazon.com/boto3/latest/reference/services/bedrock-agentcore/client/start_batch_evaluation.html#.
We might want to pull out this functionality for insights later, but thats TBD.
| // it. `rawDataSourceConfig` is the already-parsed --data-source-config (JSON | ||
| // resolution is async and happens in the handler; this stays sync/pure). Kept | ||
| // local for now; extract to a shared util when on-demand evaluate reuses it. | ||
| function resolveSource( |
There was a problem hiding this comment.
what exactly is the source of? Source of data for the evaluations? resolveSource feels somewhat ambiguous.
There was a problem hiding this comment.
I'll rename it to resolveDataSource
|
|
||
| // resolveSource picks exactly one source arm and validates the filters legal for | ||
| // it. `rawDataSourceConfig` is the already-parsed --data-source-config (JSON | ||
| // resolution is async and happens in the handler; this stays sync/pure). Kept |
There was a problem hiding this comment.
Isn't this already communicated by the function definition?
There was a problem hiding this comment.
I'll remove this comment
Adds the write path for evaluating existing sessions service-side:
`agentcore eval batch-evaluation evaluate` submits an async StartBatchEvaluation
job and returns a durable job id (poll with the existing `get`). The session
source is exactly one of:
- --agent <harness-id|runtime-id> (resolved to a CloudWatch data source)
- --online-eval <id> (an existing online-eval config's sessions)
- --data-source-config <json> (raw DataSourceConfig escape hatch; inline,
file://, or stdin)
narrowed by --lookback-days or --start-time/--end-time, plus --session-ids on the
agent arm. Ground truth (--ground-truth) maps to evaluationMetadata.
Verified end-to-end against a live account (job COMPLETED, 5/5 sessions,
averageScore 0.9). Tests cover the evaluate command flow: required flags, source
arm selection, and filter mutual-exclusion.
Note: on-demand evaluate is deferred to a later phase; the shared session-source
resolver will be extracted to a util when that lands.
Hoist `hasIds` above the raw-source guard and define it as `!!flags["session-ids"]?.length` — undefined/empty/present all collapse correctly — replacing the two `(… ?? 0) > 0` expressions.
The golden/fixture suite (batch-evaluation.fixture.test.tsx) is the convention for exercising the command → SDK seam; the TestCoreClient flow tests for evaluate were redundant scaffolding. Keeps the hierarchy + get/list edge tests.
Records the --agent source path end to end: GetAgentRuntime (agent → runtime resolution) + StartBatchEvaluation (the submitted job), with evaluate.golden.json pinning the rendered output. Matches the fixture convention used by the get/list suite.
7b521d7 to
b78318a
Compare
…lveDataSource Remove comments that restated the code (per review): the startBatchEvaluation and createEvaluateBatchEvaluationHandler doc blocks and the timeRange line note. Rename resolveSource -> resolveDataSource so the name says what it produces, and trim its comment to the one thing the code can't say (why it's still local).
…d account Record the evaluate fixtures against the shared fixture account (685197708687) using its asdf_MyAgent runtime, instead of a personal account, per review.
Name it for what it returns (runtime name + id), per review. Also drop the remaining local-helper note above resolveDataSource.
…atic class Rename for clarity and add a deferral note: when insights lands as a second consumer, promote the type + resolveDataSource into a static SessionSource class.
Summary
Adds
agentcore eval batch-evaluation evaluate— the write path that starts an evaluation over existing sessions.batch-evaluationpreviously shipped read-only (get+list); this makes it runnable.The command submits an async
StartBatchEvaluationjob (the service gathers the sessions) and returns a durable job id. Retrieve results with the existingget.Usage
Session source — exactly one
--agent <harness-id|runtime-id>resolveAgentToRuntime)--online-eval <id>--data-source-config <json>DataSourceConfigescape hatch — inline /file:/// stdinFilters & options
--start-time/--end-time(ISO-8601, together) — optional time window.--session-ids— specific sessions (agent arm only).--ground-truth <json>— inline /file:/// stdin →evaluationMetadata.--name(required),--description,--kms-key-arn.JSON-valued flags resolve via
SourceResolver+parseJsonFlag, matchingonline-eval/create.Design notes
startBatchEvaluationonEvalClientmaps the resolved source to thedataSourceConfigunion (cloudWatchLogs/onlineEvaluationConfigSource/ raw passthrough) and sends via the data-plane client. Reuses the existing agent→runtime→log-group resolution.ondemand evaluatelands as a follow-up and becomes the second consumer.flag()has no short aliases; matches every existing handler.Scope
batch-evaluation evaluateonly.ondemand evaluate(sync, client-side) andsimulate(dataset replay) are deferred to follow-up phases.--lookback-daysis intentionally not included yet; only explicit--start-time/--end-timewindows for now.--insightsand--tags(supported by the SDK request) are deferred.Verification
Verified end-to-end against a live account (
us-west-2, real runtime +Builtin.Helpfulness):Submitted (HTTP 202,
PENDING) →getpolled toCOMPLETED, 5/5 sessions,averageScore: 0.9, with the resolveddataSourceConfigechoed back.Tests
Handler command-flow tests (real root handler +
TestCoreClient): required--name/--evaluator, source-arm selection (agent + online-eval resolved shapes), zero/multiple arms rejected,--session-idsrejected on the online-eval arm.bun run typecheck,bun test src/(1001 pass),oxlint— all clean.