diff --git a/web/app/components/evaluation/__tests__/index.spec.tsx b/web/app/components/evaluation/__tests__/index.spec.tsx
index 350543121f..286d4cac68 100644
--- a/web/app/components/evaluation/__tests__/index.spec.tsx
+++ b/web/app/components/evaluation/__tests__/index.spec.tsx
@@ -11,7 +11,7 @@ const mockUseDefaultEvaluationMetrics = vi.hoisted(() => vi.fn())
const mockUseEvaluationConfig = vi.hoisted(() => vi.fn())
const mockUseSaveEvaluationConfigMutation = vi.hoisted(() => vi.fn())
const mockUseStartEvaluationRunMutation = vi.hoisted(() => vi.fn())
-const mockUseEvaluationTemplateColumnsMutation = vi.hoisted(() => vi.fn())
+const mockUseEvaluationTemplateColumns = vi.hoisted(() => vi.fn())
const mockUsePublishedPipelineInfo = vi.hoisted(() => vi.fn())
const mockUseSnippetPublishedWorkflow = vi.hoisted(() => vi.fn())
@@ -56,7 +56,7 @@ vi.mock('@/service/use-evaluation', () => ({
useDefaultEvaluationMetrics: (...args: unknown[]) => mockUseDefaultEvaluationMetrics(...args),
useSaveEvaluationConfigMutation: (...args: unknown[]) => mockUseSaveEvaluationConfigMutation(...args),
useStartEvaluationRunMutation: (...args: unknown[]) => mockUseStartEvaluationRunMutation(...args),
- useEvaluationTemplateColumnsMutation: (...args: unknown[]) => mockUseEvaluationTemplateColumnsMutation(...args),
+ useEvaluationTemplateColumns: (...args: unknown[]) => mockUseEvaluationTemplateColumns(...args),
}))
vi.mock('@/service/use-pipeline', () => ({
@@ -172,9 +172,17 @@ describe('Evaluation', () => {
isPending: false,
mutate: vi.fn(),
})
- mockUseEvaluationTemplateColumnsMutation.mockReturnValue({
+ mockUseEvaluationTemplateColumns.mockReturnValue({
+ data: {
+ columns: [
+ { name: 'index', type: 'number' },
+ { name: 'query', type: 'string' },
+ { name: 'expected_output', type: 'string' },
+ ],
+ },
+ isError: false,
+ isFetching: false,
isPending: false,
- mutate: vi.fn(),
})
mockUsePublishedPipelineInfo.mockReturnValue({
data: {
@@ -332,72 +340,61 @@ describe('Evaluation', () => {
expect(screen.queryByText('evaluation.batch.noticeDescription')).not.toBeInTheDocument()
})
- it('should use published snippet input fields for snippet batch templates', () => {
- mockUseSnippetPublishedWorkflow.mockReturnValue({
+ it('should use template columns for snippet batch templates', () => {
+ const store = useEvaluationStore.getState()
+ act(() => {
+ store.ensureResource('snippets', 'snippet-fields')
+ store.setJudgeModel('snippets', 'snippet-fields', 'openai::gpt-4o-mini')
+ store.addBuiltinMetric('snippets', 'snippet-fields', 'answer-correctness', [
+ { node_id: 'node-answer', title: 'Answer Node', type: 'llm' },
+ ])
+ })
+ mockUseEvaluationTemplateColumns.mockReturnValue({
data: {
- graph: {
- nodes: [{
- id: 'start',
- data: {
- type: 'start',
- variables: [{
- variable: 'graph_only',
- type: 'text-input',
- }],
- },
- }],
- },
- input_fields: [
- {
- label: 'Snippet Topic',
- variable: 'snippet_topic',
- type: 'text-input',
- required: true,
- },
- {
- label: 'Need Summary',
- variable: 'need_summary',
- type: 'checkbox',
- required: false,
- },
+ columns: [
+ { name: 'index', type: 'number' },
+ { name: 'snippet_topic', type: 'string' },
+ { name: 'need_summary', type: 'boolean' },
],
},
- isLoading: false,
+ isError: false,
+ isFetching: false,
+ isPending: false,
})
renderWithQueryClient()
- expect(mockUseSnippetPublishedWorkflow).toHaveBeenCalledWith('snippet-fields')
+ expect(mockUseEvaluationTemplateColumns).toHaveBeenCalledWith(
+ 'snippets',
+ 'snippet-fields',
+ expect.any(Object),
+ true,
+ )
expect(screen.getByText('snippet_topic')).toBeInTheDocument()
expect(screen.getByText('need_summary')).toBeInTheDocument()
- expect(screen.queryByText('graph_only')).not.toBeInTheDocument()
})
- it('should show snippet-specific empty input fields copy', () => {
- mockUseSnippetPublishedWorkflow.mockReturnValue({
+ it('should show empty template columns copy', () => {
+ const store = useEvaluationStore.getState()
+ act(() => {
+ store.ensureResource('snippets', 'snippet-empty-fields')
+ store.setJudgeModel('snippets', 'snippet-empty-fields', 'openai::gpt-4o-mini')
+ store.addBuiltinMetric('snippets', 'snippet-empty-fields', 'answer-correctness', [
+ { node_id: 'node-answer', title: 'Answer Node', type: 'llm' },
+ ])
+ })
+ mockUseEvaluationTemplateColumns.mockReturnValue({
data: {
- graph: {
- nodes: [{
- id: 'start',
- data: {
- type: 'start',
- variables: [{
- variable: 'graph_only',
- type: 'text-input',
- }],
- },
- }],
- },
- input_fields: [],
+ columns: [],
},
- isLoading: false,
+ isError: false,
+ isFetching: false,
+ isPending: false,
})
renderWithQueryClient()
- expect(screen.getByText('evaluation.batch.noSnippetInputFields')).toBeInTheDocument()
- expect(screen.queryByText('evaluation.batch.noInputFields')).not.toBeInTheDocument()
- expect(screen.queryByText('graph_only')).not.toBeInTheDocument()
+ expect(screen.getByText('evaluation.batch.noTemplateColumns')).toBeInTheDocument()
})
it('should hide the value row for empty operators', () => {
@@ -630,14 +627,17 @@ describe('Evaluation', () => {
it('should download the fixed pipeline template columns', () => {
const createElement = document.createElement.bind(document)
- const getTemplateColumns = vi.fn((_input: unknown, options?: { onSuccess?: (value: { columns: string[] }) => void }) => {
- options?.onSuccess?.({
- columns: ['index', 'query', 'expected_output'],
- })
- })
- mockUseEvaluationTemplateColumnsMutation.mockReturnValue({
+ mockUseEvaluationTemplateColumns.mockReturnValue({
+ data: {
+ columns: [
+ { name: 'index', type: 'number' },
+ { name: 'query', type: 'string' },
+ { name: 'expected_output', type: 'string' },
+ ],
+ },
+ isError: false,
+ isFetching: false,
isPending: false,
- mutate: getTemplateColumns,
})
let downloadLink: HTMLAnchorElement | undefined
const createElementSpy = vi.spyOn(document, 'createElement').mockImplementation((tagName, options) => {
@@ -660,16 +660,15 @@ describe('Evaluation', () => {
const templateContent = decodeURIComponent(downloadLink?.href ?? '').replace('data:text/csv;charset=utf-8,', '')
expect(downloadLink?.download).toBe('pipeline-evaluation-template.csv')
expect(templateContent.trim().split(',')).toEqual(['index', 'query', 'expected_output'])
- expect(getTemplateColumns).toHaveBeenCalledWith({
- params: {
- targetType: 'datasets',
- targetId: 'dataset-template',
- },
- body: expect.objectContaining({
+ expect(mockUseEvaluationTemplateColumns).toHaveBeenLastCalledWith(
+ 'datasets',
+ 'dataset-template',
+ expect.objectContaining({
evaluation_model: 'gpt-4o-mini',
evaluation_model_provider: 'openai',
}),
- }, expect.any(Object))
+ true,
+ )
createElementSpy.mockRestore()
})
diff --git a/web/app/components/evaluation/components/batch-test-panel/input-fields-tab.tsx b/web/app/components/evaluation/components/batch-test-panel/input-fields-tab.tsx
index 19e23719ba..e00e078263 100644
--- a/web/app/components/evaluation/components/batch-test-panel/input-fields-tab.tsx
+++ b/web/app/components/evaluation/components/batch-test-panel/input-fields-tab.tsx
@@ -5,7 +5,6 @@ import { EVALUATION_TEMPLATE_FILE_NAMES } from '../../store-utils'
import InputFieldsRequirements from './input-fields/input-fields-requirements'
import UploadRunPopover from './input-fields/upload-run-popover'
import { useInputFieldsActions } from './input-fields/use-input-fields-actions'
-import { usePublishedInputFields } from './input-fields/use-published-input-fields'
type InputFieldsTabProps = EvaluationResourceProps & {
isPanelReady: boolean
@@ -19,11 +18,9 @@ const InputFieldsTab = ({
isRunnable,
}: InputFieldsTabProps) => {
const { t } = useTranslation('evaluation')
- const { inputFields, isInputFieldsLoading } = usePublishedInputFields(resourceType, resourceId)
const actions = useInputFieldsActions({
resourceType,
resourceId,
- isInputFieldsLoading,
isPanelReady,
isRunnable,
templateFileName: EVALUATION_TEMPLATE_FILE_NAMES[resourceType],
@@ -32,9 +29,8 @@ const InputFieldsTab = ({
return (