@arizeai/phoenix-client
Version:
A client for the Phoenix API
124 lines • 4.86 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getSessionTurns = getSessionTurns;
const openinference_semantic_conventions_1 = require("@arizeai/openinference-semantic-conventions");
const client_1 = require("../client");
const getSpans_1 = require("../spans/getSpans");
const getSession_1 = require("./getSession");
const MAX_TRACE_IDS_PER_BATCH = 50;
/**
* Get the turns (root span I/O) for a session.
*
* Returns input/output extracted from root spans for each trace, along with
* the full root span. Turns are ordered by trace start_time.
*
* **Note:** A "turn" is derived from a trace's root span. For input/output to appear,
* the root span must have `input.value` and `output.value` attributes set
* (per OpenInference semantic conventions). This typically requires instrumentation
* that records these attributes on the top-level span.
*
* @experimental this function is experimental and may change in the future
*
* @example
* ```ts
* import { getSessionTurns } from "@arizeai/phoenix-client/sessions";
*
* const turns = await getSessionTurns({ sessionId: "my-session" });
* for (const turn of turns) {
* console.log(`[${turn.startTime}] Input: ${turn.input?.value}`);
* console.log(`[${turn.startTime}] Output: ${turn.output?.value}`);
* }
* ```
*/
async function getSessionTurns({ client: _client, sessionId, }) {
const client = _client !== null && _client !== void 0 ? _client : (0, client_1.createClient)();
// getSession already calls ensureSessionsApi internally
const session = await (0, getSession_1.getSession)({ client, sessionId });
const traces = session.traces;
if (traces.length === 0) {
return [];
}
const projectId = session.projectId;
const traceInfo = new Map(traces.map((t) => [t.traceId, t]));
const allTraceIds = [...traceInfo.keys()];
// Fetch root spans in batches
const rootSpansByTrace = new Map();
for (let i = 0; i < allTraceIds.length; i += MAX_TRACE_IDS_PER_BATCH) {
const traceIdBatch = allTraceIds.slice(i, i + MAX_TRACE_IDS_PER_BATCH);
const spans = await getAllRootSpansForBatch({
client,
projectId,
traceIdBatch,
});
for (const span of spans) {
const traceId = span.context.trace_id;
if (!rootSpansByTrace.has(traceId)) {
rootSpansByTrace.set(traceId, span);
}
}
}
return buildSessionTurns({ allTraceIds, traceInfo, rootSpansByTrace });
}
/**
* Fetch all root spans for a batch of trace IDs, handling pagination.
*/
async function getAllRootSpansForBatch({ client, projectId, traceIdBatch, }) {
const allSpans = [];
let cursor = null;
do {
const result = await (0, getSpans_1.getSpans)(Object.assign({ client, project: { projectId }, traceIds: traceIdBatch, parentId: null, limit: traceIdBatch.length }, (cursor ? { cursor } : {})));
allSpans.push(...result.spans);
cursor = result.nextCursor;
} while (cursor != null);
return allSpans;
}
/**
* Extract a SessionTurnIO from span attributes for a given prefix.
*/
function extractIO({ attrs, valueKey, mimeTypeKey, }) {
const value = attrs[valueKey];
if (value == null)
return undefined;
const io = { value: String(value) };
const mimeType = attrs[mimeTypeKey];
if (mimeType != null) {
io.mimeType = String(mimeType);
}
return io;
}
/**
* Build session turns from trace info and root spans, ordered by start_time.
*/
function buildSessionTurns({ allTraceIds, traceInfo, rootSpansByTrace, }) {
var _a;
const turns = [];
for (const traceId of allTraceIds) {
const info = traceInfo.get(traceId);
if (!info)
continue;
const turn = {
traceId,
startTime: info.startTime,
endTime: info.endTime,
};
const rootSpan = rootSpansByTrace.get(traceId);
if (rootSpan) {
turn.rootSpan = rootSpan;
const attrs = (_a = rootSpan.attributes) !== null && _a !== void 0 ? _a : {};
turn.input = extractIO({
attrs,
valueKey: openinference_semantic_conventions_1.SemanticConventions.INPUT_VALUE,
mimeTypeKey: openinference_semantic_conventions_1.SemanticConventions.INPUT_MIME_TYPE,
});
turn.output = extractIO({
attrs,
valueKey: openinference_semantic_conventions_1.SemanticConventions.OUTPUT_VALUE,
mimeTypeKey: openinference_semantic_conventions_1.SemanticConventions.OUTPUT_MIME_TYPE,
});
}
turns.push(turn);
}
turns.sort((a, b) => a.startTime.localeCompare(b.startTime));
return turns;
}
//# sourceMappingURL=getSessionTurns.js.map