Pulastya B commited on
Commit
ff2d6c4
·
1 Parent(s): 296ce82

Fix progress bar to show latest step, visualizations in assets, model names, data files, and response formatting

Browse files
FRRONTEEEND/components/ChatInterface.tsx CHANGED
@@ -88,11 +88,17 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
88
  const progressData = await progressResponse.json();
89
  const steps = progressData.steps || [];
90
 
91
- // Find the most recent running step
92
- const runningSteps = steps.filter((s: any) => s.status === 'running');
93
- if (runningSteps.length > 0) {
94
- const lastStep = runningSteps[runningSteps.length - 1];
95
- setCurrentStep(lastStep.tool);
 
 
 
 
 
 
96
  }
97
  }
98
  } catch (err) {
@@ -694,69 +700,101 @@ export const ChatInterface: React.FC<{ onBack: () => void }> = ({ onBack }) => {
694
  </div>
695
 
696
  <div className="flex-1 overflow-y-auto p-4 space-y-4 custom-scrollbar">
697
- {/* Collect all assets from messages */}
698
  {(() => {
699
  const allPlots: Array<{title: string, url: string, type?: string}> = [];
700
  const allReports: Array<{name: string, path: string}> = [];
701
- const allModels: string[] = [];
 
 
702
 
703
  activeSession.messages.forEach(msg => {
704
  if (msg.plots) allPlots.push(...msg.plots);
705
  if (msg.reports) allReports.push(...msg.reports);
706
- // Extract model references from content
707
- if (msg.content.includes('xgboost') || msg.content.includes('model')) {
708
- const modelMatch = msg.content.match(/\b(xgboost|random_forest|catboost|lightgbm)[^\s]*/gi);
709
- if (modelMatch) allModels.push(...modelMatch);
 
 
 
 
 
 
710
  }
711
  });
712
 
713
- const uniqueModels = [...new Set(allModels)];
 
714
 
715
  return (
716
  <>
717
- {/* Models Section */}
718
- {uniqueModels.length > 0 && (
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
719
  <div>
720
  <div className="flex items-center gap-2 mb-3">
721
  <FileText className="w-4 h-4 text-blue-400" />
722
- <h4 className="text-xs font-bold uppercase tracking-wider text-white/60">Models ({uniqueModels.length})</h4>
723
  </div>
724
  <div className="space-y-2">
725
- {uniqueModels.slice(0, 5).map((model, idx) => (
726
  <div
727
  key={idx}
728
- className="p-3 rounded-lg bg-white/5 border border-white/10 hover:bg-white/10 transition-all cursor-pointer group"
729
  >
730
  <div className="flex items-center justify-between">
731
- <span className="text-sm text-white/80 truncate flex-1">{model}</span>
732
- <ChevronRight className="w-4 h-4 text-white/40 group-hover:text-white/80 transition-all" />
733
  </div>
 
734
  </div>
735
  ))}
736
  </div>
737
  </div>
738
  )}
739
 
740
- {/* Plots Section */}
741
- {allPlots.length > 0 && (
742
  <div>
743
  <div className="flex items-center gap-2 mb-3">
744
- <BarChart3 className="w-4 h-4 text-emerald-400" />
745
- <h4 className="text-xs font-bold uppercase tracking-wider text-white/60">Visualizations ({allPlots.length})</h4>
746
  </div>
747
  <div className="space-y-2">
748
- {allPlots.map((plot, idx) => (
749
- <button
750
  key={idx}
751
- onClick={() => setReportModalUrl(plot.url)}
752
- className="w-full p-3 rounded-lg bg-white/5 border border-white/10 hover:bg-emerald-500/10 hover:border-emerald-500/30 transition-all text-left group"
753
  >
754
  <div className="flex items-center justify-between">
755
- <span className="text-sm text-white/80 truncate flex-1">{plot.title}</span>
756
- <ChevronRight className="w-4 h-4 text-white/40 group-hover:text-emerald-400 transition-all" />
757
  </div>
758
- <span className="text-xs text-white/40 mt-1 block">{plot.type || 'interactive'}</span>
759
- </button>
760
  ))}
761
  </div>
762
  </div>
 
88
  const progressData = await progressResponse.json();
89
  const steps = progressData.steps || [];
90
 
91
+ if (steps.length > 0) {
92
+ const latestStep = steps[steps.length - 1];
93
+ const toolName = latestStep.tool
94
+ .replace(/_/g, ' ')
95
+ .replace(/generate/gi, 'Generating')
96
+ .replace(/train/gi, 'Training')
97
+ .replace(/clean/gi, 'Cleaning')
98
+ .replace(/create/gi, 'Creating')
99
+ .replace(/perform/gi, 'Performing')
100
+ .replace(/\b\w/g, (l: string) => l.toUpperCase());
101
+ setCurrentStep(toolName);
102
  }
103
  }
104
  } catch (err) {
 
700
  </div>
701
 
702
  <div className="flex-1 overflow-y-auto p-4 space-y-4 custom-scrollbar">
 
703
  {(() => {
704
  const allPlots: Array<{title: string, url: string, type?: string}> = [];
705
  const allReports: Array<{name: string, path: string}> = [];
706
+ const allDataFiles: string[] = [];
707
+ const baselineModels = ['xgboost', 'random_forest', 'catboost', 'lightgbm', 'ridge', 'lasso'];
708
+ const foundModels = new Set<string>();
709
 
710
  activeSession.messages.forEach(msg => {
711
  if (msg.plots) allPlots.push(...msg.plots);
712
  if (msg.reports) allReports.push(...msg.reports);
713
+
714
+ baselineModels.forEach(model => {
715
+ if (msg.content.toLowerCase().includes(model)) {
716
+ const displayName = model.split('_').map(w => w.charAt(0).toUpperCase() + w.slice(1)).join(' ');
717
+ foundModels.add(displayName);
718
+ }
719
+ });
720
+
721
+ if (msg.content.includes('Cleaned') || msg.content.includes('encoded')) {
722
+ allDataFiles.push('Cleaned & Encoded Dataset');
723
  }
724
  });
725
 
726
+ const uniqueDataFiles = [...new Set(allDataFiles)];
727
+ const uniqueModels = Array.from(foundModels);
728
 
729
  return (
730
  <>
731
+ {/* Plots Section FIRST */}
732
+ {allPlots.length > 0 && (
733
+ <div>
734
+ <div className="flex items-center gap-2 mb-3">
735
+ <BarChart3 className="w-4 h-4 text-emerald-400" />
736
+ <h4 className="text-xs font-bold uppercase tracking-wider text-white/60">Visualizations ({allPlots.length})</h4>
737
+ </div>
738
+ <div className="space-y-2">
739
+ {allPlots.map((plot, idx) => (
740
+ <button
741
+ key={idx}
742
+ onClick={() => setReportModalUrl(plot.url)}
743
+ className="w-full p-3 rounded-lg bg-white/5 border border-white/10 hover:bg-emerald-500/10 hover:border-emerald-500/30 transition-all text-left group"
744
+ >
745
+ <div className="flex items-center justify-between">
746
+ <span className="text-sm text-white/80 truncate flex-1">{plot.title}</span>
747
+ <ChevronRight className="w-4 h-4 text-white/40 group-hover:text-emerald-400 transition-all" />
748
+ </div>
749
+ <span className="text-xs text-white/40 mt-1 block">{plot.type || 'interactive'}</span>
750
+ </button>
751
+ ))}
752
+ </div>
753
+ </div>
754
+ )}
755
+
756
+ {/* Data Files Section */}
757
+ {uniqueDataFiles.length > 0 && (
758
  <div>
759
  <div className="flex items-center gap-2 mb-3">
760
  <FileText className="w-4 h-4 text-blue-400" />
761
+ <h4 className="text-xs font-bold uppercase tracking-wider text-white/60">Data Files ({uniqueDataFiles.length})</h4>
762
  </div>
763
  <div className="space-y-2">
764
+ {uniqueDataFiles.map((file, idx) => (
765
  <div
766
  key={idx}
767
+ className="p-3 rounded-lg bg-white/5 border border-white/10 hover:bg-blue-500/10 transition-all cursor-pointer group"
768
  >
769
  <div className="flex items-center justify-between">
770
+ <span className="text-sm text-white/80 truncate flex-1">{file}</span>
771
+ <ChevronRight className="w-4 h-4 text-white/40 group-hover:text-blue-400 transition-all" />
772
  </div>
773
+ <span className="text-xs text-white/40 mt-1 block">Dataset</span>
774
  </div>
775
  ))}
776
  </div>
777
  </div>
778
  )}
779
 
780
+ {/* Models Section */}
781
+ {uniqueModels.length > 0 && (
782
  <div>
783
  <div className="flex items-center gap-2 mb-3">
784
+ <FileText className="w-4 h-4 text-purple-400" />
785
+ <h4 className="text-xs font-bold uppercase tracking-wider text-white/60">Models ({uniqueModels.length})</h4>
786
  </div>
787
  <div className="space-y-2">
788
+ {uniqueModels.map((model, idx) => (
789
+ <div
790
  key={idx}
791
+ className="p-3 rounded-lg bg-white/5 border border-white/10 hover:bg-purple-500/10 transition-all cursor-pointer group"
 
792
  >
793
  <div className="flex items-center justify-between">
794
+ <span className="text-sm text-white/80 truncate flex-1">{model}</span>
795
+ <ChevronRight className="w-4 h-4 text-white/40 group-hover:text-purple-400 transition-all" />
796
  </div>
797
+ </div>
 
798
  ))}
799
  </div>
800
  </div>
src/orchestrator.py CHANGED
@@ -2305,21 +2305,41 @@ You are a DOER. Complete workflows based on user intent."""
2305
  )
2306
  summary_text = enhanced_summary["text"]
2307
 
2308
- # 🧹 POST-PROCESS: Remove any file paths that slipped through
2309
  import re
2310
- # Remove file path patterns
2311
- summary_text = re.sub(r'\./outputs/[^\s\)]+', '[generated file]', summary_text)
2312
- summary_text = re.sub(r'/outputs/[^\s\)]+', '[generated file]', summary_text)
2313
- summary_text = re.sub(r'outputs/[^\s\)]+', '[generated file]', summary_text)
2314
- # Remove common file path mentions
2315
- summary_text = re.sub(r'saved to:?\s*[^\s]+', 'generated', summary_text, flags=re.IGNORECASE)
2316
- summary_text = re.sub(r'output file:?\s*[^\s]+', 'output generated', summary_text, flags=re.IGNORECASE)
2317
- summary_text = re.sub(r'file path:?\s*[^\s]+', 'file generated', summary_text, flags=re.IGNORECASE)
2318
- # Remove filename patterns in parentheses and backticks
2319
- summary_text = re.sub(r'\([^\)]*\.(csv|pkl|html|png|json)[^\)]*\)', '', summary_text)
 
 
 
 
 
 
 
 
 
2320
  summary_text = re.sub(r'`[^`]*\.(csv|pkl|html|png|json)[^`]*`', '', summary_text)
2321
- # Clean up table separators that mention paths
2322
- summary_text = re.sub(r'\|\s*[^\|]*\.(csv|pkl|html|png)[^\|]*\s*\|', '| [see artifacts] |', summary_text)
 
 
 
 
 
 
 
 
 
 
 
2323
 
2324
  metrics_data = enhanced_summary.get("metrics", {})
2325
  artifacts_data = enhanced_summary.get("artifacts", {})
 
2305
  )
2306
  summary_text = enhanced_summary["text"]
2307
 
2308
+ # 🧹 POST-PROCESS: Aggressive cleanup of formatting
2309
  import re
2310
+
2311
+ # Remove ALL file path patterns
2312
+ summary_text = re.sub(r'\./outputs/[^\s\)\]]+', '', summary_text)
2313
+ summary_text = re.sub(r'/outputs/[^\s\)\]]+', '', summary_text)
2314
+ summary_text = re.sub(r'outputs/[^\s\)\]]+', '', summary_text)
2315
+ summary_text = re.sub(r'\[[^\]]*\.(csv|pkl|html|png|json)[^\]]*\]', '', summary_text)
2316
+
2317
+ # Remove leftover file markers
2318
+ summary_text = re.sub(r'\[generated file\]', '', summary_text)
2319
+ summary_text = re.sub(r'\[see artifacts\]', '', summary_text)
2320
+
2321
+ # Remove file path mentions
2322
+ summary_text = re.sub(r'saved to:?\s*[^\s\.]+', '', summary_text, flags=re.IGNORECASE)
2323
+ summary_text = re.sub(r'output file:?\s*[^\s\.]+', '', summary_text, flags=re.IGNORECASE)
2324
+ summary_text = re.sub(r'file path:?\s*[^\s\.]+', '', summary_text, flags=re.IGNORECASE)
2325
+ summary_text = re.sub(r'path:?\s*[^\s\.]+', '', summary_text, flags=re.IGNORECASE)
2326
+ summary_text = re.sub(r'directory:?\s*[^\s\.]+', '', summary_text, flags=re.IGNORECASE)
2327
+
2328
+ # Remove backtick-wrapped paths and parenthetical paths
2329
  summary_text = re.sub(r'`[^`]*\.(csv|pkl|html|png|json)[^`]*`', '', summary_text)
2330
+ summary_text = re.sub(r'\([^\)]*\.(csv|pkl|html|png|json)[^\)]*\)', '', summary_text)
2331
+
2332
+ # Clean broken tables
2333
+ summary_text = re.sub(r'\|\s*\[[^\]]*\]\s*\|', '|', summary_text)
2334
+ summary_text = re.sub(r'\|\s*`[^`]*`\s*\|', '|', summary_text)
2335
+ summary_text = re.sub(r'\|\s*\|', '', summary_text)
2336
+
2337
+ # Clean excessive whitespace
2338
+ summary_text = re.sub(r'\n\n\n+', '\n\n', summary_text)
2339
+ summary_text = re.sub(r'[ \t]+', ' ', summary_text) # Remove extra spaces
2340
+
2341
+ # Remove code blocks that are just paths
2342
+ summary_text = re.sub(r'`\.?/?[\w\-/\.]*\.(csv|pkl|html|png|json)`', '', summary_text)
2343
 
2344
  metrics_data = enhanced_summary.get("metrics", {})
2345
  artifacts_data = enhanced_summary.get("artifacts", {})