promptfoo 0.18.4 → 0.19.1

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 (161) hide show
  1. package/dist/package.json +10 -5
  2. package/dist/src/evaluator.d.ts.map +1 -1
  3. package/dist/src/evaluator.js +17 -9
  4. package/dist/src/evaluator.js.map +1 -1
  5. package/dist/src/index.d.ts +1 -0
  6. package/dist/src/index.d.ts.map +1 -1
  7. package/dist/src/index.js +3 -0
  8. package/dist/src/index.js.map +1 -1
  9. package/dist/src/main.js +2 -2
  10. package/dist/src/main.js.map +1 -1
  11. package/dist/src/providers/openai.d.ts +4 -0
  12. package/dist/src/providers/openai.d.ts.map +1 -1
  13. package/dist/src/providers/openai.js +22 -7
  14. package/dist/src/providers/openai.js.map +1 -1
  15. package/dist/src/providers.d.ts +1 -1
  16. package/dist/src/providers.d.ts.map +1 -1
  17. package/dist/src/providers.js +5 -0
  18. package/dist/src/providers.js.map +1 -1
  19. package/dist/src/share.d.ts.map +1 -1
  20. package/dist/src/share.js +8 -7
  21. package/dist/src/share.js.map +1 -1
  22. package/dist/src/types.d.ts +9 -1
  23. package/dist/src/types.d.ts.map +1 -1
  24. package/dist/src/web/nextui/404/index.html +1 -0
  25. package/dist/src/web/nextui/404.html +1 -0
  26. package/dist/src/web/nextui/_next/static/chunks/121-54cee610700b4756.js +27 -0
  27. package/dist/src/web/nextui/_next/static/chunks/339-501c32916b785ef1.js +1 -0
  28. package/dist/src/web/nextui/_next/static/chunks/373-6a411db0b05027d3.js +1 -0
  29. package/dist/src/web/nextui/_next/static/chunks/583-507e6d8883bb85ff.js +1 -0
  30. package/dist/src/web/nextui/_next/static/chunks/596-9c29c47b8dee7a50.js +25 -0
  31. package/dist/src/web/nextui/_next/static/chunks/658-f8f9d18540505edc.js +15 -0
  32. package/dist/src/web/nextui/_next/static/chunks/858-7255df6dbc44dff9.js +125 -0
  33. package/dist/src/web/nextui/_next/static/chunks/97-64e11ce2b0607459.js +1 -0
  34. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/not-found-366629541fd598e9.js +1 -0
  35. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/page-655bc42ac68b25cc.js +1 -0
  36. package/dist/src/web/nextui/_next/static/chunks/app/eval/page-d5e8697859d6294e.js +1 -0
  37. package/dist/src/web/nextui/_next/static/chunks/app/layout-4c714b1a5a3a768d.js +1 -0
  38. package/dist/src/web/nextui/_next/static/chunks/app/page-4fe8a6342d24ca23.js +1 -0
  39. package/dist/src/web/nextui/_next/static/chunks/app/setup/page-cd35686fe6c12be8.js +1 -0
  40. package/dist/src/web/nextui/_next/static/chunks/fd9d1056-d8847af536b5787b.js +9 -0
  41. package/dist/src/web/nextui/_next/static/chunks/framework-8883d1e9be70c3da.js +25 -0
  42. package/dist/src/web/nextui/_next/static/chunks/main-0670de04b1c026b4.js +1 -0
  43. package/dist/src/web/nextui/_next/static/chunks/main-app-581ccf0003955b21.js +1 -0
  44. package/dist/src/web/nextui/_next/static/chunks/pages/_app-52924524f99094ab.js +1 -0
  45. package/dist/src/web/nextui/_next/static/chunks/pages/_error-c92d5c4bb2b49926.js +1 -0
  46. package/dist/src/web/nextui/_next/static/chunks/polyfills-78c92fac7aa8fdd8.js +1 -0
  47. package/dist/src/web/nextui/_next/static/chunks/webpack-a886dd767c2e76b7.js +1 -0
  48. package/dist/src/web/nextui/_next/static/css/48d388184a2f4ce3.css +1 -0
  49. package/dist/src/web/nextui/_next/static/css/7265c36d84346934.css +1 -0
  50. package/dist/src/web/nextui/_next/static/css/8119d8bd13a8adab.css +1 -0
  51. package/dist/src/web/nextui/_next/static/css/a35c840ac696f161.css +1 -0
  52. package/dist/src/web/nextui/_next/static/css/e388dd377baf25ec.css +1 -0
  53. package/dist/src/web/nextui/_next/static/css/fc460b8a7cadb952.css +1 -0
  54. package/dist/src/web/nextui/_next/static/i1iOxHlErUK1hGZ9mGI2E/_buildManifest.js +1 -0
  55. package/dist/src/web/nextui/_next/static/i1iOxHlErUK1hGZ9mGI2E/_ssgManifest.js +1 -0
  56. package/dist/src/web/nextui/_next/static/media/0e4fe491bf84089c-s.p.woff2 +0 -0
  57. package/dist/src/web/nextui/_next/static/media/1c57ca6f5208a29b-s.woff2 +0 -0
  58. package/dist/src/web/nextui/_next/static/media/3dbd163d3bb09d47-s.woff2 +0 -0
  59. package/dist/src/web/nextui/_next/static/media/42d52f46a26971a3-s.woff2 +0 -0
  60. package/dist/src/web/nextui/_next/static/media/5647e4c23315a2d2-s.woff2 +0 -0
  61. package/dist/src/web/nextui/_next/static/media/627622453ef56b0d-s.p.woff2 +0 -0
  62. package/dist/src/web/nextui/_next/static/media/7be645d133f3ee22-s.woff2 +0 -0
  63. package/dist/src/web/nextui/_next/static/media/7c53f7419436e04b-s.woff2 +0 -0
  64. package/dist/src/web/nextui/_next/static/media/8fb72f69fba4e3d2-s.woff2 +0 -0
  65. package/dist/src/web/nextui/_next/static/media/912a9cfe43c928d9-s.woff2 +0 -0
  66. package/dist/src/web/nextui/_next/static/media/934c4b7cb736f2a3-s.p.woff2 +0 -0
  67. package/dist/src/web/nextui/_next/static/media/a5b77b63ef20339c-s.woff2 +0 -0
  68. package/dist/src/web/nextui/_next/static/media/a6d330d7873e7320-s.woff2 +0 -0
  69. package/dist/src/web/nextui/_next/static/media/baf12dd90520ae41-s.woff2 +0 -0
  70. package/dist/src/web/nextui/_next/static/media/bbdb6f0234009aba-s.woff2 +0 -0
  71. package/dist/src/web/nextui/_next/static/media/cff529cd86cc0276-s.woff2 +0 -0
  72. package/dist/src/web/nextui/_next/static/media/d117eea74e01de14-s.woff2 +0 -0
  73. package/dist/src/web/nextui/_next/static/media/dfa8b99978df7bbc-s.woff2 +0 -0
  74. package/dist/src/web/nextui/_next/static/media/e25729ca87cc7df9-s.woff2 +0 -0
  75. package/dist/src/web/nextui/_next/static/media/eb52b768f62eeeb4-s.woff2 +0 -0
  76. package/dist/src/web/nextui/_next/static/media/f06116e890b3dadb-s.woff2 +0 -0
  77. package/dist/src/web/nextui/api +1 -0
  78. package/dist/src/web/nextui/eval/index.html +1 -0
  79. package/dist/src/web/nextui/eval/index.txt +13 -0
  80. package/dist/src/web/nextui/index.html +1 -0
  81. package/dist/src/web/nextui/index.txt +13 -0
  82. package/dist/src/web/nextui/setup/index.html +1 -0
  83. package/dist/src/web/nextui/setup/index.txt +14 -0
  84. package/dist/src/web/server.d.ts +1 -1
  85. package/dist/src/web/server.d.ts.map +1 -1
  86. package/dist/src/web/server.js +47 -4
  87. package/dist/src/web/server.js.map +1 -1
  88. package/package.json +10 -5
  89. package/src/evaluator.ts +17 -9
  90. package/src/index.ts +7 -1
  91. package/src/main.ts +3 -3
  92. package/src/providers/openai.ts +26 -7
  93. package/src/providers.ts +11 -2
  94. package/src/share.ts +10 -8
  95. package/src/types.ts +10 -1
  96. package/src/web/nextui/.eslintrc.json +3 -0
  97. package/src/web/nextui/next.config.js +14 -0
  98. package/src/web/nextui/package-lock.json +4615 -0
  99. package/src/web/nextui/package.json +45 -0
  100. package/src/web/nextui/src/app/Home.css +3 -0
  101. package/src/web/nextui/src/app/api/route.ts +6 -0
  102. package/src/web/{client/src/NavBar.css → nextui/src/app/components/DarkMode.css} +1 -0
  103. package/src/web/{client/src/NavBar.tsx → nextui/src/app/components/DarkMode.tsx} +4 -9
  104. package/src/web/nextui/src/app/components/Logo.css +32 -0
  105. package/src/web/nextui/src/app/components/PageShell.css +33 -0
  106. package/src/web/nextui/src/app/components/PageShell.tsx +87 -0
  107. package/src/web/{client/src → nextui/src/app/eval}/ConfigModal.tsx +8 -5
  108. package/src/web/nextui/src/app/eval/Eval.css +13 -0
  109. package/src/web/nextui/src/app/eval/Eval.tsx +79 -0
  110. package/src/web/{client/src → nextui/src/app/eval}/EvalOutputPromptDialog.tsx +2 -2
  111. package/src/web/{client/src → nextui/src/app/eval}/ResultsTable.css +10 -12
  112. package/src/web/{client/src → nextui/src/app/eval}/ResultsTable.tsx +57 -14
  113. package/src/web/{client/src → nextui/src/app/eval}/ResultsView.tsx +4 -4
  114. package/src/web/nextui/src/app/eval/[id]/not-found.tsx +5 -0
  115. package/src/web/nextui/src/app/eval/[id]/page.css +9 -0
  116. package/src/web/nextui/src/app/eval/[id]/page.tsx +20 -0
  117. package/src/web/nextui/src/app/eval/index.css +0 -0
  118. package/src/web/nextui/src/app/eval/page.tsx +8 -0
  119. package/src/web/{client/src → nextui/src/app/eval}/store.ts +2 -2
  120. package/src/web/nextui/src/app/eval/types.ts +20 -0
  121. package/src/web/{client/src/index.css → nextui/src/app/globals.css} +21 -3
  122. package/src/web/nextui/src/app/layout.tsx +25 -0
  123. package/src/web/nextui/src/app/page.tsx +7 -0
  124. package/src/web/nextui/src/app/setup/AssertsForm.tsx +118 -0
  125. package/src/web/nextui/src/app/setup/PromptDialog.tsx +77 -0
  126. package/src/web/nextui/src/app/setup/PromptsSection.tsx +190 -0
  127. package/src/web/nextui/src/app/setup/ProviderConfigDialog.tsx +99 -0
  128. package/src/web/nextui/src/app/setup/ProviderSelector.tsx +149 -0
  129. package/src/web/nextui/src/app/setup/RunTestSuiteButton.tsx +88 -0
  130. package/src/web/nextui/src/app/setup/TestCaseDialog.tsx +108 -0
  131. package/src/web/nextui/src/app/setup/TestCasesSection.tsx +154 -0
  132. package/src/web/nextui/src/app/setup/VarsForm.tsx +57 -0
  133. package/src/web/nextui/src/app/setup/page.css +3 -0
  134. package/src/web/nextui/src/app/setup/page.tsx +160 -0
  135. package/src/web/nextui/src/util/api.ts +1 -0
  136. package/src/web/nextui/src/util/store.ts +53 -0
  137. package/src/web/nextui/tsconfig.json +28 -0
  138. package/src/web/server.ts +56 -2
  139. package/dist/src/web/client/assets/index-6d2a3573.js +0 -200
  140. package/dist/src/web/client/assets/index-d2b6a160.css +0 -1
  141. package/dist/src/web/client/assets/js-yaml-8bbf9398.js +0 -32
  142. package/dist/src/web/client/index.html +0 -15
  143. package/src/web/client/.eslintrc.cjs +0 -14
  144. package/src/web/client/index.html +0 -13
  145. package/src/web/client/package-lock.json +0 -5726
  146. package/src/web/client/package.json +0 -39
  147. package/src/web/client/src/App.css +0 -4
  148. package/src/web/client/src/App.tsx +0 -120
  149. package/src/web/client/src/Logo.css +0 -18
  150. package/src/web/client/src/main.tsx +0 -10
  151. package/src/web/client/src/types.ts +0 -36
  152. package/src/web/client/src/vite-env.d.ts +0 -1
  153. package/src/web/client/tsconfig.json +0 -24
  154. package/src/web/client/tsconfig.node.json +0 -10
  155. package/src/web/client/vite.config.ts +0 -7
  156. /package/dist/src/web/{client → nextui}/favicon.ico +0 -0
  157. /package/dist/src/web/{client → nextui}/logo.svg +0 -0
  158. /package/src/web/{client → nextui}/public/favicon.ico +0 -0
  159. /package/src/web/{client → nextui}/public/logo.svg +0 -0
  160. /package/src/web/{client/src → nextui/src/app/components}/Logo.tsx +0 -0
  161. /package/src/web/{client/src → nextui/src/app/eval}/ShareModal.tsx +0 -0
package/src/main.ts CHANGED
@@ -24,7 +24,7 @@ import {
24
24
  import { DEFAULT_README, DEFAULT_YAML_CONFIG, DEFAULT_PROMPTS } from './onboarding';
25
25
  import { disableCache, clearCache } from './cache';
26
26
  import { getDirectory } from './esm';
27
- import { init } from './web/server';
27
+ import { startServer } from './web/server';
28
28
  import { checkForUpdates } from './updates';
29
29
 
30
30
  import type {
@@ -127,7 +127,7 @@ async function main() {
127
127
  name: 'view',
128
128
  });
129
129
  await telemetry.send();
130
- init(cmdObj.port);
130
+ startServer(cmdObj.port);
131
131
  });
132
132
 
133
133
  program
@@ -424,7 +424,7 @@ async function main() {
424
424
  logger.info('Done.');
425
425
 
426
426
  if (cmdObj.view) {
427
- init(parseInt(cmdObj.view, 10) || 15500);
427
+ startServer(parseInt(cmdObj.view, 10) || 15500);
428
428
  }
429
429
  });
430
430
 
@@ -19,6 +19,8 @@ interface OpenAiCompletionOptions {
19
19
  parameters: any;
20
20
  }[];
21
21
  function_call?: 'none' | 'auto';
22
+ apiKey?: string;
23
+ organization?: string;
22
24
  }
23
25
 
24
26
  class OpenAiGenericProvider implements ApiProvider {
@@ -29,7 +31,7 @@ class OpenAiGenericProvider implements ApiProvider {
29
31
  constructor(modelName: string, apiKey?: string) {
30
32
  this.modelName = modelName;
31
33
 
32
- this.apiKey = apiKey || process.env.OPENAI_API_KEY;
34
+ this.apiKey = apiKey;
33
35
 
34
36
  this.apiHost = process.env.OPENAI_API_HOST || DEFAULT_OPENAI_HOST;
35
37
  }
@@ -42,6 +44,14 @@ class OpenAiGenericProvider implements ApiProvider {
42
44
  return `[OpenAI Provider ${this.modelName}]`;
43
45
  }
44
46
 
47
+ getOrganization(options?: OpenAiCompletionOptions): string | undefined {
48
+ return options?.organization || process.env.OPENAI_ORGANIZATION;
49
+ }
50
+
51
+ getApiKey(options?: OpenAiCompletionOptions): string | undefined {
52
+ return options?.apiKey || this.apiKey || process.env.OPENAI_API_KEY;
53
+ }
54
+
45
55
  // @ts-ignore: Prompt is not used in this implementation
46
56
  async callApi(prompt: string, options?: OpenAiCompletionOptions): Promise<ProviderResponse> {
47
57
  throw new Error('Not implemented');
@@ -50,7 +60,7 @@ class OpenAiGenericProvider implements ApiProvider {
50
60
 
51
61
  export class OpenAiEmbeddingProvider extends OpenAiGenericProvider {
52
62
  async callEmbeddingApi(text: string): Promise<ProviderEmbeddingResponse> {
53
- if (!this.apiKey) {
63
+ if (!this.getApiKey()) {
54
64
  throw new Error('OpenAI API key must be set for similarity comparison');
55
65
  }
56
66
 
@@ -67,7 +77,10 @@ export class OpenAiEmbeddingProvider extends OpenAiGenericProvider {
67
77
  method: 'POST',
68
78
  headers: {
69
79
  'Content-Type': 'application/json',
70
- Authorization: `Bearer ${this.apiKey}`,
80
+ Authorization: `Bearer ${this.getApiKey()}`,
81
+ ...(this.getOrganization()
82
+ ? { 'OpenAI-Organization': this.getOrganization() }
83
+ : {}),
71
84
  },
72
85
  body: JSON.stringify(body),
73
86
  },
@@ -135,7 +148,7 @@ export class OpenAiCompletionProvider extends OpenAiGenericProvider {
135
148
  }
136
149
 
137
150
  async callApi(prompt: string, options?: OpenAiCompletionOptions): Promise<ProviderResponse> {
138
- if (!this.apiKey) {
151
+ if (!this.getApiKey(options)) {
139
152
  throw new Error(
140
153
  'OpenAI API key is not set. Set OPENAI_API_KEY environment variable or pass it as an argument to the constructor.',
141
154
  );
@@ -183,7 +196,10 @@ export class OpenAiCompletionProvider extends OpenAiGenericProvider {
183
196
  method: 'POST',
184
197
  headers: {
185
198
  'Content-Type': 'application/json',
186
- Authorization: `Bearer ${this.apiKey}`,
199
+ Authorization: `Bearer ${this.getApiKey(options)}`,
200
+ ...(this.getOrganization(options)
201
+ ? { 'OpenAI-Organization': this.getOrganization(options) }
202
+ : {}),
187
203
  },
188
204
  body: JSON.stringify(body),
189
205
  },
@@ -240,7 +256,7 @@ export class OpenAiChatCompletionProvider extends OpenAiGenericProvider {
240
256
  }
241
257
 
242
258
  async callApi(prompt: string, options?: OpenAiCompletionOptions): Promise<ProviderResponse> {
243
- if (!this.apiKey) {
259
+ if (!this.getApiKey(options)) {
244
260
  throw new Error(
245
261
  'OpenAI API key is not set. Set OPENAI_API_KEY environment variable or pass it as an argument to the constructor.',
246
262
  );
@@ -281,7 +297,10 @@ export class OpenAiChatCompletionProvider extends OpenAiGenericProvider {
281
297
  method: 'POST',
282
298
  headers: {
283
299
  'Content-Type': 'application/json',
284
- Authorization: `Bearer ${this.apiKey}`,
300
+ Authorization: `Bearer ${this.getApiKey(options)}`,
301
+ ...(this.getOrganization(options)
302
+ ? { 'OpenAI-Organization': this.getOrganization(options) }
303
+ : {}),
285
304
  },
286
305
  body: JSON.stringify(body),
287
306
  },
package/src/providers.ts CHANGED
@@ -21,7 +21,12 @@ import type {
21
21
  } from './types';
22
22
 
23
23
  export async function loadApiProviders(
24
- providerPaths: ProviderId | ProviderId[] | RawProviderConfig[] | ProviderFunction,
24
+ providerPaths:
25
+ | ProviderId
26
+ | ProviderId[]
27
+ | RawProviderConfig[]
28
+ | ProviderConfig[]
29
+ | ProviderFunction,
25
30
  basePath?: string,
26
31
  ): Promise<ApiProvider[]> {
27
32
  if (typeof providerPaths === 'string') {
@@ -43,9 +48,13 @@ export async function loadApiProviders(
43
48
  id: () => `custom-function-${idx}`,
44
49
  callApi: provider,
45
50
  };
51
+ } else if (provider.id) {
52
+ // List of ProviderConfig objects
53
+ return loadApiProvider((provider as ProviderConfig).id!, provider, basePath);
46
54
  } else {
55
+ // List of { id: string, config: ProviderConfig } objects
47
56
  const id = Object.keys(provider)[0];
48
- const providerObject = provider[id];
57
+ const providerObject = (provider as RawProviderConfig)[id];
49
58
  const context = { ...providerObject, id: providerObject.id || id };
50
59
  return loadApiProvider(id, context, basePath);
51
60
  }
package/src/share.ts CHANGED
@@ -1,23 +1,25 @@
1
1
  import fetch from 'node-fetch';
2
2
 
3
- import type { EvaluateSummary, UnifiedConfig } from './types';
3
+ import type { EvaluateSummary, SharedResults, UnifiedConfig } from './types';
4
4
 
5
5
  export async function createShareableUrl(
6
6
  results: EvaluateSummary,
7
7
  config: Partial<UnifiedConfig>,
8
8
  ): Promise<string> {
9
+ const sharedResults: SharedResults = {
10
+ data: {
11
+ version: 1,
12
+ results,
13
+ config,
14
+ },
15
+ };
16
+
9
17
  const response = await fetch('https://api.promptfoo.dev/eval', {
10
18
  method: 'POST',
11
19
  headers: {
12
20
  'Content-Type': 'application/json',
13
21
  },
14
- body: JSON.stringify({
15
- data: {
16
- version: 1,
17
- results,
18
- config,
19
- },
20
- }),
22
+ body: JSON.stringify(sharedResults),
21
23
  });
22
24
 
23
25
  const { id } = (await response.json()) as { id: string };
package/src/types.ts CHANGED
@@ -80,6 +80,7 @@ export interface OutputConfig {
80
80
  export interface EvaluateOptions {
81
81
  maxConcurrency?: number;
82
82
  showProgressBar?: boolean;
83
+ progressCallback?: (progress: number, total: number) => void;
83
84
  generateSuggestions?: boolean;
84
85
  repeat?: number;
85
86
  }
@@ -256,7 +257,7 @@ export interface TestSuiteConfig {
256
257
  description?: string;
257
258
 
258
259
  // One or more LLM APIs to use, for example: openai:gpt-3.5-turbo, openai:gpt-4, localai:chat:vicuna
259
- providers: ProviderId | ProviderId[] | RawProviderConfig[] | ProviderFunction;
260
+ providers: ProviderId | ProviderId[] | RawProviderConfig[] | ProviderConfig[] | ProviderFunction;
260
261
 
261
262
  // One or more prompt files to load
262
263
  prompts: string | string[];
@@ -281,3 +282,11 @@ export type UnifiedConfig = TestSuiteConfig & {
281
282
  evaluateOptions: EvaluateOptions;
282
283
  commandLineOptions: Partial<CommandLineOptions>;
283
284
  };
285
+
286
+ export interface SharedResults {
287
+ data: {
288
+ version: number;
289
+ results: EvaluateSummary;
290
+ config: Partial<UnifiedConfig>;
291
+ };
292
+ }
@@ -0,0 +1,3 @@
1
+ {
2
+ "extends": "next/core-web-vitals"
3
+ }
@@ -0,0 +1,14 @@
1
+ /** @type {import('next').NextConfig} */
2
+ const nextConfig = {
3
+ output: process.env.USING_VERCEL ? 'standalone' : 'export',
4
+ trailingSlash: true,
5
+ webpack: (config, { buildId, dev, isServer, defaultLoaders, webpack }) => {
6
+ config.externals.push({
7
+ 'utf-8-validate': 'commonjs utf-8-validate',
8
+ bufferutil: 'commonjs bufferutil',
9
+ });
10
+ return config;
11
+ },
12
+ };
13
+
14
+ module.exports = nextConfig;