diff --git a/web/app/components/evaluation/__tests__/index.spec.tsx b/web/app/components/evaluation/__tests__/index.spec.tsx index 140ef72edd..1568b60be7 100644 --- a/web/app/components/evaluation/__tests__/index.spec.tsx +++ b/web/app/components/evaluation/__tests__/index.spec.tsx @@ -642,9 +642,9 @@ describe('Evaluation', () => { fireEvent.click(screen.getByRole('button', { name: /Context Precision/i })) fireEvent.click(screen.getByRole('button', { name: 'evaluation.batch.downloadTemplate' })) + const templateContent = decodeURIComponent(downloadLink?.href ?? '').replace('data:text/csv;charset=utf-8,', '') expect(downloadLink?.download).toBe('pipeline-evaluation-template.csv') - expect(decodeURIComponent(downloadLink?.href ?? '')).toContain('query,expected_outputs\n') - expect(decodeURIComponent(downloadLink?.href ?? '')).not.toContain('expected_output') + expect(templateContent.trim().split(',')).toEqual(['index', 'query', 'expected_output']) createElementSpy.mockRestore() }) @@ -667,14 +667,14 @@ describe('Evaluation', () => { fireEvent.click(screen.getByRole('button', { name: 'evaluation.pipeline.uploadAndRun' })) expect(screen.getAllByText('query').length).toBeGreaterThan(0) - expect(screen.getAllByText('expected_outputs').length).toBeGreaterThan(0) + expect(screen.getAllByText('expected_output').length).toBeGreaterThan(0) const fileInput = document.querySelector('input[type="file"][accept=".csv"]') expect(fileInput).toBeInTheDocument() fireEvent.change(fileInput!, { target: { - files: [new File(['query,expected_outputs'], 'pipeline-evaluation.csv', { type: 'text/csv' })], + files: [new File(['index,query,expected_output'], 'pipeline-evaluation.csv', { type: 'text/csv' })], }, }) diff --git a/web/app/components/evaluation/components/batch-test-panel/input-fields/__tests__/input-fields-utils.spec.ts b/web/app/components/evaluation/components/batch-test-panel/input-fields/__tests__/input-fields-utils.spec.ts index 67ee548738..94e8c5f091 100644 --- a/web/app/components/evaluation/components/batch-test-panel/input-fields/__tests__/input-fields-utils.spec.ts +++ b/web/app/components/evaluation/components/batch-test-panel/input-fields/__tests__/input-fields-utils.spec.ts @@ -1,26 +1,39 @@ -import { buildTemplateCsvContent } from '../input-fields-utils' +import { buildTemplateCsvContent, getExampleValue } from '../input-fields-utils' describe('input fields utils', () => { describe('buildTemplateCsvContent', () => { - it('should append expected_output as the last CSV column', () => { + it('should use index as the first CSV column and append expected_output as the last CSV column', () => { expect(buildTemplateCsvContent([ { name: 'query', type: 'string' }, { name: 'context', type: 'string' }, - ])).toBe('query,context,expected_output\n') + ])).toBe('index,query,context,expected_output\n') }) it('should not duplicate expected_output when it already exists', () => { expect(buildTemplateCsvContent([ { name: 'query', type: 'string' }, { name: 'expected_output', type: 'string' }, - ])).toBe('query,expected_output\n') + ])).toBe('index,query,expected_output\n') + }) + + it('should not duplicate index when it already exists', () => { + expect(buildTemplateCsvContent([ + { name: 'query', type: 'string' }, + { name: 'index', type: 'number' }, + ])).toBe('index,query,expected_output\n') }) it('should escape CSV column names before appending expected_output', () => { expect(buildTemplateCsvContent([ { name: 'query,text', type: 'string' }, { name: 'answer "draft"', type: 'string' }, - ])).toBe('"query,text","answer ""draft""",expected_output\n') + ])).toBe('index,"query,text","answer ""draft""",expected_output\n') + }) + }) + + describe('getExampleValue', () => { + it('should use a row number example for index fields', () => { + expect(getExampleValue({ name: 'index', type: 'number' }, 'True')).toBe('1') }) }) }) diff --git a/web/app/components/evaluation/components/batch-test-panel/input-fields/input-fields-utils.ts b/web/app/components/evaluation/components/batch-test-panel/input-fields/input-fields-utils.ts index 6daae07a84..0666dfb4b6 100644 --- a/web/app/components/evaluation/components/batch-test-panel/input-fields/input-fields-utils.ts +++ b/web/app/components/evaluation/components/batch-test-panel/input-fields/input-fields-utils.ts @@ -10,6 +10,7 @@ export type InputField = { type: string } +export const INDEX_FIELD_NAME = 'index' export const EXPECTED_OUTPUT_FIELD_NAME = 'expected_output' export const getGraphNodes = (graph?: Record) => { @@ -65,10 +66,12 @@ const escapeCsvCell = (value: string) => { } export const buildTemplateCsvContent = (inputFields: InputField[]) => { - const fieldNames = inputFields.map(field => field.name) + const fieldNames = inputFields + .map(field => field.name) + .filter(name => name !== INDEX_FIELD_NAME) const templateFieldNames = fieldNames.includes(EXPECTED_OUTPUT_FIELD_NAME) - ? fieldNames - : [...fieldNames, EXPECTED_OUTPUT_FIELD_NAME] + ? [INDEX_FIELD_NAME, ...fieldNames] + : [INDEX_FIELD_NAME, ...fieldNames, EXPECTED_OUTPUT_FIELD_NAME] return `${templateFieldNames.map(escapeCsvCell).join(',')}\n` } @@ -79,6 +82,9 @@ export const getFileExtension = (fileName: string) => { } export const getExampleValue = (field: InputField, booleanLabel: string) => { + if (field.name === INDEX_FIELD_NAME) + return '1' + if (field.type === 'number') return '0.7' diff --git a/web/app/components/evaluation/components/pipeline/pipeline-batch-actions.tsx b/web/app/components/evaluation/components/pipeline/pipeline-batch-actions.tsx index 63a529f63c..f7ac97069f 100644 --- a/web/app/components/evaluation/components/pipeline/pipeline-batch-actions.tsx +++ b/web/app/components/evaluation/components/pipeline/pipeline-batch-actions.tsx @@ -10,10 +10,11 @@ import UploadRunPopover from '../batch-test-panel/input-fields/upload-run-popove import { useInputFieldsActions } from '../batch-test-panel/input-fields/use-input-fields-actions' const PIPELINE_INPUT_FIELDS: InputField[] = [ + { name: 'index', type: 'number' }, { name: 'query', type: 'string' }, - { name: 'expected_outputs', type: 'string' }, + { name: 'expected_output', type: 'string' }, ] -const PIPELINE_TEMPLATE_CONTENT = 'query,expected_outputs\n' +const PIPELINE_TEMPLATE_CONTENT = 'index,query,expected_output\n' const PipelineBatchActions = ({ resourceType,