refactor(web): store of evaluation

This commit is contained in:
JzoNg 2026-04-09 20:32:53 +08:00
parent 5316372772
commit 8dc6d736ee
8 changed files with 38 additions and 77 deletions

View File

@ -130,7 +130,7 @@ describe('Evaluation', () => {
]) ])
store.addCondition(resourceType, resourceId) store.addCondition(resourceType, resourceId)
const condition = useEvaluationStore.getState().resources['apps:app-2'].conditions.conditions[0] const condition = useEvaluationStore.getState().resources['apps:app-2'].judgmentConfig.conditions[0]
conditionId = condition.id conditionId = condition.id
store.updateConditionOperator(resourceType, resourceId, conditionId, '=') store.updateConditionOperator(resourceType, resourceId, conditionId, '=')
}) })

View File

@ -107,7 +107,7 @@ describe('evaluation store', () => {
{ node_id: 'node-2', title: 'Retriever Node', type: 'retriever' }, { node_id: 'node-2', title: 'Retriever Node', type: 'retriever' },
]) ])
expect(state.metrics.filter(item => item.optionId === metricId)).toHaveLength(1) expect(state.metrics.filter(item => item.optionId === metricId)).toHaveLength(1)
expect(state.conditions.conditions).toHaveLength(0) expect(state.judgmentConfig.conditions).toHaveLength(0)
}) })
it('should build numeric conditions from selected metrics', () => { it('should build numeric conditions from selected metrics', () => {
@ -124,9 +124,9 @@ describe('evaluation store', () => {
store.addCondition(resourceType, resourceId) store.addCondition(resourceType, resourceId)
const state = useEvaluationStore.getState().resources['apps:app-conditions'] const state = useEvaluationStore.getState().resources['apps:app-conditions']
const condition = state.conditions.conditions[0] const condition = state.judgmentConfig.conditions[0]
expect(state.conditions.logicalOperator).toBe('or') expect(state.judgmentConfig.logicalOperator).toBe('or')
expect(condition.variableSelector).toEqual(['node-answer', 'answer-correctness']) expect(condition.variableSelector).toEqual(['node-answer', 'answer-correctness'])
expect(condition.comparisonOperator).toBe('=') expect(condition.comparisonOperator).toBe('=')
expect(getAllowedOperators(state.metrics, condition.variableSelector)).toEqual(['=', '≠', '>', '<', '≥', '≤', 'is null', 'is not null']) expect(getAllowedOperators(state.metrics, condition.variableSelector)).toEqual(['=', '≠', '>', '<', '≥', '≤', 'is null', 'is not null'])
@ -153,13 +153,13 @@ describe('evaluation store', () => {
}]) }])
store.addCondition(resourceType, resourceId) store.addCondition(resourceType, resourceId)
const condition = useEvaluationStore.getState().resources['apps:app-3'].conditions.conditions[0] const condition = useEvaluationStore.getState().resources['apps:app-3'].judgmentConfig.conditions[0]
store.updateConditionMetric(resourceType, resourceId, condition.id, [config.workflowOptions[0].id, 'reason']) store.updateConditionMetric(resourceType, resourceId, condition.id, [config.workflowOptions[0].id, 'reason'])
store.updateConditionValue(resourceType, resourceId, condition.id, 'needs follow-up') store.updateConditionValue(resourceType, resourceId, condition.id, 'needs follow-up')
store.updateConditionOperator(resourceType, resourceId, condition.id, 'empty') store.updateConditionOperator(resourceType, resourceId, condition.id, 'empty')
const updatedCondition = useEvaluationStore.getState().resources['apps:app-3'].conditions.conditions[0] const updatedCondition = useEvaluationStore.getState().resources['apps:app-3'].judgmentConfig.conditions[0]
expect(requiresConditionValue('empty')).toBe(false) expect(requiresConditionValue('empty')).toBe(false)
expect(updatedCondition.value).toBeNull() expect(updatedCondition.value).toBeNull()
@ -232,8 +232,8 @@ describe('evaluation store', () => {
expect(hydratedState.metrics[1].customConfig?.mappings[0].inputVariableId).toBe('query') expect(hydratedState.metrics[1].customConfig?.mappings[0].inputVariableId).toBe('query')
expect(hydratedState.metrics[1].customConfig?.mappings[0].outputVariableId).toBe('answer') expect(hydratedState.metrics[1].customConfig?.mappings[0].outputVariableId).toBe('answer')
expect(hydratedState.metrics[1].customConfig?.outputs).toEqual([{ id: 'reason', valueType: 'string' }]) expect(hydratedState.metrics[1].customConfig?.outputs).toEqual([{ id: 'reason', valueType: 'string' }])
expect(hydratedState.conditions.logicalOperator).toBe('or') expect(hydratedState.judgmentConfig.logicalOperator).toBe('or')
expect(hydratedState.conditions.conditions[0]).toMatchObject({ expect(hydratedState.judgmentConfig.conditions[0]).toMatchObject({
variableSelector: ['node-1', 'faithfulness'], variableSelector: ['node-1', 'faithfulness'],
comparisonOperator: '≥', comparisonOperator: '≥',
value: '0.9', value: '0.9',

View File

@ -231,7 +231,7 @@ const ConditionGroup = ({
type="button" type="button"
className={cn( className={cn(
'rounded-md px-3 py-1.5 system-xs-medium-uppercase', 'rounded-md px-3 py-1.5 system-xs-medium-uppercase',
resource.conditions.logicalOperator === operator resource.judgmentConfig.logicalOperator === operator
? 'bg-components-card-bg text-text-primary shadow-xs' ? 'bg-components-card-bg text-text-primary shadow-xs'
: 'text-text-tertiary', : 'text-text-tertiary',
)} )}
@ -245,7 +245,7 @@ const ConditionGroup = ({
</div> </div>
<div className="space-y-3"> <div className="space-y-3">
{resource.conditions.conditions.map((condition) => { {resource.judgmentConfig.conditions.map((condition) => {
const metric = metricOptions.find(option => isSelectorEqual(option.variableSelector, condition.variableSelector)) const metric = metricOptions.find(option => isSelectorEqual(option.variableSelector, condition.variableSelector))
const allowedOperators = getAllowedOperators(resource.metrics, condition.variableSelector) const allowedOperators = getAllowedOperators(resource.metrics, condition.variableSelector)
const showValue = !!metric && requiresConditionValue(condition.comparisonOperator) const showValue = !!metric && requiresConditionValue(condition.comparisonOperator)

View File

@ -26,12 +26,12 @@ const ConditionsSection = ({
tooltip={t('conditions.description')} tooltip={t('conditions.description')}
/> />
<div className="mt-2 space-y-4"> <div className="mt-2 space-y-4">
{resource.conditions.conditions.length === 0 && ( {resource.judgmentConfig.conditions.length === 0 && (
<div className="rounded-xl bg-background-section px-3 py-3 system-xs-regular text-text-tertiary"> <div className="rounded-xl bg-background-section px-3 py-3 system-xs-regular text-text-tertiary">
{t('conditions.emptyDescription')} {t('conditions.emptyDescription')}
</div> </div>
)} )}
{resource.conditions.conditions.length > 0 && ( {resource.judgmentConfig.conditions.length > 0 && (
<ConditionGroup <ConditionGroup
resourceType={resourceType} resourceType={resourceType}
resourceId={resourceId} resourceId={resourceId}

View File

@ -180,21 +180,6 @@ const getNormalizedConditionValue = (
return typeof previousValue === 'string' ? previousValue : null return typeof previousValue === 'string' ? previousValue : null
} }
const getRawJudgmentConfig = (config: EvaluationConfig): EvaluationJudgmentConfig | null | undefined => {
if (config.judgment_config)
return config.judgment_config
if (
config.judgement_conditions
&& !Array.isArray(config.judgement_conditions)
&& 'conditions' in config.judgement_conditions
) {
return config.judgement_conditions as EvaluationJudgmentConfig
}
return null
}
const normalizeConditionItem = ( const normalizeConditionItem = (
value: EvaluationJudgmentCondition, value: EvaluationJudgmentCondition,
metrics: EvaluationMetric[], metrics: EvaluationMetric[],
@ -234,7 +219,7 @@ const normalizeJudgmentConfig = (
config: EvaluationConfig, config: EvaluationConfig,
metrics: EvaluationMetric[], metrics: EvaluationMetric[],
): JudgmentConfig => { ): JudgmentConfig => {
const rawJudgmentConfig = getRawJudgmentConfig(config) const rawJudgmentConfig: EvaluationJudgmentConfig | null | undefined = config.judgment_config
if (!rawJudgmentConfig) if (!rawJudgmentConfig)
return createEmptyJudgmentConfig() return createEmptyJudgmentConfig()
@ -393,7 +378,7 @@ export const buildInitialState = (_resourceType: EvaluationResourceType): Evalua
return { return {
judgeModelId: null, judgeModelId: null,
metrics: [], metrics: [],
conditions: createEmptyJudgmentConfig(), judgmentConfig: createEmptyJudgmentConfig(),
activeBatchTab: 'input-fields', activeBatchTab: 'input-fields',
uploadedFileName: null, uploadedFileName: null,
batchRecords: [], batchRecords: [],
@ -414,7 +399,7 @@ export const buildStateFromEvaluationConfig = (
? encodeModelSelection(config.evaluation_model_provider, config.evaluation_model) ? encodeModelSelection(config.evaluation_model_provider, config.evaluation_model)
: null, : null,
metrics, metrics,
conditions: normalizeJudgmentConfig(config, metrics), judgmentConfig: normalizeJudgmentConfig(config, metrics),
} }
} }

View File

@ -133,7 +133,7 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...currentResource, ...currentResource,
metrics, metrics,
conditions: syncJudgmentConfigWithMetrics(currentResource.conditions, metrics), judgmentConfig: syncJudgmentConfigWithMetrics(currentResource.judgmentConfig, metrics),
} }
}), }),
} }
@ -160,7 +160,7 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...resource, ...resource,
metrics, metrics,
conditions: syncJudgmentConfigWithMetrics(resource.conditions, metrics), judgmentConfig: syncJudgmentConfigWithMetrics(resource.judgmentConfig, metrics),
} }
}), }),
})) }))
@ -173,7 +173,7 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...resource, ...resource,
metrics, metrics,
conditions: syncJudgmentConfigWithMetrics(resource.conditions, metrics), judgmentConfig: syncJudgmentConfigWithMetrics(resource.judgmentConfig, metrics),
} }
}), }),
})) }))
@ -201,7 +201,7 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...resource, ...resource,
metrics, metrics,
conditions: syncJudgmentConfigWithMetrics(resource.conditions, metrics), judgmentConfig: syncJudgmentConfigWithMetrics(resource.judgmentConfig, metrics),
} }
}), }),
})) }))
@ -238,7 +238,7 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...resource, ...resource,
metrics, metrics,
conditions: syncJudgmentConfigWithMetrics(resource.conditions, metrics), judgmentConfig: syncJudgmentConfigWithMetrics(resource.judgmentConfig, metrics),
} }
}), }),
})) }))
@ -263,8 +263,8 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
set(state => ({ set(state => ({
resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({ resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({
...resource, ...resource,
conditions: { judgmentConfig: {
...resource.conditions, ...resource.judgmentConfig,
logicalOperator, logicalOperator,
}, },
})), })),
@ -274,9 +274,9 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
set(state => ({ set(state => ({
resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({ resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({
...resource, ...resource,
conditions: { judgmentConfig: {
...resource.conditions, ...resource.judgmentConfig,
conditions: [...resource.conditions.conditions, buildConditionItem(resource.metrics)], conditions: [...resource.judgmentConfig.conditions, buildConditionItem(resource.metrics)],
}, },
})), })),
})) }))
@ -285,9 +285,9 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
set(state => ({ set(state => ({
resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({ resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({
...resource, ...resource,
conditions: { judgmentConfig: {
...resource.conditions, ...resource.judgmentConfig,
conditions: resource.conditions.conditions.filter(condition => condition.id !== conditionId), conditions: resource.judgmentConfig.conditions.filter(condition => condition.id !== conditionId),
}, },
})), })),
})) }))
@ -303,9 +303,9 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
...resource, ...resource,
conditions: { judgmentConfig: {
...resource.conditions, ...resource.judgmentConfig,
conditions: resource.conditions.conditions.map(condition => condition.id === conditionId conditions: resource.judgmentConfig.conditions.map(condition => condition.id === conditionId
? { ? {
...condition, ...condition,
variableSelector, variableSelector,
@ -323,9 +323,9 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
return { return {
resources: updateResourceState(state.resources, resourceType, resourceId, currentResource => ({ resources: updateResourceState(state.resources, resourceType, resourceId, currentResource => ({
...currentResource, ...currentResource,
conditions: { judgmentConfig: {
...currentResource.conditions, ...currentResource.judgmentConfig,
conditions: currentResource.conditions.conditions.map((condition) => { conditions: currentResource.judgmentConfig.conditions.map((condition) => {
if (condition.id !== conditionId) if (condition.id !== conditionId)
return condition return condition
@ -350,9 +350,9 @@ export const useEvaluationStore = create<EvaluationStore>((set, get) => ({
set(state => ({ set(state => ({
resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({ resources: updateResourceState(state.resources, resourceType, resourceId, resource => ({
...resource, ...resource,
conditions: { judgmentConfig: {
...resource.conditions, ...resource.judgmentConfig,
conditions: resource.conditions.conditions.map(condition => condition.id === conditionId ? { ...condition, value } : condition), conditions: resource.judgmentConfig.conditions.map(condition => condition.id === conditionId ? { ...condition, value } : condition),
}, },
})), })),
})) }))

View File

@ -130,7 +130,7 @@ export type BatchTestRecord = {
export type EvaluationResourceState = { export type EvaluationResourceState = {
judgeModelId: string | null judgeModelId: string | null
metrics: EvaluationMetric[] metrics: EvaluationMetric[]
conditions: JudgmentConfig judgmentConfig: JudgmentConfig
activeBatchTab: BatchTestTab activeBatchTab: BatchTestTab
uploadedFileName: string | null uploadedFileName: string | null
batchRecords: BatchTestRecord[] batchRecords: BatchTestRecord[]

View File

@ -13,36 +13,12 @@ export type EvaluationJudgmentConfig = {
conditions?: EvaluationJudgmentCondition[] conditions?: EvaluationJudgmentCondition[]
} }
export type EvaluationConditionValue = string | number | boolean | null
export type EvaluationJudgementConditionItem = {
id?: string
fieldId?: string
field_id?: string
operator?: string
value?: EvaluationConditionValue
}
export type EvaluationJudgementConditionGroup = {
id?: string
logicalOperator?: 'and' | 'or'
logical_operator?: 'and' | 'or'
items?: EvaluationJudgementConditionItem[]
}
export type EvaluationJudgementConditions
= | EvaluationJudgementConditionGroup[]
| {
groups?: EvaluationJudgementConditionGroup[]
}
export type EvaluationConfig = { export type EvaluationConfig = {
evaluation_model: string | null evaluation_model: string | null
evaluation_model_provider: string | null evaluation_model_provider: string | null
default_metrics?: EvaluationDefaultMetric[] | null default_metrics?: EvaluationDefaultMetric[] | null
customized_metrics?: EvaluationCustomizedMetric | null customized_metrics?: EvaluationCustomizedMetric | null
judgment_config?: EvaluationJudgmentConfig | null judgment_config?: EvaluationJudgmentConfig | null
judgement_conditions?: EvaluationJudgementConditions | null
} }
export type NodeInfo = { export type NodeInfo = {