diff --git a/src/components/SmartGeneration/index.tsx b/src/components/SmartGeneration/index.tsx index 6a4a6fa8..139208af 100644 --- a/src/components/SmartGeneration/index.tsx +++ b/src/components/SmartGeneration/index.tsx @@ -162,6 +162,7 @@ interface ChangeField { member_type: string; cube: string; reason?: string; + source?: "map" | "nested" | "ai"; } interface ChangeBlock { @@ -896,7 +897,11 @@ const SmartGeneration: FC = ({ new Set() ); + const [selectedModelFields, setSelectedModelFields] = useState>( + new Set() + ); const [profileData, setProfileData] = useState(null); + const [skipLlm, setSkipLlm] = useState(false); const [progressEvents, setProgressEvents] = useState([]); const abortRef = useRef(null); @@ -1204,7 +1209,8 @@ const SmartGeneration: FC = ({ file_name: fileNameOverride || undefined, cube_name: cubeNameOverride || undefined, selected_columns: isSubset ? [...selectedColumns] : undefined, - }); + skip_llm: skipLlm || undefined, + } as any); if (result.error) { setError(result.error.message); @@ -1216,13 +1222,43 @@ const SmartGeneration: FC = ({ const preview = genData?.change_preview; if (preview) { setChangePreview(preview as ChangePreview); + + // Required fields: rewrite rule dimensions + filter dimensions (always included) + const requiredSet = new Set(genData?.required_fields || []); + + // Default selection rules: + // ALWAYS checked: count measure, required fields (rewrite rules + filters) + // Checked by default: regular columns (no source tag) + // Unchecked (opt-in): map fields, nested fields, AI-generated fields + const isDefaultSelected = (f: any) => { + const key = `${f.cube}.${f.name}`; + // Always include required fields + if (requiredSet.has(key)) return true; + // Always include the count measure + if (f.name === "count" && f.member_type === "measure") return true; + // Opt-in sources: map, nested (ARRAY JOIN), AI-generated + if (f.source === "map" || f.source === "nested" || f.source === "ai") + return false; + // Everything else checked by default + return true; + }; + + const allKeys = [ + ...(preview.fields_added || []) + .filter(isDefaultSelected) + .map((f: any) => `${f.cube}.${f.name}`), + ...(preview.fields_updated || []) + .filter(isDefaultSelected) + .map((f: any) => `${f.cube}.${f.name}`), + ]; + setSelectedModelFields(new Set(allKeys)); } // Capture AI metric suggestions from the LLM (if any) const aiSuggestions = genData?.ai_enrichment?.suggested_metrics || []; setSuggestedAIMetrics(aiSuggestions); - // All selected by default - setSelectedAIMetricNames(new Set(aiSuggestions.map((m: any) => m.name))); + // AI metrics are opt-in (unchecked by default) + setSelectedAIMetricNames(new Set()); setStep("change_preview"); }, [ @@ -1255,6 +1291,15 @@ const SmartGeneration: FC = ({ ).length ?? 0; const applyIsSubset = selectedColumns.size < applyActiveCount; + // Compute excluded fields: all preview fields NOT in the user's selection + const allPreviewFields = [ + ...((changePreview?.fields_added || []) as ChangeField[]), + ...((changePreview?.fields_updated || []) as ChangeField[]), + ].map((f) => `${f.cube}.${f.name}`); + const excludedFields = allPreviewFields.filter( + (key) => !selectedModelFields.has(key) + ); + const result = await execSmartGen({ datasource_id: dataSource.id!, branch_id: branchId, @@ -1269,9 +1314,10 @@ const SmartGeneration: FC = ({ filters: filters.length > 0 ? filters : undefined, file_name: fileNameOverride || undefined, cube_name: cubeNameOverride || undefined, - selected_ai_metrics: - selectedAIMetricNames.size > 0 ? [...selectedAIMetricNames] : undefined, + selected_ai_metrics: [...selectedAIMetricNames], selected_columns: applyIsSubset ? [...selectedColumns] : undefined, + excluded_fields: excludedFields.length > 0 ? excludedFields : undefined, + skip_llm: skipLlm || undefined, } as any); if (result.error) { @@ -1292,6 +1338,8 @@ const SmartGeneration: FC = ({ filters, selectedAIMetricNames, selectedColumns, + selectedModelFields, + changePreview, profileData, execSmartGen, ]); @@ -1579,6 +1627,24 @@ const SmartGeneration: FC = ({ /> )} +
+ setSkipLlm(e.target.checked)} + > + + Skip LLM enrichment (faster, no AI metrics or descriptions) + + +
+