promptfoo 0.20.0 → 0.21.0

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 (184) hide show
  1. package/README.md +1 -1
  2. package/dist/package.json +4 -4
  3. package/dist/src/assertions.d.ts.map +1 -1
  4. package/dist/src/assertions.js +5 -0
  5. package/dist/src/assertions.js.map +1 -1
  6. package/dist/src/evaluator.js +1 -1
  7. package/dist/src/evaluator.js.map +1 -1
  8. package/dist/src/index.d.ts +1 -5
  9. package/dist/src/index.d.ts.map +1 -1
  10. package/dist/src/index.js +1 -1
  11. package/dist/src/index.js.map +1 -1
  12. package/dist/src/matchers.d.ts +3 -2
  13. package/dist/src/matchers.d.ts.map +1 -1
  14. package/dist/src/matchers.js +37 -9
  15. package/dist/src/matchers.js.map +1 -1
  16. package/dist/src/providers/anthropic.d.ts +5 -3
  17. package/dist/src/providers/anthropic.d.ts.map +1 -1
  18. package/dist/src/providers/anthropic.js +8 -10
  19. package/dist/src/providers/anthropic.js.map +1 -1
  20. package/dist/src/providers/azureopenai.d.ts +9 -8
  21. package/dist/src/providers/azureopenai.d.ts.map +1 -1
  22. package/dist/src/providers/azureopenai.js +33 -36
  23. package/dist/src/providers/azureopenai.js.map +1 -1
  24. package/dist/src/providers/openai.d.ts +12 -12
  25. package/dist/src/providers/openai.d.ts.map +1 -1
  26. package/dist/src/providers/openai.js +54 -65
  27. package/dist/src/providers/openai.js.map +1 -1
  28. package/dist/src/providers/replicate.d.ts +4 -2
  29. package/dist/src/providers/replicate.d.ts.map +1 -1
  30. package/dist/src/providers/replicate.js +10 -8
  31. package/dist/src/providers/replicate.js.map +1 -1
  32. package/dist/src/providers/webhook.d.ts +9 -0
  33. package/dist/src/providers/webhook.d.ts.map +1 -0
  34. package/dist/src/providers/webhook.js +54 -0
  35. package/dist/src/providers/webhook.js.map +1 -0
  36. package/dist/src/providers.d.ts +1 -1
  37. package/dist/src/providers.d.ts.map +1 -1
  38. package/dist/src/providers.js +36 -28
  39. package/dist/src/providers.js.map +1 -1
  40. package/dist/src/suggestions.d.ts.map +1 -1
  41. package/dist/src/suggestions.js +1 -3
  42. package/dist/src/suggestions.js.map +1 -1
  43. package/dist/src/types.d.ts +7 -1
  44. package/dist/src/types.d.ts.map +1 -1
  45. package/dist/src/util.js +1 -1
  46. package/dist/src/util.js.map +1 -1
  47. package/dist/src/web/nextui/404/index.html +1 -1
  48. package/dist/src/web/nextui/404.html +1 -1
  49. package/dist/src/web/nextui/_next/static/Bl3o5lF4ON7Fjki46lPhr/_buildManifest.js +1 -0
  50. package/dist/src/web/nextui/_next/static/chunks/226-7bbb6c98a19542fd.js +37 -0
  51. package/dist/src/web/nextui/_next/static/chunks/249-ea9c0f034888ccff.js +125 -0
  52. package/dist/src/web/nextui/_next/static/chunks/339-501c32916b785ef1.js +1 -0
  53. package/dist/src/web/nextui/_next/static/chunks/365-e426ea5bc7e815fc.js +8 -0
  54. package/dist/src/web/nextui/_next/static/chunks/396-0a51429a01e24cdd.js +1 -0
  55. package/dist/src/web/nextui/_next/static/chunks/596-297f7ff4a0436e87.js +25 -0
  56. package/dist/src/web/nextui/_next/static/chunks/613-572c22424de64659.js +1 -0
  57. package/dist/src/web/nextui/_next/static/chunks/706-ae1d3352d28419e9.js +9 -0
  58. package/dist/src/web/nextui/_next/static/chunks/891-7035926a62c1c4e0.js +1 -0
  59. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/not-found-366629541fd598e9.js +1 -0
  60. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/page-319d2ee38d37574e.js +1 -0
  61. package/dist/src/web/nextui/_next/static/chunks/app/eval/page-a6b1ff91723b7beb.js +1 -0
  62. package/dist/src/web/nextui/_next/static/chunks/app/layout-024c4adc71c9feb0.js +1 -0
  63. package/dist/src/web/nextui/_next/static/chunks/app/page-1ae60660130041b2.js +1 -0
  64. package/dist/src/web/nextui/_next/static/chunks/app/setup/page-6ef16148040bf4f4.js +1 -0
  65. package/dist/src/web/nextui/_next/static/chunks/{ca377847-cb6ae6a6a073aebb.js → ca377847-26b462611379a4f7.js} +3 -3
  66. package/dist/src/web/nextui/_next/static/chunks/{fd9d1056-ac777be631f5a9e9.js → fd9d1056-fba4b53a2f01213b.js} +1 -1
  67. package/dist/src/web/nextui/_next/static/chunks/framework-8883d1e9be70c3da.js +25 -0
  68. package/dist/src/web/nextui/_next/static/chunks/main-8ea85465d428ecfe.js +1 -0
  69. package/dist/src/web/nextui/_next/static/chunks/main-app-581ccf0003955b21.js +1 -0
  70. package/dist/src/web/nextui/_next/static/chunks/pages/_app-52924524f99094ab.js +1 -0
  71. package/dist/src/web/nextui/_next/static/chunks/pages/_error-c92d5c4bb2b49926.js +1 -0
  72. package/dist/src/web/nextui/_next/static/chunks/webpack-55c264ce2fd85eb7.js +1 -0
  73. package/dist/src/web/nextui/_next/static/css/4d399fceacd06992.css +1 -0
  74. package/dist/src/web/nextui/eval/index.html +1 -1
  75. package/dist/src/web/nextui/eval/index.txt +6 -6
  76. package/dist/src/web/nextui/index.html +1 -1
  77. package/dist/src/web/nextui/index.txt +5 -5
  78. package/dist/src/web/nextui/setup/index.html +27 -1
  79. package/dist/src/web/nextui/setup/index.txt +9 -9
  80. package/dist/src/web/server.d.ts.map +1 -1
  81. package/dist/src/web/server.js +9 -5
  82. package/dist/src/web/server.js.map +1 -1
  83. package/package.json +4 -4
  84. package/dist/src/web/nextui/_next/static/US6gOx8LHTX_Hzm9aYNrC/_buildManifest.js +0 -1
  85. package/dist/src/web/nextui/_next/static/chunks/339-4fc8a80fa840e771.js +0 -1
  86. package/dist/src/web/nextui/_next/static/chunks/373-8a280796c0f2d1af.js +0 -1
  87. package/dist/src/web/nextui/_next/static/chunks/583-125d32af505e9bc4.js +0 -1
  88. package/dist/src/web/nextui/_next/static/chunks/596-07e4a23a5c6cdf04.js +0 -25
  89. package/dist/src/web/nextui/_next/static/chunks/658-a62210d07dc4dcb6.js +0 -15
  90. package/dist/src/web/nextui/_next/static/chunks/707-699cbd84b259c37b.js +0 -37
  91. package/dist/src/web/nextui/_next/static/chunks/858-ceb6fa22e614492b.js +0 -125
  92. package/dist/src/web/nextui/_next/static/chunks/891-3000ea7c0a292558.js +0 -1
  93. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/not-found-50e40614fa05600e.js +0 -1
  94. package/dist/src/web/nextui/_next/static/chunks/app/eval/[id]/page-c19c44ed1b2dfb58.js +0 -1
  95. package/dist/src/web/nextui/_next/static/chunks/app/eval/page-d4a1813b2f8c4532.js +0 -1
  96. package/dist/src/web/nextui/_next/static/chunks/app/layout-664a8d716d2d24b1.js +0 -1
  97. package/dist/src/web/nextui/_next/static/chunks/app/page-1f8ef6a00a2355f0.js +0 -1
  98. package/dist/src/web/nextui/_next/static/chunks/app/setup/page-182018a3c6397345.js +0 -1
  99. package/dist/src/web/nextui/_next/static/chunks/framework-43665103d101a22d.js +0 -25
  100. package/dist/src/web/nextui/_next/static/chunks/main-50cc0a98559591ce.js +0 -1
  101. package/dist/src/web/nextui/_next/static/chunks/main-app-c9dc13756d166550.js +0 -1
  102. package/dist/src/web/nextui/_next/static/chunks/pages/_app-6b79a29ad0d63b21.js +0 -1
  103. package/dist/src/web/nextui/_next/static/chunks/pages/_error-9aeb3e4d490fe4b8.js +0 -1
  104. package/dist/src/web/nextui/_next/static/chunks/webpack-6e474e42be502dd7.js +0 -1
  105. package/dist/src/web/nextui/_next/static/css/a35c840ac696f161.css +0 -1
  106. package/dist/src/web/nextui/api +0 -1
  107. package/src/__mocks__/esm.ts +0 -3
  108. package/src/assertions.ts +0 -580
  109. package/src/cache.ts +0 -109
  110. package/src/esm.ts +0 -13
  111. package/src/evaluator.ts +0 -500
  112. package/src/index.ts +0 -52
  113. package/src/logger.ts +0 -46
  114. package/src/main.ts +0 -442
  115. package/src/matchers.ts +0 -120
  116. package/src/onboarding.ts +0 -69
  117. package/src/prompts.ts +0 -39
  118. package/src/providers/anthropic.ts +0 -88
  119. package/src/providers/azureopenai.ts +0 -299
  120. package/src/providers/llama.ts +0 -95
  121. package/src/providers/localai.ts +0 -111
  122. package/src/providers/ollama.ts +0 -89
  123. package/src/providers/openai.ts +0 -337
  124. package/src/providers/replicate.ts +0 -99
  125. package/src/providers/scriptCompletion.ts +0 -35
  126. package/src/providers/shared.ts +0 -34
  127. package/src/providers.ts +0 -192
  128. package/src/share.ts +0 -27
  129. package/src/suggestions.ts +0 -63
  130. package/src/table.ts +0 -43
  131. package/src/tableOutput.html +0 -52
  132. package/src/telemetry.ts +0 -70
  133. package/src/types.ts +0 -299
  134. package/src/updates.ts +0 -46
  135. package/src/util.ts +0 -543
  136. package/src/web/nextui/.eslintrc.json +0 -3
  137. package/src/web/nextui/next.config.js +0 -14
  138. package/src/web/nextui/package-lock.json +0 -4644
  139. package/src/web/nextui/package.json +0 -47
  140. package/src/web/nextui/public/favicon.ico +0 -0
  141. package/src/web/nextui/public/logo.svg +0 -30
  142. package/src/web/nextui/src/app/Home.css +0 -3
  143. package/src/web/nextui/src/app/api/route.ts +0 -6
  144. package/src/web/nextui/src/app/components/DarkMode.css +0 -22
  145. package/src/web/nextui/src/app/components/DarkMode.tsx +0 -17
  146. package/src/web/nextui/src/app/components/Logo.css +0 -32
  147. package/src/web/nextui/src/app/components/Logo.tsx +0 -11
  148. package/src/web/nextui/src/app/components/PageShell.css +0 -33
  149. package/src/web/nextui/src/app/components/PageShell.tsx +0 -87
  150. package/src/web/nextui/src/app/eval/ConfigModal.tsx +0 -84
  151. package/src/web/nextui/src/app/eval/Eval.css +0 -13
  152. package/src/web/nextui/src/app/eval/Eval.tsx +0 -79
  153. package/src/web/nextui/src/app/eval/EvalOutputPromptDialog.tsx +0 -127
  154. package/src/web/nextui/src/app/eval/ResultsCharts.tsx +0 -355
  155. package/src/web/nextui/src/app/eval/ResultsTable.css +0 -179
  156. package/src/web/nextui/src/app/eval/ResultsTable.tsx +0 -503
  157. package/src/web/nextui/src/app/eval/ResultsView.tsx +0 -301
  158. package/src/web/nextui/src/app/eval/ShareModal.tsx +0 -70
  159. package/src/web/nextui/src/app/eval/[id]/not-found.tsx +0 -5
  160. package/src/web/nextui/src/app/eval/[id]/page.css +0 -9
  161. package/src/web/nextui/src/app/eval/[id]/page.tsx +0 -20
  162. package/src/web/nextui/src/app/eval/index.css +0 -0
  163. package/src/web/nextui/src/app/eval/page.tsx +0 -8
  164. package/src/web/nextui/src/app/eval/store.ts +0 -18
  165. package/src/web/nextui/src/app/eval/types.ts +0 -20
  166. package/src/web/nextui/src/app/globals.css +0 -58
  167. package/src/web/nextui/src/app/layout.tsx +0 -25
  168. package/src/web/nextui/src/app/page.tsx +0 -7
  169. package/src/web/nextui/src/app/setup/AssertsForm.tsx +0 -118
  170. package/src/web/nextui/src/app/setup/PromptDialog.tsx +0 -77
  171. package/src/web/nextui/src/app/setup/PromptsSection.tsx +0 -190
  172. package/src/web/nextui/src/app/setup/ProviderConfigDialog.tsx +0 -99
  173. package/src/web/nextui/src/app/setup/ProviderSelector.tsx +0 -149
  174. package/src/web/nextui/src/app/setup/RunTestSuiteButton.tsx +0 -88
  175. package/src/web/nextui/src/app/setup/TestCaseDialog.tsx +0 -108
  176. package/src/web/nextui/src/app/setup/TestCasesSection.tsx +0 -154
  177. package/src/web/nextui/src/app/setup/VarsForm.tsx +0 -57
  178. package/src/web/nextui/src/app/setup/page.css +0 -3
  179. package/src/web/nextui/src/app/setup/page.tsx +0 -160
  180. package/src/web/nextui/src/util/api.ts +0 -1
  181. package/src/web/nextui/src/util/store.ts +0 -53
  182. package/src/web/nextui/tsconfig.json +0 -28
  183. package/src/web/server.ts +0 -151
  184. /package/dist/src/web/nextui/_next/static/{US6gOx8LHTX_Hzm9aYNrC → Bl3o5lF4ON7Fjki46lPhr}/_ssgManifest.js +0 -0
@@ -1,108 +0,0 @@
1
- import React, { useState } from 'react';
2
- import {
3
- Button,
4
- TextField,
5
- Box,
6
- Dialog,
7
- DialogTitle,
8
- DialogContent,
9
- DialogActions,
10
- } from '@mui/material';
11
- import VarsForm from './VarsForm';
12
- import AssertsForm from './AssertsForm';
13
- import type { TestCase } from '../../../../../types';
14
-
15
- interface TestCaseFormProps {
16
- open: boolean;
17
- onAdd: (testCase: TestCase, shouldClose: boolean) => void;
18
- varsList: string[];
19
- initialValues?: TestCase;
20
- onCancel: () => void;
21
- }
22
-
23
- const TestCaseForm: React.FC<TestCaseFormProps> = ({
24
- open,
25
- onAdd,
26
- varsList,
27
- initialValues,
28
- onCancel,
29
- }) => {
30
- const [description, setDescription] = useState(initialValues?.description || '');
31
- const [vars, setVars] = useState(initialValues?.vars || {});
32
- const [asserts, setAsserts] = useState(initialValues?.assert || []);
33
- const [assertsFormKey, setAssertsFormKey] = useState(0);
34
-
35
- React.useEffect(() => {
36
- if (initialValues) {
37
- setDescription(initialValues.description || '');
38
- setVars(initialValues.vars || {});
39
- setAsserts(initialValues.assert || []);
40
- } else {
41
- setDescription('');
42
- setVars({});
43
- setAsserts([]);
44
- }
45
- }, [initialValues]);
46
-
47
- const handleAdd = (close: boolean) => {
48
- onAdd(
49
- {
50
- description,
51
- vars,
52
- assert: asserts,
53
- },
54
- close,
55
- );
56
- if (close) {
57
- onCancel();
58
- }
59
- setDescription('');
60
- setVars({});
61
- setAsserts([]);
62
- setAssertsFormKey((prevKey) => prevKey + 1);
63
- };
64
-
65
- return (
66
- <Dialog open={open} onClose={onCancel} fullWidth maxWidth="md">
67
- <DialogTitle>{initialValues ? 'Edit Test Case' : 'Add Test Case'}</DialogTitle>
68
- <DialogContent>
69
- <Box>
70
- {/*
71
- <TextField
72
- label="Description"
73
- value={description}
74
- onChange={(e) => setDescription(e.target.value)}
75
- fullWidth
76
- margin="normal"
77
- />
78
- */}
79
- <VarsForm
80
- onAdd={(vars) => setVars(vars)}
81
- varsList={varsList}
82
- initialValues={initialValues?.vars as Record<string, string>}
83
- />
84
- <AssertsForm
85
- key={assertsFormKey}
86
- onAdd={(asserts) => setAsserts(asserts)}
87
- initialValues={initialValues?.assert || []}
88
- />
89
- </Box>
90
- </DialogContent>
91
- <DialogActions>
92
- <Button onClick={handleAdd.bind(this, true)} color="primary" variant="contained">
93
- {initialValues ? 'Update Test Case' : 'Add Test Case'}
94
- </Button>
95
- {!initialValues && (
96
- <Button onClick={handleAdd.bind(this, false)} color="primary" variant="contained">
97
- Add Another
98
- </Button>
99
- )}
100
- <Button onClick={onCancel} color="secondary">
101
- Cancel
102
- </Button>
103
- </DialogActions>
104
- </Dialog>
105
- );
106
- };
107
-
108
- export default TestCaseForm;
@@ -1,154 +0,0 @@
1
- import React from 'react';
2
- import Button from '@mui/material/Button';
3
- import Copy from '@mui/icons-material/ContentCopy';
4
- import Delete from '@mui/icons-material/Delete';
5
- import Edit from '@mui/icons-material/Edit';
6
- import IconButton from '@mui/material/IconButton';
7
- import Stack from '@mui/material/Stack';
8
- import Table from '@mui/material/Table';
9
- import TableBody from '@mui/material/TableBody';
10
- import TableCell from '@mui/material/TableCell';
11
- import TableContainer from '@mui/material/TableContainer';
12
- import TableHead from '@mui/material/TableHead';
13
- import TableRow from '@mui/material/TableRow';
14
- import Typography from '@mui/material/Typography';
15
-
16
- import TestCaseDialog from './TestCaseDialog';
17
- import { useStore } from '../../util/store';
18
-
19
- import type { TestCase } from '../../../../../types';
20
-
21
- interface TestCasesSectionProps {
22
- varsList: string[];
23
- }
24
-
25
- const TestCasesSection: React.FC<TestCasesSectionProps> = ({ varsList }) => {
26
- const { testCases, setTestCases } = useStore();
27
- const [editingTestCaseIndex, setEditingTestCaseIndex] = React.useState<number | null>(null);
28
- const [testCaseDialogOpen, setTestCaseDialogOpen] = React.useState(false);
29
-
30
- const handleAddTestCase = (testCase: TestCase, shouldClose: boolean) => {
31
- if (editingTestCaseIndex === null) {
32
- setTestCases([...testCases, testCase]);
33
- } else {
34
- const updatedTestCases = testCases.map((tc, index) =>
35
- index === editingTestCaseIndex ? testCase : tc,
36
- );
37
- setTestCases(updatedTestCases);
38
- setEditingTestCaseIndex(null);
39
- }
40
-
41
- if (shouldClose) {
42
- setTestCaseDialogOpen(false);
43
- }
44
- };
45
-
46
- const handleRemoveTestCase = (event: React.MouseEvent, index: number) => {
47
- event.stopPropagation();
48
-
49
- if (confirm('Are you sure you want to delete this test case?')) {
50
- setTestCases(testCases.filter((_, i) => i !== index));
51
- }
52
- };
53
-
54
- const handleDuplicateTestCase = (event: React.MouseEvent, index: number) => {
55
- event.stopPropagation();
56
- const duplicatedTestCase = JSON.parse(JSON.stringify(testCases[index]));
57
- setTestCases([...testCases, duplicatedTestCase]);
58
- };
59
-
60
- return (
61
- <>
62
- <Stack direction="row" spacing={2} justifyContent="space-between">
63
- <Typography variant="h5">Test Cases</Typography>
64
- <Button color="primary" onClick={() => setTestCaseDialogOpen(true)} variant="contained">
65
- Add Test Case
66
- </Button>
67
- </Stack>
68
- <TableContainer>
69
- <Table>
70
- <TableHead>
71
- <TableRow>
72
- <TableCell>Description</TableCell>
73
- <TableCell>Assertions</TableCell>
74
- <TableCell>Variables</TableCell>
75
- <TableCell align="right"></TableCell>
76
- </TableRow>
77
- </TableHead>
78
- <TableBody>
79
- {testCases.length === 0 ? (
80
- <TableRow>
81
- <TableCell colSpan={4} align="center">
82
- No test cases added yet.
83
- </TableCell>
84
- </TableRow>
85
- ) : (
86
- testCases.map((testCase, index) => (
87
- <TableRow
88
- key={index}
89
- sx={{
90
- '&:hover': {
91
- backgroundColor: 'rgba(0, 0, 0, 0.04)',
92
- cursor: 'pointer',
93
- },
94
- }}
95
- onClick={() => {
96
- setEditingTestCaseIndex(index);
97
- setTestCaseDialogOpen(true);
98
- }}
99
- >
100
- <TableCell>
101
- <Typography variant="body2">
102
- {testCase.description || `Test Case #${index + 1}`}
103
- </Typography>
104
- </TableCell>
105
- <TableCell>{testCase.assert?.length || 0} assertions</TableCell>
106
- <TableCell>
107
- {Object.entries(testCase.vars || {})
108
- .map(([k, v]) => k + '=' + v)
109
- .join(', ')}
110
- </TableCell>
111
- <TableCell align="right" sx={{ minWidth: 150 }}>
112
- <IconButton
113
- onClick={() => {
114
- setEditingTestCaseIndex(index);
115
- setTestCaseDialogOpen(true);
116
- }}
117
- size="small"
118
- >
119
- <Edit />
120
- </IconButton>
121
- <IconButton
122
- onClick={(event) => handleDuplicateTestCase(event, index)}
123
- size="small"
124
- >
125
- <Copy />
126
- </IconButton>
127
- <IconButton
128
- onClick={(event) => handleRemoveTestCase(event, index)}
129
- size="small"
130
- >
131
- <Delete />
132
- </IconButton>
133
- </TableCell>
134
- </TableRow>
135
- ))
136
- )}
137
- </TableBody>
138
- </Table>
139
- </TableContainer>
140
- <TestCaseDialog
141
- open={testCaseDialogOpen}
142
- onAdd={handleAddTestCase}
143
- varsList={varsList}
144
- initialValues={editingTestCaseIndex !== null ? testCases[editingTestCaseIndex] : undefined}
145
- onCancel={() => {
146
- setEditingTestCaseIndex(null);
147
- setTestCaseDialogOpen(false);
148
- }}
149
- />
150
- </>
151
- );
152
- };
153
-
154
- export default TestCasesSection;
@@ -1,57 +0,0 @@
1
- import React, { useEffect } from 'react';
2
- import { Box, TextField, Typography, Stack } from '@mui/material';
3
-
4
- interface VarsFormProps {
5
- onAdd: (vars: Record<string, string>) => void;
6
- varsList: string[];
7
- initialValues?: Record<string, string>;
8
- }
9
-
10
- const VarsForm: React.FC<VarsFormProps> = ({ onAdd, varsList, initialValues }) => {
11
- const [vars, setVars] = React.useState<Record<string, string>>(initialValues || {});
12
-
13
- useEffect(() => {
14
- const newVars: Record<string, string> = {};
15
- varsList.forEach((v) => {
16
- newVars[v] = initialValues?.[v] || '';
17
- });
18
- setVars(newVars);
19
- }, [varsList, initialValues]);
20
-
21
- return (
22
- <Box my={2}>
23
- <Typography variant="h6" mb={2}>
24
- Vars
25
- </Typography>
26
- {varsList.length > 0 ? (
27
- <Stack direction="row" spacing={2} alignItems="center">
28
- {Object.keys(vars).map((varName, index) => (
29
- <Stack key={index} direction="row" spacing={2} alignItems="center">
30
- <TextField
31
- placeholder={varName}
32
- label={varName}
33
- value={vars[varName]}
34
- fullWidth
35
- onChange={(e) => {
36
- const newValue = e.target.value;
37
- const newVars = {
38
- ...vars,
39
- [varName]: newValue,
40
- };
41
- setVars(newVars);
42
- onAdd(newVars);
43
- }}
44
- />
45
- </Stack>
46
- ))}
47
- </Stack>
48
- ) : (
49
- <Typography variant="subtitle1" gutterBottom>
50
- Add variables to your prompt using the {'{{varname}}'} syntax.
51
- </Typography>
52
- )}
53
- </Box>
54
- );
55
- };
56
-
57
- export default VarsForm;
@@ -1,3 +0,0 @@
1
- .yaml-config {
2
- font-size: 10px;
3
- }
@@ -1,160 +0,0 @@
1
- 'use client';
2
-
3
- import React, { useState, useEffect } from 'react';
4
- import Link from 'next/link';
5
- import yaml from 'js-yaml';
6
- import { Light as SyntaxHighlighter } from 'react-syntax-highlighter';
7
- import { docco } from 'react-syntax-highlighter/dist/cjs/styles/hljs';
8
- import Button from '@mui/material/Button';
9
- import Container from '@mui/material/Container';
10
- import Typography from '@mui/material/Typography';
11
- import Box from '@mui/material/Box';
12
- import Stack from '@mui/material/Stack';
13
- import Dialog from '@mui/material/Dialog';
14
- import DialogActions from '@mui/material/DialogActions';
15
- import DialogContent from '@mui/material/DialogContent';
16
- import DialogContentText from '@mui/material/DialogContentText';
17
- import DialogTitle from '@mui/material/DialogTitle';
18
-
19
- import RunTestSuiteButton from './RunTestSuiteButton';
20
- import PromptsSection from './PromptsSection';
21
- import TestCasesSection from './TestCasesSection';
22
- import ProviderSelector from './ProviderSelector';
23
- import { useStore } from '../../util/store';
24
-
25
- import './page.css';
26
-
27
- const EvaluateTestSuiteCreator: React.FC = () => {
28
- const [yamlString, setYamlString] = useState('');
29
- const [resetDialogOpen, setResetDialogOpen] = useState(false);
30
-
31
- const {
32
- description,
33
- setDescription,
34
- providers,
35
- setProviders,
36
- prompts,
37
- setPrompts,
38
- testCases,
39
- setTestCases,
40
- } = useStore();
41
-
42
- useEffect(() => {
43
- useStore.persist.rehydrate();
44
- }, []);
45
-
46
- useEffect(() => {
47
- const testSuite = {
48
- description,
49
- providers,
50
- prompts,
51
- tests: testCases,
52
- };
53
- setYamlString(yaml.dump(testSuite));
54
- }, [description, providers, prompts, testCases]);
55
-
56
- if (process.env.NEXT_PUBLIC_NO_BROWSING) {
57
- return null;
58
- }
59
-
60
- const extractVarsFromPrompts = (prompts: string[]): string[] => {
61
- const varRegex = /{{(\w+)}}/g;
62
- const varsSet = new Set<string>();
63
-
64
- prompts.forEach((prompt) => {
65
- let match;
66
- while ((match = varRegex.exec(prompt)) !== null) {
67
- varsSet.add(match[1]);
68
- }
69
- });
70
-
71
- return Array.from(varsSet);
72
- };
73
-
74
- const varsList = extractVarsFromPrompts(prompts);
75
-
76
- const handleReset = () => {
77
- setDescription('');
78
- setProviders([]);
79
- setPrompts([]);
80
- setTestCases([]);
81
- setYamlString('');
82
- setResetDialogOpen(false);
83
- };
84
-
85
- return (
86
- <Container maxWidth="lg" sx={{ marginTop: '2rem' }}>
87
- <Stack direction="row" spacing={2} justifyContent="space-between">
88
- <Typography variant="h4">Set up an evaluation</Typography>
89
- <Stack direction="row" spacing={2}>
90
- <RunTestSuiteButton />
91
- <Button variant="outlined" color="primary" onClick={() => setResetDialogOpen(true)}>
92
- Reset
93
- </Button>
94
- </Stack>
95
- </Stack>
96
- <Box mt={4} />
97
- {/*
98
- <Box mt={4}>
99
- <TextField
100
- label="Description"
101
- value={description}
102
- onChange={(e) => {
103
- setDescription(e.target.value);
104
- }}
105
- fullWidth
106
- margin="normal"
107
- />
108
- </Box>
109
- */}
110
- <Box mt={2}>
111
- <Stack direction="column" spacing={2} justifyContent="space-between">
112
- <Typography variant="h5">Providers</Typography>
113
- <ProviderSelector providers={providers} onChange={setProviders} />
114
- </Stack>
115
- </Box>
116
- <Box mt={4} />
117
- <PromptsSection />
118
- <Box mt={6} />
119
- <TestCasesSection varsList={varsList} />
120
- <Box mt={8}>
121
- {yamlString && (
122
- <Box mt={4}>
123
- <Typography variant="h5" gutterBottom>
124
- YAML config
125
- </Typography>
126
- <Typography variant="body1" gutterBottom>
127
- This is the evaluation config that is run by promptfoo. See{' '}
128
- <Link href="https://promptfoo.dev/docs/configuration/guide">configuration docs</Link>{' '}
129
- to learn more.
130
- </Typography>
131
- <SyntaxHighlighter className="yaml-config" language="yaml" style={docco}>
132
- {yamlString}
133
- </SyntaxHighlighter>
134
- </Box>
135
- )}
136
- </Box>
137
- <Dialog
138
- open={resetDialogOpen}
139
- onClose={() => setResetDialogOpen(false)}
140
- aria-labelledby="alert-dialog-title"
141
- aria-describedby="alert-dialog-description"
142
- >
143
- <DialogTitle id="alert-dialog-title">{'Confirm Reset'}</DialogTitle>
144
- <DialogContent>
145
- <DialogContentText id="alert-dialog-description">
146
- Are you sure you want to reset all the fields? This action cannot be undone.
147
- </DialogContentText>
148
- </DialogContent>
149
- <DialogActions>
150
- <Button onClick={() => setResetDialogOpen(false)}>Cancel</Button>
151
- <Button onClick={handleReset} autoFocus>
152
- Reset
153
- </Button>
154
- </DialogActions>
155
- </Dialog>
156
- </Container>
157
- );
158
- };
159
-
160
- export default EvaluateTestSuiteCreator;
@@ -1 +0,0 @@
1
- export const API_BASE_URL = `http://localhost:15500`;
@@ -1,53 +0,0 @@
1
- import { create } from 'zustand';
2
- import { persist } from 'zustand/middleware';
3
-
4
- import type { Assertion, ProviderOptions, TestCase } from '../../../../types';
5
-
6
- export interface State {
7
- asserts: Assertion[];
8
- testCases: TestCase[];
9
- description: string;
10
- providers: ProviderOptions[];
11
- prompts: string[];
12
- setAsserts: (asserts: Assertion[]) => void;
13
- setTestCases: (testCases: TestCase[]) => void;
14
- setDescription: (description: string) => void;
15
- setProviders: (providers: ProviderOptions[]) => void;
16
- setPrompts: (prompts: string[]) => void;
17
- }
18
-
19
- export const useStore = create<State>()(
20
- persist(
21
- (set) => ({
22
- asserts: [],
23
- testCases: [],
24
- description: '',
25
- providers: [],
26
- prompts: [],
27
- setAsserts: (asserts) => set({ asserts }),
28
- setTestCases: (testCases) => set({ testCases }),
29
- setDescription: (description) => set({ description }),
30
- setProviders: (providers) => set({ providers }),
31
- setPrompts: (prompts) => set({ prompts }),
32
- }),
33
- {
34
- name: 'promptfoo',
35
- skipHydration: true,
36
- },
37
- ),
38
- );
39
-
40
- /*
41
- export const useStore = create<State>((set) => ({
42
- asserts: [],
43
- testCases: [],
44
- description: '',
45
- providers: [],
46
- prompts: [],
47
- setAsserts: (asserts) => set({ asserts }),
48
- setTestCases: (testCases) => set({ testCases }),
49
- setDescription: (description) => set({ description }),
50
- setProviders: (providers) => set({ providers }),
51
- setPrompts: (prompts) => set({ prompts }),
52
- }));
53
- */
@@ -1,28 +0,0 @@
1
- {
2
- "compilerOptions": {
3
- "target": "es5",
4
- "lib": ["dom", "dom.iterable", "esnext"],
5
- "allowJs": true,
6
- "skipLibCheck": true,
7
- "strict": true,
8
- "forceConsistentCasingInFileNames": true,
9
- "noEmit": true,
10
- "esModuleInterop": true,
11
- "module": "esnext",
12
- "moduleResolution": "bundler",
13
- "resolveJsonModule": true,
14
- "isolatedModules": true,
15
- "jsx": "preserve",
16
- "incremental": true,
17
- "plugins": [
18
- {
19
- "name": "next"
20
- }
21
- ],
22
- "paths": {
23
- "@/*": ["./src/*"]
24
- }
25
- },
26
- "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
27
- "exclude": ["node_modules"]
28
- }