@lmnr-ai/lmnr 0.6.10 → 0.6.11

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.
package/dist/index.js CHANGED
@@ -31,6 +31,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
33
  Dataset: () => EvaluationDataset,
34
+ HumanEvaluator: () => HumanEvaluator,
34
35
  Laminar: () => Laminar,
35
36
  LaminarAttributes: () => LaminarAttributes,
36
37
  LaminarClient: () => LaminarClient,
@@ -485,7 +486,7 @@ var AgentResource = class extends BaseResource {
485
486
  };
486
487
 
487
488
  // package.json
488
- var version = "0.6.10";
489
+ var version = "0.6.11";
489
490
 
490
491
  // src/version.ts
491
492
  var getLangVersion = () => {
@@ -553,6 +554,81 @@ var EvalsResource = class extends BaseResource {
553
554
  }
554
555
  return response.json();
555
556
  }
557
+ /**
558
+ * Create a new evaluation and return its ID.
559
+ *
560
+ * @param {string} [name] - Optional name of the evaluation
561
+ * @param {string} [groupName] - An identifier to group evaluations
562
+ * @returns {Promise<StringUUID>} The evaluation ID
563
+ */
564
+ async createEvaluation(name, groupName) {
565
+ const evaluation = await this.init(name, groupName);
566
+ return evaluation.id;
567
+ }
568
+ /**
569
+ * Create a datapoint for an evaluation.
570
+ *
571
+ * @param {Object} options - Create datapoint options
572
+ * @param {string} options.evalId - The evaluation ID
573
+ * @param {D} options.data - The input data for the executor
574
+ * @param {T} [options.target] - The target/expected output for evaluators
575
+ * @param {Record<string, any>} [options.metadata] - Optional metadata
576
+ * @param {number} [options.index] - Optional index of the datapoint
577
+ * @param {string} [options.traceId] - Optional trace ID
578
+ * @returns {Promise<StringUUID>} The datapoint ID
579
+ */
580
+ async createDatapoint({
581
+ evalId,
582
+ data,
583
+ target,
584
+ metadata,
585
+ index,
586
+ traceId
587
+ }) {
588
+ const datapointId = newUUID();
589
+ const partialDatapoint = {
590
+ id: datapointId,
591
+ data,
592
+ target,
593
+ index: index ?? 0,
594
+ traceId: traceId ?? newUUID(),
595
+ executorSpanId: newUUID(),
596
+ metadata
597
+ };
598
+ await this.saveDatapoints({
599
+ evalId,
600
+ datapoints: [partialDatapoint]
601
+ });
602
+ return datapointId;
603
+ }
604
+ /**
605
+ * Update a datapoint with evaluation results.
606
+ *
607
+ * @param {Object} options - Update datapoint options
608
+ * @param {string} options.evalId - The evaluation ID
609
+ * @param {string} options.datapointId - The datapoint ID
610
+ * @param {Record<string, number>} options.scores - The scores
611
+ * @param {O} [options.executorOutput] - The executor output
612
+ * @returns {Promise<void>}
613
+ */
614
+ async updateDatapoint({
615
+ evalId,
616
+ datapointId,
617
+ scores,
618
+ executorOutput
619
+ }) {
620
+ const response = await fetch(this.baseHttpUrl + `/v1/evals/${evalId}/datapoints/${datapointId}`, {
621
+ method: "POST",
622
+ headers: this.headers(),
623
+ body: JSON.stringify({
624
+ executorOutput,
625
+ scores
626
+ })
627
+ });
628
+ if (!response.ok) {
629
+ await this.handleError(response);
630
+ }
631
+ }
556
632
  /**
557
633
  * Save evaluation datapoints.
558
634
  *
@@ -1475,6 +1551,39 @@ var prettyPrintZodSchema = (schema, indent = 2) => {
1475
1551
  ${reconstructed.join("\n")}
1476
1552
  })`;
1477
1553
  };
1554
+ var modelToProviderMap = {
1555
+ "gpt-4.1": "openai",
1556
+ "gpt-4.1-mini": "openai",
1557
+ "gpt-4.1-nano": "openai",
1558
+ "o4-mini": "openai",
1559
+ //prettier-ignore
1560
+ "o3": "openai",
1561
+ "o3-mini": "openai",
1562
+ //prettier-ignore
1563
+ "o1": "openai",
1564
+ "o1-mini": "openai",
1565
+ "gpt-4o": "openai",
1566
+ "gpt-4o-mini": "openai",
1567
+ "gpt-4o-2024-08-06": "openai",
1568
+ "gpt-4.5-preview": "openai",
1569
+ "o1-preview": "openai",
1570
+ "claude-3-5-sonnet-latest": "anthropic",
1571
+ "claude-3-5-sonnet-20240620": "anthropic",
1572
+ "claude-3-5-sonnet-20241022": "anthropic",
1573
+ "claude-3-7-sonnet-20250219": "anthropic",
1574
+ "claude-3-7-sonnet-latest": "anthropic",
1575
+ "cerebras-llama-3.3-70b": "cerebras",
1576
+ "cerebras-llama-3.1-8b": "cerebras",
1577
+ "groq-llama-3.3-70b-versatile": "groq",
1578
+ "groq-llama-3.3-70b-specdec": "groq",
1579
+ "gemini-1.5-flash": "google",
1580
+ "gemini-1.5-pro": "google",
1581
+ "gemini-1.5-flash-8b": "google",
1582
+ "gemini-2.0-flash-lite": "google",
1583
+ "gemini-2.0-flash": "google",
1584
+ "gemini-2.5-flash-preview-04-17": "google",
1585
+ "gemini-2.5-pro-preview-03-25": "google"
1586
+ };
1478
1587
 
1479
1588
  // src/browser/playwright.ts
1480
1589
  var logger5 = initializeLogger();
@@ -1978,6 +2087,15 @@ var StagehandInstrumentation = class extends import_instrumentation2.Instrumenta
1978
2087
  const result = await original.bind(this).apply(this, args);
1979
2088
  await instrumentation.playwrightInstrumentation.patchPage(this.page);
1980
2089
  instrumentation.patchStagehandPage(this.stagehandPage);
2090
+ instrumentation.globalLLMClientOptions = {
2091
+ provider: this.llmClient.type,
2092
+ model: this.llmClient.modelName
2093
+ };
2094
+ instrumentation._wrap(
2095
+ this.llmClient,
2096
+ "createChatCompletion",
2097
+ instrumentation.patchStagehandLLMClientCreateChatCompletion()
2098
+ );
1981
2099
  return result;
1982
2100
  };
1983
2101
  }
@@ -2025,16 +2143,20 @@ var StagehandInstrumentation = class extends import_instrumentation2.Instrumenta
2025
2143
  }
2026
2144
  const extractHandler = page.extractHandler;
2027
2145
  if (extractHandler) {
2028
- this._wrap(
2029
- extractHandler,
2030
- "textExtract",
2031
- this.patchStagehandExtractHandlerTextExtract()
2032
- );
2033
- this._wrap(
2034
- extractHandler,
2035
- "domExtract",
2036
- this.patchStagehandExtractHandlerDomExtract()
2037
- );
2146
+ if (extractHandler.textExtract) {
2147
+ this._wrap(
2148
+ extractHandler,
2149
+ "textExtract",
2150
+ this.patchStagehandExtractHandlerTextExtract()
2151
+ );
2152
+ }
2153
+ if (extractHandler.domExtract) {
2154
+ this._wrap(
2155
+ extractHandler,
2156
+ "domExtract",
2157
+ this.patchStagehandExtractHandlerDomExtract()
2158
+ );
2159
+ }
2038
2160
  }
2039
2161
  this._wrap(
2040
2162
  page,
@@ -2196,6 +2318,92 @@ var StagehandInstrumentation = class extends import_instrumentation2.Instrumenta
2196
2318
  );
2197
2319
  };
2198
2320
  }
2321
+ patchStagehandLLMClientCreateChatCompletion() {
2322
+ const instrumentation = this;
2323
+ return (original) => async function createChatCompletion(...args) {
2324
+ const options = args[0];
2325
+ return await observe({
2326
+ name: "createChatCompletion",
2327
+ // input and output are set as gen_ai.prompt and gen_ai.completion
2328
+ ignoreInput: true,
2329
+ ignoreOutput: true
2330
+ }, async () => {
2331
+ const span = import_api6.trace.getActiveSpan();
2332
+ const innerOptions = options.options;
2333
+ const recordedProvider = instrumentation.globalLLMClientOptions?.provider;
2334
+ const provider = recordedProvider === "aisdk" && instrumentation.globalLLMClientOptions?.model ? modelToProviderMap[instrumentation.globalLLMClientOptions.model] ?? "aisdk" : recordedProvider;
2335
+ span.setAttributes({
2336
+ [SPAN_TYPE]: "LLM",
2337
+ ...innerOptions.temperature ? {
2338
+ "gen_ai.request.temperature": innerOptions.temperature
2339
+ } : {},
2340
+ ...innerOptions.top_p ? {
2341
+ "gen_ai.request.top_p": innerOptions.top_p
2342
+ } : {},
2343
+ ...innerOptions.frequency_penalty ? {
2344
+ "gen_ai.request.frequency_penalty": innerOptions.frequency_penalty
2345
+ } : {},
2346
+ ...innerOptions.presence_penalty ? {
2347
+ "gen_ai.request.presence_penalty": innerOptions.presence_penalty
2348
+ } : {},
2349
+ ...innerOptions.maxTokens !== void 0 ? {
2350
+ "gen_ai.request.max_tokens": innerOptions.maxTokens
2351
+ } : {},
2352
+ ...instrumentation.globalLLMClientOptions ? {
2353
+ "gen_ai.request.model": instrumentation.globalLLMClientOptions.model,
2354
+ "gen_ai.system": provider
2355
+ } : {}
2356
+ });
2357
+ innerOptions.messages?.forEach((message, index) => {
2358
+ span.setAttributes({
2359
+ [`gen_ai.prompt.${index}.role`]: message.role,
2360
+ [`gen_ai.prompt.${index}.content`]: JSON.stringify(message.content)
2361
+ });
2362
+ });
2363
+ innerOptions.tools?.forEach((tool, index) => {
2364
+ span.setAttributes({
2365
+ [`llm.request.functions.${index}.name`]: tool.name,
2366
+ [`llm.request.functions.${index}.description`]: tool.description,
2367
+ [`llm.request.functions.${index}.parameters`]: JSON.stringify(tool.parameters)
2368
+ });
2369
+ });
2370
+ const result = await original.bind(this).apply(this, args);
2371
+ span.setAttributes({
2372
+ "gen_ai.response.model": result.model,
2373
+ "gen_ai.usage.input_tokens": result.usage.prompt_tokens,
2374
+ "gen_ai.usage.output_tokens": result.usage.completion_tokens,
2375
+ "llm.usage.total_tokens": result.usage.total_tokens
2376
+ });
2377
+ result.choices?.forEach((choice) => {
2378
+ const index = choice.index;
2379
+ span.setAttributes({
2380
+ [`gen_ai.completion.${index}.finish_reason`]: choice.finish_reason,
2381
+ [`gen_ai.completion.${index}.role`]: choice.message.role
2382
+ });
2383
+ if (choice.message.content) {
2384
+ span.setAttribute(`gen_ai.completion.${index}.content`, JSON.stringify(choice.message.content));
2385
+ }
2386
+ choice.message.tool_calls?.forEach((toolCall, toolCallIndex) => {
2387
+ span.setAttributes({
2388
+ [`gen_ai.completion.${index}.message.tool_calls.${toolCallIndex}.id`]: toolCall.id,
2389
+ [`gen_ai.completion.${index}.message.tool_calls.${toolCallIndex}.name`]: toolCall.function.name,
2390
+ [`gen_ai.completion.${index}.message.tool_calls.${toolCallIndex}.arguments`]: JSON.stringify(toolCall.function.arguments)
2391
+ });
2392
+ });
2393
+ });
2394
+ if (!result.choices || result.choices.length === 0) {
2395
+ const data = result.data;
2396
+ if (data) {
2397
+ span.setAttributes({
2398
+ "gen_ai.completion.0.role": "assistant",
2399
+ "gen_ai.completion.0.content": typeof data === "string" ? data : JSON.stringify(data)
2400
+ });
2401
+ }
2402
+ }
2403
+ return result;
2404
+ });
2405
+ };
2406
+ }
2199
2407
  };
2200
2408
 
2201
2409
  // src/browser/puppeteer.ts
@@ -3298,10 +3506,11 @@ var getAverageScores = (results) => {
3298
3506
  const perScoreValues = {};
3299
3507
  for (const result of results) {
3300
3508
  for (const key in result.scores) {
3301
- if (perScoreValues[key]) {
3302
- perScoreValues[key].push(result.scores[key]);
3509
+ const score = result.scores[key];
3510
+ if (perScoreValues[key] && score !== null) {
3511
+ perScoreValues[key].push(score);
3303
3512
  } else {
3304
- perScoreValues[key] = [result.scores[key]];
3513
+ perScoreValues[key] = score !== null ? [score] : [];
3305
3514
  }
3306
3515
  }
3307
3516
  }
@@ -3311,6 +3520,8 @@ var getAverageScores = (results) => {
3311
3520
  }
3312
3521
  return averageScores;
3313
3522
  };
3523
+ var HumanEvaluator = class {
3524
+ };
3314
3525
  var EvaluationReporter = class {
3315
3526
  constructor(baseUrl) {
3316
3527
  this.cliProgress = new import_cli_progress.default.SingleBar(
@@ -3517,18 +3728,27 @@ var Evaluation = class {
3517
3728
  const value = await observe(
3518
3729
  { name: evaluatorName },
3519
3730
  async (output2, target2) => {
3520
- import_api13.trace.getActiveSpan().setAttribute(SPAN_TYPE, "EVALUATOR");
3521
- return await evaluator(output2, target2);
3731
+ if (evaluator instanceof HumanEvaluator) {
3732
+ import_api13.trace.getActiveSpan().setAttribute(SPAN_TYPE, "HUMAN_EVALUATOR");
3733
+ return null;
3734
+ } else {
3735
+ import_api13.trace.getActiveSpan().setAttribute(SPAN_TYPE, "EVALUATOR");
3736
+ return await evaluator(output2, target2);
3737
+ }
3522
3738
  },
3523
3739
  output,
3524
3740
  target
3525
3741
  );
3742
+ if (evaluator instanceof HumanEvaluator) {
3743
+ scores[evaluatorName] = null;
3744
+ continue;
3745
+ }
3526
3746
  if (typeof value === "number") {
3527
3747
  if (isNaN(value)) {
3528
3748
  throw new Error(`Evaluator ${evaluatorName} returned NaN`);
3529
3749
  }
3530
3750
  scores[evaluatorName] = value;
3531
- } else {
3751
+ } else if (value !== null) {
3532
3752
  scores = { ...scores, ...value };
3533
3753
  }
3534
3754
  }
@@ -3592,6 +3812,7 @@ var import_api14 = require("@opentelemetry/api");
3592
3812
  // Annotate the CommonJS export names for ESM import in node:
3593
3813
  0 && (module.exports = {
3594
3814
  Dataset,
3815
+ HumanEvaluator,
3595
3816
  Laminar,
3596
3817
  LaminarAttributes,
3597
3818
  LaminarClient,