stillerman commited on
Commit
cb1d20a
·
1 Parent(s): cb34e94

force directed actually working

Browse files
.gitignore CHANGED
@@ -24,4 +24,6 @@ dist-ssr
24
  *.sw?
25
 
26
  .env
27
- tmp
 
 
 
24
  *.sw?
25
 
26
  .env
27
+ tmp
28
+
29
+ qwen3-final-results.json
src/components/force-directed-graph.tsx CHANGED
@@ -1,9 +1,9 @@
1
  "use client";
2
 
3
  import { useEffect, useRef, useState } from "react";
4
- import ForceGraph2D from "react-force-graph-2d";
5
  import { Run } from "./reasoning-trace";
6
-
7
  // This is a placeholder component for the force-directed graph
8
  // In a real implementation, you would use a library like D3.js or react-force-graph
9
 
@@ -13,19 +13,20 @@ interface ForceDirectedGraphProps {
13
  }
14
 
15
  export default function ForceDirectedGraph({runs, runId }: ForceDirectedGraphProps) {
16
- const [graphData, setGraphData] = useState<{nodes: {id: string}[], links: {source: string, target: string}[]}>({nodes: [], links: []});
17
- const [dimensions, setDimensions] = useState({ width: 300, height: 300 });
18
  const containerRef = useRef<HTMLDivElement>(null);
19
-
20
  useEffect(() => {
21
 
22
- const newGraphData: {nodes: {id: string}[], links: {source: string, target: string}[]} = {nodes: [], links: []};
23
  const nodesSet: Set<string> = new Set();
24
  const mainNodeSet: Set<string> = new Set();
25
 
26
  if(runs) {
27
- runs.forEach((run) => {
28
  // add in src and dst to nodes
 
29
 
30
  mainNodeSet.add(run.start_article);
31
  mainNodeSet.add(run.destination_article);
@@ -42,13 +43,17 @@ export default function ForceDirectedGraph({runs, runId }: ForceDirectedGraphPro
42
  nodesSet.add(nextStep.article);
43
  }
44
 
45
- newGraphData.links.push({source: step.article, target: nextStep.article});
 
 
 
 
46
  }
47
 
48
  const mainNodes = Array.from(mainNodeSet);
49
- const radius = 200; // Radius of the circle
50
- const centerX = 400; // Center X coordinate
51
- const centerY = 300; // Center Y coordinate
52
 
53
  newGraphData.nodes = mainNodes.map((id, index) => {
54
  const angle = (index * 2 * Math.PI) / mainNodes.length;
@@ -56,50 +61,84 @@ export default function ForceDirectedGraph({runs, runId }: ForceDirectedGraphPro
56
  id,
57
  fx: centerX + radius * Math.cos(angle),
58
  fy: centerY + radius * Math.sin(angle),
59
- color: "red"
60
  };
61
  });
62
- newGraphData.nodes.push(...Array.from(nodesSet).map((id) => ({id})));
 
 
 
63
  });
64
 
65
  setGraphData(newGraphData);
66
  }
67
- }, [runs]);
68
-
69
- // useEffect(() => {
70
- // if (!containerRef.current) return;
71
- // const observer = new window.ResizeObserver(entries => {
72
- // for (const entry of entries) {
73
- // const { width, height } = entry.contentRect;
74
- // setDimensions({ width, height });
75
- // }
76
- // });
77
- // observer.observe(containerRef.current);
78
- // // Set initial size
79
- // setDimensions({
80
- // width: containerRef.current.offsetWidth,
81
- // height: containerRef.current.offsetHeight
82
- // });
83
- // return () => observer.disconnect();
84
- // }, []);
85
-
86
- // if (!runId) {
87
- // return (
88
- // <div className="w-full h-full flex items-center justify-center text-muted-foreground">
89
- // Select a run to view the path graph
90
- // </div>
91
- // );
92
- // }
93
 
94
  return (
95
  <div className="w-full h-full flex items-center justify-center">
96
  <div ref={containerRef} className="w-full h-full">
97
  <ForceGraph2D
 
98
  graphData={graphData}
99
  nodeLabel="id"
100
  linkLabel="id"
101
  nodeColor="color"
102
- linkColor="gray"
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
103
  width={dimensions.width}
104
  height={dimensions.height}
105
  />
 
1
  "use client";
2
 
3
  import { useEffect, useRef, useState } from "react";
4
+ import ForceGraph2D, { ForceGraphMethods, LinkObject, NodeObject } from "react-force-graph-2d";
5
  import { Run } from "./reasoning-trace";
6
+ import * as d3 from "d3";
7
  // This is a placeholder component for the force-directed graph
8
  // In a real implementation, you would use a library like D3.js or react-force-graph
9
 
 
13
  }
14
 
15
  export default function ForceDirectedGraph({runs, runId }: ForceDirectedGraphProps) {
16
+ const [graphData, setGraphData] = useState<{nodes: {id: string, color?: string}[], links: {source: string, target: string, color?: string}[]}>({nodes: [], links: []});
17
+ const [dimensions, setDimensions] = useState({ width: 800, height: 800 });
18
  const containerRef = useRef<HTMLDivElement>(null);
19
+ const graphRef = useRef<ForceGraphMethods<NodeObject<{ id: string; color?: string; }>, LinkObject<{ id: string; color?: string; }, { source: string; target: string; color?: string; }>>>(null);
20
  useEffect(() => {
21
 
22
+ const newGraphData: {nodes: {id: string, color?: string}[], links: {source: string, target: string, color?: string}[]} = {nodes: [], links: []};
23
  const nodesSet: Set<string> = new Set();
24
  const mainNodeSet: Set<string> = new Set();
25
 
26
  if(runs) {
27
+ runs.forEach((run, runIndex) => {
28
  // add in src and dst to nodes
29
+ const isSelectedRun = runId === runIndex;
30
 
31
  mainNodeSet.add(run.start_article);
32
  mainNodeSet.add(run.destination_article);
 
43
  nodesSet.add(nextStep.article);
44
  }
45
 
46
+ newGraphData.links.push({
47
+ source: step.article,
48
+ target: nextStep.article,
49
+ color: isSelectedRun ? '#ff6b6b' : 'gray'
50
+ });
51
  }
52
 
53
  const mainNodes = Array.from(mainNodeSet);
54
+ const radius = 400; // Radius of the circle
55
+ const centerX = 0; // Center X coordinate
56
+ const centerY = 0; // Center Y coordinate
57
 
58
  newGraphData.nodes = mainNodes.map((id, index) => {
59
  const angle = (index * 2 * Math.PI) / mainNodes.length;
 
61
  id,
62
  fx: centerX + radius * Math.cos(angle),
63
  fy: centerY + radius * Math.sin(angle),
64
+ color: isSelectedRun && (id === run.start_article || id === run.destination_article) ? '#ff6b6b' : 'red'
65
  };
66
  });
67
+ newGraphData.nodes.push(...Array.from(nodesSet).map((id) => ({
68
+ id,
69
+ color: isSelectedRun && run.steps.some(step => step.article === id) ? '#ff6b6b' : 'gray'
70
+ })));
71
  });
72
 
73
  setGraphData(newGraphData);
74
  }
75
+ }, [runs, runId]);
76
+
77
+ useEffect(() => {
78
+ if (graphRef.current) {
79
+ const radialForceStrength = 0.7;
80
+ const radialTargetRadius = 40; // Increased radius to allow more space
81
+ const linkDistance = 35; // Keep links relatively short
82
+ const chargeStrength = -100; // Increase repulsion more
83
+ const COLLISION_PADDING = 3;
84
+
85
+
86
+ // graphRef.current.centerAt(400, 400);
87
+ graphRef.current.zoomToFit();
88
+
89
+ graphRef.current.d3Force("link", d3.forceLink(graphData.links).id((d) => d.id).distance(linkDistance).strength(0.9));
90
+ graphRef.current.d3Force("charge", d3.forceManyBody().strength(chargeStrength));
91
+ graphRef.current.d3Force("radial", d3.forceRadial(radialTargetRadius, 0, 0).strength(radialForceStrength));
92
+ graphRef.current.d3Force("collide", d3.forceCollide().radius((d) => d.radius + COLLISION_PADDING));
93
+
94
+ }
95
+ }, [graphRef]);
96
+
 
 
 
 
97
 
98
  return (
99
  <div className="w-full h-full flex items-center justify-center">
100
  <div ref={containerRef} className="w-full h-full">
101
  <ForceGraph2D
102
+ ref={graphRef}
103
  graphData={graphData}
104
  nodeLabel="id"
105
  linkLabel="id"
106
  nodeColor="color"
107
+ linkColor="color"
108
+ nodeCanvasObject={(node, ctx, globalScale) => {
109
+ const label = node.id;
110
+ const fontSize = 12/globalScale;
111
+ ctx.font = `${fontSize}px Sans-Serif`;
112
+ const textWidth = ctx.measureText(label).width;
113
+ const bckgDimensions = [textWidth, fontSize].map(n => n + fontSize * 0.2);
114
+
115
+ // Draw node circle
116
+ ctx.beginPath();
117
+ ctx.arc(node.x!, node.y!, 5, 0, 2 * Math.PI);
118
+ ctx.fillStyle = node.color || 'gray';
119
+ ctx.fill();
120
+
121
+ if(node.color === "red") {
122
+ // Draw label background
123
+ ctx.fillStyle = 'rgba(255, 255, 255, 0.8)';
124
+ ctx.fillRect(
125
+ node.x! - bckgDimensions[0] / 2,
126
+ node.y! + 8,
127
+ bckgDimensions[0],
128
+ bckgDimensions[1]
129
+ );
130
+
131
+ // Draw label text
132
+ ctx.textAlign = 'center';
133
+ ctx.textBaseline = 'middle';
134
+ ctx.fillStyle = 'black';
135
+ ctx.fillText(
136
+ label,
137
+ node.x!,
138
+ node.y! + 8 + fontSize / 2
139
+ );
140
+ }
141
+ }}
142
  width={dimensions.width}
143
  height={dimensions.height}
144
  />
src/components/viewer-tab.tsx CHANGED
@@ -3,9 +3,9 @@
3
  import * as hub from "@huggingface/hub";
4
  import type { RepoDesignation } from "@huggingface/hub";
5
 
6
- // import mockResults from "../../qwen3-final-results.json";
7
 
8
- import { useState } from "react";
9
  import {
10
  Select,
11
  SelectContent,
@@ -26,15 +26,6 @@ type Run = {
26
  hops: number;
27
  };
28
 
29
- // Sample data - would be fetched from HuggingFace dataset in a real implementation
30
- const sampleRuns = [
31
- { id: 1, start: "Pokemon", end: "Canada", hops: 16 },
32
- { id: 2, start: "Pokemon", end: "Canada", hops: 16 },
33
- { id: 3, start: "Pokemon", end: "Canada", hops: 16 },
34
- { id: 4, start: "Pokemon", end: "Canada", hops: 16 },
35
- // Add more sample runs as needed
36
- ];
37
-
38
  const datasets = [
39
  { id: "dataset1", name: "Eureka-Lab/PHYBench" },
40
  { id: "dataset2", name: "Eureka-Lab/PHYBench-LLM" },
@@ -48,8 +39,8 @@ export default function ViewerTab() {
48
 
49
  const fetchDataset = async () => {
50
  console.log("Fetching dataset...");
51
- // console.log(Object.keys(mockResults));
52
- // setRuns(mockResults.runs.slice(0, 10));
53
 
54
  return;
55
  setLoading(true);
@@ -85,6 +76,10 @@ export default function ViewerTab() {
85
  setSelectedRun(runId);
86
  };
87
 
 
 
 
 
88
  return (
89
  <div className="grid grid-cols-1 md:grid-cols-12 gap-4">
90
  <div className="md:col-span-3">
@@ -118,16 +113,16 @@ export default function ViewerTab() {
118
  </div>
119
 
120
  <div className="md:col-span-5">
121
- <Card className="w-full h-[600px] flex items-center justify-center">
122
- <ForceDirectedGraph runs={runs} runId={selectedRun} />
123
  </Card>
124
  </div>
125
 
126
- <div className="md:col-span-4">
127
  <Card className="w-full h-[600px] p-4">
128
  <ReasoningTrace run={runs[selectedRun]} />
129
  </Card>
130
- </div>
131
  </div>
132
  );
133
  }
 
3
  import * as hub from "@huggingface/hub";
4
  import type { RepoDesignation } from "@huggingface/hub";
5
 
6
+ import mockResults from "../../qwen3-final-results.json"
7
 
8
+ import { useMemo, useState } from "react";
9
  import {
10
  Select,
11
  SelectContent,
 
26
  hops: number;
27
  };
28
 
 
 
 
 
 
 
 
 
 
29
  const datasets = [
30
  { id: "dataset1", name: "Eureka-Lab/PHYBench" },
31
  { id: "dataset2", name: "Eureka-Lab/PHYBench-LLM" },
 
39
 
40
  const fetchDataset = async () => {
41
  console.log("Fetching dataset...");
42
+ console.log(Object.keys(mockResults));
43
+ setRuns(mockResults.runs.slice(0, 1000));
44
 
45
  return;
46
  setLoading(true);
 
76
  setSelectedRun(runId);
77
  };
78
 
79
+ const filterRuns = useMemo(() => {
80
+ return runs.filter(run => run.result === "win");
81
+ }, [runs]);
82
+
83
  return (
84
  <div className="grid grid-cols-1 md:grid-cols-12 gap-4">
85
  <div className="md:col-span-3">
 
113
  </div>
114
 
115
  <div className="md:col-span-5">
116
+ <Card className="h-[800px] w-[800px] flex items-center justify-center p-0 m-0">
117
+ <ForceDirectedGraph runs={filterRuns} runId={selectedRun} />
118
  </Card>
119
  </div>
120
 
121
+ {/* <div className="md:col-span-4">
122
  <Card className="w-full h-[600px] p-4">
123
  <ReasoningTrace run={runs[selectedRun]} />
124
  </Card>
125
+ </div> */}
126
  </div>
127
  );
128
  }