mirror of
https://github.com/langgenius/dify.git
synced 2026-04-05 09:49:25 +08:00
183 lines
5.5 KiB
TypeScript
183 lines
5.5 KiB
TypeScript
import type {
|
|
BatchTestRecord,
|
|
ComparisonOperator,
|
|
CustomMetricMapping,
|
|
EvaluationFieldOption,
|
|
EvaluationMetric,
|
|
EvaluationResourceState,
|
|
EvaluationResourceType,
|
|
JudgmentConditionGroup,
|
|
MetricOption,
|
|
} from './types'
|
|
import type { NodeInfo } from '@/types/evaluation'
|
|
import { getComparisonOperators, getDefaultOperator, getEvaluationMockConfig } from './mock'
|
|
|
|
type EvaluationStoreResources = Record<string, EvaluationResourceState>
|
|
|
|
const createId = (prefix: string) => `${prefix}-${Math.random().toString(36).slice(2, 10)}`
|
|
|
|
export const buildResourceKey = (resourceType: EvaluationResourceType, resourceId: string) => `${resourceType}:${resourceId}`
|
|
|
|
const conditionOperatorsWithoutValue: ComparisonOperator[] = ['is_empty', 'is_not_empty']
|
|
|
|
export const requiresConditionValue = (operator: ComparisonOperator) => !conditionOperatorsWithoutValue.includes(operator)
|
|
|
|
export const getConditionValue = (
|
|
field: EvaluationFieldOption | undefined,
|
|
operator: ComparisonOperator,
|
|
previousValue: string | number | boolean | null = null,
|
|
) => {
|
|
if (!field || !requiresConditionValue(operator))
|
|
return null
|
|
|
|
if (field.type === 'boolean')
|
|
return typeof previousValue === 'boolean' ? previousValue : null
|
|
|
|
if (field.type === 'enum')
|
|
return typeof previousValue === 'string' ? previousValue : null
|
|
|
|
if (field.type === 'number')
|
|
return typeof previousValue === 'number' ? previousValue : null
|
|
|
|
return typeof previousValue === 'string' ? previousValue : null
|
|
}
|
|
|
|
export const createBuiltinMetric = (metric: MetricOption, nodeInfoList: NodeInfo[] = []): EvaluationMetric => ({
|
|
id: createId('metric'),
|
|
optionId: metric.id,
|
|
kind: 'builtin',
|
|
label: metric.label,
|
|
description: metric.description,
|
|
badges: metric.badges,
|
|
nodeInfoList,
|
|
})
|
|
|
|
export const createCustomMetricMapping = (): CustomMetricMapping => ({
|
|
id: createId('mapping'),
|
|
sourceFieldId: null,
|
|
targetVariableId: null,
|
|
})
|
|
|
|
export const createCustomMetric = (): EvaluationMetric => ({
|
|
id: createId('metric'),
|
|
optionId: createId('custom'),
|
|
kind: 'custom-workflow',
|
|
label: 'Custom Evaluator',
|
|
description: 'Map workflow variables to your evaluation inputs.',
|
|
badges: ['Workflow'],
|
|
customConfig: {
|
|
workflowId: null,
|
|
mappings: [createCustomMetricMapping()],
|
|
},
|
|
})
|
|
|
|
export const buildConditionItem = (resourceType: EvaluationResourceType) => {
|
|
const field = getEvaluationMockConfig(resourceType).fieldOptions[0]
|
|
const operator = field ? getDefaultOperator(field.type) : 'contains'
|
|
|
|
return {
|
|
id: createId('condition'),
|
|
fieldId: field?.id ?? null,
|
|
operator,
|
|
value: getConditionValue(field, operator),
|
|
}
|
|
}
|
|
|
|
export const createConditionGroup = (resourceType: EvaluationResourceType): JudgmentConditionGroup => ({
|
|
id: createId('group'),
|
|
logicalOperator: 'and',
|
|
items: [buildConditionItem(resourceType)],
|
|
})
|
|
|
|
export const buildInitialState = (resourceType: EvaluationResourceType): EvaluationResourceState => {
|
|
return {
|
|
judgeModelId: null,
|
|
metrics: [],
|
|
conditions: [createConditionGroup(resourceType)],
|
|
activeBatchTab: 'input-fields',
|
|
uploadedFileName: null,
|
|
batchRecords: [],
|
|
}
|
|
}
|
|
|
|
const getResourceState = (
|
|
resources: EvaluationStoreResources,
|
|
resourceType: EvaluationResourceType,
|
|
resourceId: string,
|
|
) => {
|
|
const resourceKey = buildResourceKey(resourceType, resourceId)
|
|
|
|
return {
|
|
resourceKey,
|
|
resource: resources[resourceKey] ?? buildInitialState(resourceType),
|
|
}
|
|
}
|
|
|
|
export const updateResourceState = (
|
|
resources: EvaluationStoreResources,
|
|
resourceType: EvaluationResourceType,
|
|
resourceId: string,
|
|
updater: (resource: EvaluationResourceState) => EvaluationResourceState,
|
|
) => {
|
|
const { resource, resourceKey } = getResourceState(resources, resourceType, resourceId)
|
|
|
|
return {
|
|
...resources,
|
|
[resourceKey]: updater(resource),
|
|
}
|
|
}
|
|
|
|
export const updateMetric = (
|
|
metrics: EvaluationMetric[],
|
|
metricId: string,
|
|
updater: (metric: EvaluationMetric) => EvaluationMetric,
|
|
) => metrics.map(metric => metric.id === metricId ? updater(metric) : metric)
|
|
|
|
export const updateConditionGroup = (
|
|
groups: JudgmentConditionGroup[],
|
|
groupId: string,
|
|
updater: (group: JudgmentConditionGroup) => JudgmentConditionGroup,
|
|
) => groups.map(group => group.id === groupId ? updater(group) : group)
|
|
|
|
export const createBatchTestRecord = (
|
|
resourceType: EvaluationResourceType,
|
|
uploadedFileName: string | null | undefined,
|
|
): BatchTestRecord => {
|
|
const config = getEvaluationMockConfig(resourceType)
|
|
|
|
return {
|
|
id: createId('batch'),
|
|
fileName: uploadedFileName ?? config.templateFileName,
|
|
status: 'running',
|
|
startedAt: new Date().toLocaleTimeString(),
|
|
summary: config.historySummaryLabel,
|
|
}
|
|
}
|
|
|
|
export const isCustomMetricConfigured = (metric: EvaluationMetric) => {
|
|
if (metric.kind !== 'custom-workflow')
|
|
return true
|
|
|
|
if (!metric.customConfig?.workflowId)
|
|
return false
|
|
|
|
return metric.customConfig.mappings.length > 0
|
|
&& metric.customConfig.mappings.every(mapping => !!mapping.sourceFieldId && !!mapping.targetVariableId)
|
|
}
|
|
|
|
export const isEvaluationRunnable = (state: EvaluationResourceState) => {
|
|
return !!state.judgeModelId
|
|
&& state.metrics.length > 0
|
|
&& state.metrics.every(isCustomMetricConfigured)
|
|
&& state.conditions.some(group => group.items.length > 0)
|
|
}
|
|
|
|
export const getAllowedOperators = (resourceType: EvaluationResourceType, fieldId: string | null) => {
|
|
const field = getEvaluationMockConfig(resourceType).fieldOptions.find(option => option.id === fieldId)
|
|
|
|
if (!field)
|
|
return ['contains'] as ComparisonOperator[]
|
|
|
|
return getComparisonOperators(field.type)
|
|
}
|