evalution 1.0.1 → 1.0.3

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.
@@ -1,7 +1,7 @@
1
1
  import path from "node:path";
2
2
  import { SpanStatusCode, trace } from "@opentelemetry/api";
3
3
  import fs from "node:fs";
4
- import { generateText, streamText } from "ai";
4
+ import { generateText } from "ai";
5
5
  import { extractPropertiesFromDeclaration, findTypeDeclaration } from "ts-proppy";
6
6
  import ts from "typescript";
7
7
  //#region src/shared/helpers.ts
@@ -31,10 +31,9 @@ function isEditable(value) {
31
31
  */
32
32
  const SPAN_KIND_ATTRIBUTE = "evalution.span.type";
33
33
  /**
34
- * Attribute name a span can set to scope its {@link PROMPT_ID_ATTRIBUTE} to a
35
- * specific prompt provider. When absent, the prompt ID is treated as global.
34
+ * Attribute name a span can set to give a human-readable name to the prompt.
36
35
  */
37
- const PROMPT_PROVIDER_ID_ATTRIBUTE = "evalution.prompt.provider.id";
36
+ const PROMPT_NAME_ATTRIBUTE = "gen_ai.prompt.name";
38
37
  /**
39
38
  * Attribute name a span can set to link itself to a specific prompt. The value
40
39
  * is a globally-unique prompt ID unless {@link PROMPT_PROVIDER_ID_ATTRIBUTE} is
@@ -42,9 +41,24 @@ const PROMPT_PROVIDER_ID_ATTRIBUTE = "evalution.prompt.provider.id";
42
41
  */
43
42
  const PROMPT_ID_ATTRIBUTE = "evalution.prompt.id";
44
43
  /**
45
- * Attribute name a span can set to give a human-readable name to the prompt.
44
+ * Attribute name a span can set to scope its {@link PROMPT_ID_ATTRIBUTE} to a
45
+ * specific prompt provider. When absent, the prompt ID is treated as global.
46
46
  */
47
- const PROMPT_NAME_ATTRIBUTE = "gen_ai.prompt.name";
47
+ const PROMPT_PROVIDER_ID_ATTRIBUTE = "evalution.prompt.provider.id";
48
+ /**
49
+ * Attribute name a span can set to include an array of input parameters used
50
+ * to construct the final prompt.
51
+ */
52
+ const PROMPT_INPUTS_ATTRIBUTE = "evalution.prompt.inputs";
53
+ function getPromptSpanAttributes(prompt, attributes = {}) {
54
+ return Object.fromEntries([
55
+ [SPAN_KIND_ATTRIBUTE, "LLM"],
56
+ [PROMPT_NAME_ATTRIBUTE, prompt.name],
57
+ [PROMPT_ID_ATTRIBUTE, prompt.id],
58
+ [PROMPT_INPUTS_ATTRIBUTE, prompt.functionParameters],
59
+ ...Object.entries(attributes)
60
+ ].filter(([, v]) => v !== void 0 && v !== null));
61
+ }
48
62
  /**
49
63
  * Wraps a {@link Tracer} so that every span it produces is tagged with the
50
64
  * attributes that associate it with a prompt — the prompt's name
@@ -69,12 +83,7 @@ function createTracerForPrompt(prompt, tracer) {
69
83
  const inner = tracer ?? trace.getTracer("evalution");
70
84
  const withPromptAttributes = (options) => ({
71
85
  ...options,
72
- attributes: {
73
- [SPAN_KIND_ATTRIBUTE]: "LLM",
74
- [PROMPT_NAME_ATTRIBUTE]: prompt.name,
75
- ...prompt.id !== void 0 && { ["evalution.prompt.id"]: prompt.id },
76
- ...options?.attributes
77
- }
86
+ attributes: getPromptSpanAttributes(prompt, options?.attributes)
78
87
  });
79
88
  return {
80
89
  startSpan(name, options, context) {
@@ -171,9 +180,9 @@ function readLLM(attributes) {
171
180
  const messages = parseMessages(attributes["gen_ai.input.messages"] ?? attributes["ai.prompt.messages"]);
172
181
  const output = parseOutput(attributes["gen_ai.output.messages"]) ?? str(attributes["ai.response.text"]);
173
182
  const paramEntries = PARAM_ATTRIBUTES.map((key) => [key.replace("gen_ai.request.", ""), attributes[key]]).filter(([, v]) => v !== void 0);
174
- const parameters = paramEntries.length > 0 ? Object.fromEntries(paramEntries) : void 0;
183
+ const modelParameters = paramEntries.length > 0 ? Object.fromEntries(paramEntries) : void 0;
175
184
  const totalTokens = promptTokens !== void 0 && completionTokens !== void 0 ? promptTokens + completionTokens : void 0;
176
- if (!provider && !model && !promptTokens && !completionTokens && !messages && !output && !parameters) return;
185
+ if (!provider && !model && !promptTokens && !completionTokens && !messages && !output && !modelParameters) return;
177
186
  return {
178
187
  ...provider && { provider },
179
188
  ...model && { model },
@@ -182,7 +191,7 @@ function readLLM(attributes) {
182
191
  ...promptTokens !== void 0 && { promptTokens },
183
192
  ...completionTokens !== void 0 && { completionTokens },
184
193
  ...totalTokens !== void 0 && { totalTokens },
185
- ...parameters && { parameters }
194
+ ...modelParameters && { modelParameters }
186
195
  };
187
196
  }
188
197
  function llmAndPrompt(attributes) {
@@ -502,6 +511,93 @@ const RESERVED_KEYS = new Set([
502
511
  SYSTEM_KEY,
503
512
  MESSAGES_KEY
504
513
  ]);
514
+ const FALLBACK_CALL_SETTINGS_PARAMS = [
515
+ {
516
+ name: "maxOutputTokens",
517
+ description: "Maximum number of tokens to generate.",
518
+ type: {
519
+ kind: "primitive",
520
+ syntax: "number"
521
+ },
522
+ optional: true
523
+ },
524
+ {
525
+ name: "temperature",
526
+ description: "Temperature setting. The value is passed through to the provider. The range depends on the provider and model.",
527
+ type: {
528
+ kind: "primitive",
529
+ syntax: "number"
530
+ },
531
+ optional: true
532
+ },
533
+ {
534
+ name: "topP",
535
+ description: "Nucleus sampling. The value is passed through to the provider. The range depends on the provider and model.",
536
+ type: {
537
+ kind: "primitive",
538
+ syntax: "number"
539
+ },
540
+ optional: true
541
+ },
542
+ {
543
+ name: "topK",
544
+ description: "Only sample from the top K options for each subsequent token.",
545
+ type: {
546
+ kind: "primitive",
547
+ syntax: "number"
548
+ },
549
+ optional: true
550
+ },
551
+ {
552
+ name: "presencePenalty",
553
+ description: "Presence penalty setting. It affects the likelihood of the model to repeat information that is already in the prompt.",
554
+ type: {
555
+ kind: "primitive",
556
+ syntax: "number"
557
+ },
558
+ optional: true
559
+ },
560
+ {
561
+ name: "frequencyPenalty",
562
+ description: "Frequency penalty setting. It affects the likelihood of the model to repeatedly use the same words or phrases.",
563
+ type: {
564
+ kind: "primitive",
565
+ syntax: "number"
566
+ },
567
+ optional: true
568
+ },
569
+ {
570
+ name: "stopSequences",
571
+ description: "Stop sequences. If set, the model will stop generating text.",
572
+ type: {
573
+ kind: "array",
574
+ syntax: "string[]",
575
+ elementType: {
576
+ kind: "primitive",
577
+ syntax: "string"
578
+ }
579
+ },
580
+ optional: true
581
+ },
582
+ {
583
+ name: "seed",
584
+ description: "The seed (integer) to use for random sampling.",
585
+ type: {
586
+ kind: "primitive",
587
+ syntax: "number"
588
+ },
589
+ optional: true
590
+ },
591
+ {
592
+ name: "maxRetries",
593
+ description: "Maximum number of retries. Set to 0 to disable retries.",
594
+ type: {
595
+ kind: "primitive",
596
+ syntax: "number"
597
+ },
598
+ optional: true
599
+ }
600
+ ];
505
601
  /** The `prompts()` factory from `@evalution/vercel-ai-sdk`. */
506
602
  const PROMPTS_HELPER_CALL = {
507
603
  callee: "prompts",
@@ -581,7 +677,10 @@ export default {
581
677
  */
582
678
  var VercelAISDK = class {
583
679
  promptsHelperImport = PROMPTS_HELPER_CALL.import.from;
584
- /** Onboarding task: install the SDK package, then drop a starter config. */
680
+ /**
681
+ * Onboarding task: install the SDK package, then drop a starter config.
682
+ * @internal
683
+ */
585
684
  static setupTask = {
586
685
  id: "vercel-ai-sdk",
587
686
  label: "AI SDK",
@@ -639,24 +738,19 @@ var VercelAISDK = class {
639
738
  });
640
739
  }
641
740
  getModelParameters(rootDir) {
642
- const dtsPath = findPackageDts("ai", "dist/index.d.ts", rootDir);
643
- if (!dtsPath) return [];
644
- const sourceText = fs.readFileSync(dtsPath, "utf-8");
645
- const sourceFile = ts.createSourceFile(dtsPath, sourceText, ts.ScriptTarget.Latest, true);
646
- const decl = findTypeDeclaration(sourceFile, "CallSettings");
647
- if (!decl) return [];
648
- return extractPropertiesFromDeclaration(decl, sourceFile).definitions;
741
+ try {
742
+ const dtsPath = findPackageDts("ai", "dist/index.d.ts", rootDir);
743
+ if (dtsPath) {
744
+ const sourceText = fs.readFileSync(dtsPath, "utf-8");
745
+ const sourceFile = ts.createSourceFile(dtsPath, sourceText, ts.ScriptTarget.Latest, true);
746
+ const decl = findTypeDeclaration(sourceFile, "CallSettings");
747
+ if (decl) return extractPropertiesFromDeclaration(decl, sourceFile).definitions;
748
+ }
749
+ } catch {}
750
+ return FALLBACK_CALL_SETTINGS_PARAMS;
649
751
  }
650
- async executeConfig(config, stream) {
651
- if (stream) return (await streamText(config)).textStream;
652
- else {
653
- const result = await generateText(config);
654
- return {
655
- text: result.text,
656
- usage: result.usage,
657
- finishReason: result.finishReason
658
- };
659
- }
752
+ async executeConfig(config) {
753
+ await generateText(config);
660
754
  }
661
755
  normalizePrompt(prompt) {
662
756
  const { definitions, values } = prompt.extractedProps;
@@ -756,4 +850,4 @@ function extractToolCalls(value) {
756
850
  return out.length > 0 ? out : void 0;
757
851
  }
758
852
  //#endregion
759
- export { MemoryTraceProvider as a, PROMPT_PROVIDER_ID_ATTRIBUTE as c, isEditable as d, setupStepCommand as i, SPAN_KIND_ATTRIBUTE as l, findPackageDts as n, PROMPT_ID_ATTRIBUTE as o, CONFIG_FILE_RELATIVE_PATH as r, PROMPT_NAME_ATTRIBUTE as s, VercelAISDK as t, createTracerForPrompt as u };
853
+ export { MemoryTraceProvider as a, PROMPT_NAME_ATTRIBUTE as c, createTracerForPrompt as d, getPromptSpanAttributes as f, setupStepCommand as i, PROMPT_PROVIDER_ID_ATTRIBUTE as l, findPackageDts as n, PROMPT_ID_ATTRIBUTE as o, isEditable as p, CONFIG_FILE_RELATIVE_PATH as r, PROMPT_INPUTS_ATTRIBUTE as s, VercelAISDK as t, SPAN_KIND_ATTRIBUTE as u };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "evalution",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "description": "TypeScript AI Prompt Playground - Edit and execute AI prompts with live preview",
5
5
  "type": "module",
6
6
  "exports": {
@@ -58,7 +58,7 @@
58
58
  "minimatch": "^10.2.4",
59
59
  "react": ">=18.2.0",
60
60
  "react-dom": ">=18.2.0",
61
- "ts-proppy": "0.2.1",
61
+ "ts-proppy": "0.2.3",
62
62
  "typescript": ">=5.3.3",
63
63
  "ws": "^8.21.0"
64
64
  },