@arizeai/phoenix-client 4.0.0 → 4.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/dist/esm/client.d.ts +3 -3
  2. package/dist/esm/client.d.ts.map +1 -1
  3. package/dist/esm/client.js +14 -1
  4. package/dist/esm/client.js.map +1 -1
  5. package/dist/esm/datasets/appendDatasetExamples.js +1 -1
  6. package/dist/esm/datasets/appendDatasetExamples.js.map +1 -1
  7. package/dist/esm/datasets/createDataset.js +2 -2
  8. package/dist/esm/datasets/createDataset.js.map +1 -1
  9. package/dist/esm/experiments/{instrumention.d.ts → instrumentation.d.ts} +1 -1
  10. package/dist/esm/experiments/instrumentation.d.ts.map +1 -0
  11. package/dist/esm/experiments/{instrumention.js → instrumentation.js} +1 -1
  12. package/dist/esm/experiments/instrumentation.js.map +1 -0
  13. package/dist/esm/experiments/runExperiment.d.ts +4 -3
  14. package/dist/esm/experiments/runExperiment.d.ts.map +1 -1
  15. package/dist/esm/experiments/runExperiment.js +26 -8
  16. package/dist/esm/experiments/runExperiment.js.map +1 -1
  17. package/dist/esm/tsconfig.esm.tsbuildinfo +1 -1
  18. package/dist/esm/types/datasets.d.ts +2 -2
  19. package/dist/esm/types/datasets.d.ts.map +1 -1
  20. package/dist/esm/types/experiments.d.ts +1 -1
  21. package/dist/esm/types/experiments.d.ts.map +1 -1
  22. package/dist/src/client.d.ts +3 -3
  23. package/dist/src/client.d.ts.map +1 -1
  24. package/dist/src/client.js +14 -1
  25. package/dist/src/client.js.map +1 -1
  26. package/dist/src/datasets/appendDatasetExamples.js +1 -1
  27. package/dist/src/datasets/appendDatasetExamples.js.map +1 -1
  28. package/dist/src/datasets/createDataset.js +2 -2
  29. package/dist/src/datasets/createDataset.js.map +1 -1
  30. package/dist/src/experiments/{instrumention.d.ts → instrumentation.d.ts} +1 -1
  31. package/dist/src/experiments/instrumentation.d.ts.map +1 -0
  32. package/dist/src/experiments/{instrumention.js → instrumentation.js} +1 -1
  33. package/dist/src/experiments/instrumentation.js.map +1 -0
  34. package/dist/src/experiments/runExperiment.d.ts +4 -3
  35. package/dist/src/experiments/runExperiment.d.ts.map +1 -1
  36. package/dist/src/experiments/runExperiment.js +30 -12
  37. package/dist/src/experiments/runExperiment.js.map +1 -1
  38. package/dist/src/types/datasets.d.ts +2 -2
  39. package/dist/src/types/datasets.d.ts.map +1 -1
  40. package/dist/src/types/experiments.d.ts +1 -1
  41. package/dist/src/types/experiments.d.ts.map +1 -1
  42. package/dist/tsconfig.tsbuildinfo +1 -1
  43. package/package.json +1 -1
  44. package/src/client.ts +21 -2
  45. package/src/datasets/appendDatasetExamples.ts +1 -1
  46. package/src/datasets/createDataset.ts +2 -2
  47. package/src/experiments/runExperiment.ts +56 -13
  48. package/src/types/datasets.ts +2 -2
  49. package/src/types/experiments.ts +1 -1
  50. package/dist/esm/experiments/instrumention.d.ts.map +0 -1
  51. package/dist/esm/experiments/instrumention.js.map +0 -1
  52. package/dist/src/experiments/instrumention.d.ts.map +0 -1
  53. package/dist/src/experiments/instrumention.js.map +0 -1
  54. /package/src/experiments/{instrumention.ts → instrumentation.ts} +0 -0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@arizeai/phoenix-client",
3
- "version": "4.0.0",
3
+ "version": "4.0.2",
4
4
  "description": "A client for the Phoenix API",
5
5
  "main": "dist/src/index.js",
6
6
  "module": "dist/esm/index.js",
package/src/client.ts CHANGED
@@ -1,4 +1,7 @@
1
- import createOpenApiClient, { type ClientOptions } from "openapi-fetch";
1
+ import createOpenApiClient, {
2
+ type Middleware,
3
+ type ClientOptions,
4
+ } from "openapi-fetch";
2
5
  import type {
3
6
  paths as oapiPathsV1,
4
7
  components as oapiComponentsV1,
@@ -49,6 +52,20 @@ export const getMergedOptions = ({
49
52
  };
50
53
  };
51
54
 
55
+ /**
56
+ * Middleware to take non-successful API calls throw instead of being swallowed
57
+ */
58
+ const middleware: Middleware = {
59
+ onResponse({ response }) {
60
+ if (!response.ok) {
61
+ // Will produce error messages like "https://example.org/api/v1/example: 404 Not Found".
62
+ throw new Error(
63
+ `${response.url}: ${response.status} ${response.statusText}`
64
+ );
65
+ }
66
+ },
67
+ };
68
+
52
69
  /**
53
70
  * Create a Phoenix client.
54
71
  *
@@ -79,8 +96,10 @@ export const createClient = (
79
96
  } = {}
80
97
  ) => {
81
98
  const mergedOptions = getMergedOptions(config);
99
+ const openApiClient = createOpenApiClient<pathsV1>(mergedOptions);
100
+ openApiClient.use(middleware);
82
101
  return {
83
- ...createOpenApiClient<pathsV1>(mergedOptions),
102
+ ...openApiClient,
84
103
  config: mergedOptions,
85
104
  };
86
105
  };
@@ -33,7 +33,7 @@ export async function appendDatasetExamples({
33
33
  const client = _client || createClient();
34
34
  const inputs = examples.map((example) => example.input);
35
35
  const outputs = examples.map((example) => example.output ?? {}); // Treat null as an empty object
36
- const metadata = examples.map((example) => example.metadata);
36
+ const metadata = examples.map((example) => example.metadata ?? {});
37
37
  let datasetName: string;
38
38
  if ("datasetName" in dataset) {
39
39
  datasetName = dataset.datasetName;
@@ -34,8 +34,8 @@ export async function createDataset({
34
34
  }: CreateDatasetParams): Promise<CreateDatasetResponse> {
35
35
  const client = _client || createClient();
36
36
  const inputs = examples.map((example) => example.input);
37
- const outputs = examples.map((example) => example.output ?? {}); // Treat null as an empty object
38
- const metadata = examples.map((example) => example.metadata);
37
+ const outputs = examples.map((example) => example?.output ?? {}); // Treat null as an empty object
38
+ const metadata = examples.map((example) => example?.metadata ?? {});
39
39
  const createDatasetResponse = await client.POST("/v1/datasets/upload", {
40
40
  params: {
41
41
  query: {
@@ -22,7 +22,7 @@ import { getDataset } from "../datasets/getDataset";
22
22
  import { pluralize } from "../utils/pluralize";
23
23
  import { promisifyResult } from "../utils/promisifyResult";
24
24
  import { AnnotatorKind } from "../types/annotations";
25
- import { createProvider, createNoOpProvider } from "./instrumention";
25
+ import { createProvider, createNoOpProvider } from "./instrumentation";
26
26
  import { SpanStatusCode, Tracer } from "@opentelemetry/api";
27
27
  import {
28
28
  MimeType,
@@ -37,7 +37,14 @@ import {
37
37
  getDatasetExperimentsUrl,
38
38
  getExperimentUrl,
39
39
  } from "../utils/urlUtils";
40
+ import assert from "assert";
40
41
 
42
+ /**
43
+ * Validate that a repetition is valid
44
+ */
45
+ function isValidRepetitionParam(repetitions: number) {
46
+ return Number.isInteger(repetitions) && repetitions > 0;
47
+ }
41
48
  /**
42
49
  * Parameters for running an experiment.
43
50
  *
@@ -95,6 +102,11 @@ export type RunExperimentParams = ClientFn & {
95
102
  */
96
103
  setGlobalTracerProvider?: boolean;
97
104
  /**
105
+ * Number of times to repeat each dataset example
106
+ * @default 1
107
+ */
108
+ repetitions?: number;
109
+ /*
98
110
  * Whether to use batching for the span processor.
99
111
  * @default true
100
112
  */
@@ -146,8 +158,14 @@ export async function runExperiment({
146
158
  concurrency = 5,
147
159
  dryRun = false,
148
160
  setGlobalTracerProvider = true,
161
+ repetitions = 1,
149
162
  useBatchSpanProcessor = true,
150
163
  }: RunExperimentParams): Promise<RanExperiment> {
164
+ // Validation
165
+ assert(
166
+ isValidRepetitionParam(repetitions),
167
+ "repetitions must be an integer greater than 0"
168
+ );
151
169
  let provider: NodeTracerProvider | undefined;
152
170
  const isDryRun = typeof dryRun === "number" || dryRun === true;
153
171
  const client = _client ?? createClient();
@@ -185,6 +203,7 @@ export async function runExperiment({
185
203
  description: experimentDescription,
186
204
  metadata: experimentMetadata,
187
205
  project_name: projectName,
206
+ repetitions,
188
207
  },
189
208
  })
190
209
  .then((res) => res.data?.data);
@@ -262,6 +281,7 @@ export async function runExperiment({
262
281
  isDryRun,
263
282
  nExamples,
264
283
  tracer: taskTracer,
284
+ repetitions,
265
285
  });
266
286
  logger.info(`✅ Task runs completed`);
267
287
 
@@ -315,6 +335,7 @@ function runTaskWithExamples({
315
335
  isDryRun,
316
336
  nExamples,
317
337
  tracer,
338
+ repetitions = 1,
318
339
  }: {
319
340
  /** The client to use */
320
341
  client: PhoenixClient;
@@ -336,9 +357,23 @@ function runTaskWithExamples({
336
357
  nExamples: number;
337
358
  /** TraceProvider instance that will be used to create spans from task calls */
338
359
  tracer: Tracer;
360
+ /** Number of repetitions per example */
361
+ repetitions?: number;
339
362
  }): Promise<void> {
363
+ // Validate the input
364
+ assert(
365
+ isValidRepetitionParam(repetitions),
366
+ "repetitions must be an integer greater than 0"
367
+ );
368
+
340
369
  logger.info(`🔧 Running task "${task.name}" on dataset "${dataset.id}"`);
341
- const run = async (example: ExampleWithId) => {
370
+ const run = async ({
371
+ example,
372
+ repetitionNumber,
373
+ }: {
374
+ example: ExampleWithId;
375
+ repetitionNumber: number;
376
+ }) => {
342
377
  return tracer.startActiveSpan(`Task: ${task.name}`, async (span) => {
343
378
  logger.info(
344
379
  `🔧 Running task "${task.name}" on example "${example.id} of dataset "${dataset.id}"`
@@ -374,7 +409,7 @@ function runTaskWithExamples({
374
409
  body: {
375
410
  dataset_example_id: example.id,
376
411
  output: thisRun.output,
377
- repetition_number: 0,
412
+ repetition_number: repetitionNumber,
378
413
  start_time: thisRun.startTime.toISOString(),
379
414
  end_time: thisRun.endTime.toISOString(),
380
415
  trace_id: thisRun.traceId,
@@ -404,15 +439,23 @@ function runTaskWithExamples({
404
439
  };
405
440
  const q = queue(run, concurrency);
406
441
  const examplesToUse = dataset.examples.slice(0, nExamples);
407
- examplesToUse.forEach((example) =>
408
- q.push(example, (err) => {
409
- if (err) {
410
- logger.error(
411
- `Error running task "${task.name}" on example "${example.id}": ${err}`
412
- );
413
- }
414
- })
415
- );
442
+
443
+ examplesToUse
444
+ .flatMap((example) =>
445
+ Array.from({ length: repetitions }, (_, index) => ({
446
+ example,
447
+ repetitionNumber: index + 1, // Repetitions start at 1
448
+ }))
449
+ )
450
+ .forEach((exampleWithRepetition) =>
451
+ q.push(exampleWithRepetition, (err) => {
452
+ if (err) {
453
+ logger.error(
454
+ `Error running task "${task.name}" on example "${exampleWithRepetition.example.id}" repetition ${exampleWithRepetition.repetitionNumber}: ${err}`
455
+ );
456
+ }
457
+ })
458
+ );
416
459
  return q.drain();
417
460
  }
418
461
 
@@ -674,7 +717,7 @@ async function runEvaluator({
674
717
  input: example.input,
675
718
  output: run.output ?? null,
676
719
  expected: example.output,
677
- metadata: example.metadata,
720
+ metadata: example?.metadata,
678
721
  });
679
722
  thisEval.result = result;
680
723
  logger.info(
@@ -47,8 +47,8 @@ export interface DatasetExamples {
47
47
  */
48
48
  export interface Example {
49
49
  input: Record<string, unknown>;
50
- output: Record<string, unknown> | null;
51
- metadata: Record<string, unknown>;
50
+ output?: Record<string, unknown> | null;
51
+ metadata?: Record<string, unknown> | null;
52
52
  }
53
53
 
54
54
  /**
@@ -67,7 +67,7 @@ export type EvaluatorParams = {
67
67
  /**
68
68
  * Metadata associated with the Dataset Example
69
69
  */
70
- metadata?: Record<string, unknown>;
70
+ metadata?: Example["metadata"];
71
71
  };
72
72
 
73
73
  export type Evaluator = {
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumention.d.ts","sourceRoot":"","sources":["../../../src/experiments/instrumention.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAEnB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAM/C;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,EACP,qBAA4B,GAC7B,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,cAAc,CAAC;IACxB;;;OAGG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,sBAuBA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,uBAIjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumention.js","sourceRoot":"","sources":["../../../src/experiments/instrumention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,iBAAiB,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAC3E,OAAO,EAAE,iBAAiB,EAAE,MAAM,0CAA0C,CAAC;AAC7E,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EACL,kBAAkB,GAEnB,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,wBAAwB,EAAE,MAAM,6CAA6C,CAAC;AAEvF,OAAO,EACL,+BAA+B,EAC/B,gCAAgC,GACjC,MAAM,+BAA+B,CAAC;AAEvC;;GAEG;AACH,MAAM,UAAU,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,EACP,qBAAqB,GAAG,IAAI,GAa7B;IACC,IAAI,CAAC,SAAS,CAAC,IAAI,iBAAiB,EAAE,EAAE,YAAY,CAAC,KAAK,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,IAAI,iBAAiB,CAAC;QACrC,GAAG,EAAE,GAAG,OAAO,YAAY;QAC3B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;KACxE,CAAC,CAAC;IAEH,IAAI,aAA4B,CAAC;IACjC,IAAI,qBAAqB,EAAE,CAAC;QAC1B,aAAa,GAAG,IAAI,+BAA+B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,IAAI,gCAAgC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC;QACtC,QAAQ,EAAE,sBAAsB,CAAC;YAC/B,CAAC,wBAAwB,CAAC,EAAE,WAAW;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,aAAa,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,kBAAkB;IAChC,MAAM,QAAQ,GAAG,IAAI,kBAAkB,CAAC,EAAE,CAAC,CAAC;IAE5C,OAAO,QAAQ,CAAC;AAClB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumention.d.ts","sourceRoot":"","sources":["../../../src/experiments/instrumention.ts"],"names":[],"mappings":"AAGA,OAAO,EACL,kBAAkB,EAEnB,MAAM,+BAA+B,CAAC;AAEvC,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAM/C;;GAEG;AACH,wBAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,EACP,qBAA4B,GAC7B,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,OAAO,EAAE,cAAc,CAAC;IACxB;;;OAGG;IACH,qBAAqB,EAAE,OAAO,CAAC;IAC/B;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;CACjB,sBAuBA;AAED;;GAEG;AACH,wBAAgB,kBAAkB,uBAIjC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"instrumention.js","sourceRoot":"","sources":["../../../src/experiments/instrumention.ts"],"names":[],"mappings":";;AAiBA,wCAwCC;AAKD,gDAIC;AAlED,4CAA2E;AAC3E,wFAA6E;AAC7E,wDAAkE;AAClE,kEAGuC;AACvC,oGAAuF;AAEvF,wEAGuC;AAEvC;;GAEG;AACH,SAAgB,cAAc,CAAC,EAC7B,WAAW,EACX,OAAO,EACP,OAAO,EACP,qBAAqB,GAAG,IAAI,GAa7B;IACC,UAAI,CAAC,SAAS,CAAC,IAAI,uBAAiB,EAAE,EAAE,kBAAY,CAAC,KAAK,CAAC,CAAC;IAE5D,MAAM,QAAQ,GAAG,IAAI,6CAAiB,CAAC;QACrC,GAAG,EAAE,GAAG,OAAO,YAAY;QAC3B,OAAO,EAAE,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO;KACxE,CAAC,CAAC;IAEH,IAAI,aAA4B,CAAC;IACjC,IAAI,qBAAqB,EAAE,CAAC;QAC1B,aAAa,GAAG,IAAI,sDAA+B,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,IAAI,uDAAgC,CAAC,EAAE,QAAQ,EAAE,CAAC,CAAC;IACrE,CAAC;IAED,MAAM,QAAQ,GAAG,IAAI,mCAAkB,CAAC;QACtC,QAAQ,EAAE,IAAA,kCAAsB,EAAC;YAC/B,CAAC,6DAAwB,CAAC,EAAE,WAAW;SACxC,CAAC;QACF,cAAc,EAAE,CAAC,aAAa,CAAC;KAChC,CAAC,CAAC;IAEH,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,SAAgB,kBAAkB;IAChC,MAAM,QAAQ,GAAG,IAAI,mCAAkB,CAAC,EAAE,CAAC,CAAC;IAE5C,OAAO,QAAQ,CAAC;AAClB,CAAC"}