ping98k commited on
Commit
4656699
·
1 Parent(s): ec160fc

Enhance heatmap event handling by incorporating search group functionality, allowing users to specify a search group for improved similarity calculations and visualization in the heatmap.

Browse files
Files changed (1) hide show
  1. heatmap_event.js +43 -23
heatmap_event.js CHANGED
@@ -58,17 +58,18 @@ export async function handleHeatmapEvent() {
58
  progressBarInner.style.width = "0%";
59
 
60
  const text = document.getElementById("input").value;
 
 
61
  // Get search sort mode from dropdown (either 'line' or 'group')
62
  const searchSortMode = document.getElementById("search-sort-mode")?.value || "group";
63
  const search_by_max_search_line = searchSortMode === "line";
64
  const search_by_max_search_group = searchSortMode === "group";
65
 
66
- // Find the index of the search cluster (case-insensitive, looks for 'search' in header)
67
  const clusterNames = text.split(/\n/)
68
  .map(x => x.trim())
69
  .filter(x => x && x.startsWith('##'))
70
  .map(x => x.replace(/^##\s*/, ''));
71
- let searchIdx = clusterNames.findIndex(name => name.toLowerCase().includes('search'));
72
 
73
  const groups = text.split(/\n{3,}/);
74
  // Get group embeddings (removes ## lines internally)
@@ -91,53 +92,72 @@ export async function handleHeatmapEvent() {
91
  sim.push(row);
92
  }
93
  progressBarInner.style.width = "60%";
94
- // Reorder clusters if search cluster is found, otherwise keep original order
95
  // Always use all group indices in order
96
  let order = Array.from({ length: n }, (_, i) => i);
97
- if (searchIdx !== -1) {
98
- // Compute similarity to search cluster and sort others by similarity
99
- const simToSearch = sim[searchIdx].map((v, i) => ({ idx: i, sim: v }));
100
- // Exclude searchIdx from sorting
101
- const others = simToSearch.filter(x => x.idx !== searchIdx);
102
- others.sort((a, b) => b.sim - a.sim); // descending similarity
103
- order = [searchIdx, ...others.map(x => x.idx)];
 
 
 
 
 
 
 
 
 
 
 
104
  }
105
  // Reorder sim matrix and clusterNames for heatmap visualization
106
- const simOrdered = order.map(i => order.map(j => sim[i][j]));
107
- const xLabels = order.map(i => (clusterNames && clusterNames[i]) ? clusterNames[i] : `Group ${i + 1}`);
 
 
 
 
 
 
 
 
 
 
108
  plotHeatmap(simOrdered, xLabels, xLabels);
109
 
110
- // If search cluster is found and sorting by line, reorder lines in each group by similarity to search lines
111
- if (searchIdx !== -1 && search_by_max_search_line) {
112
- const searchLines = getCleanGroups(groups)[searchIdx];
113
- const searchEmbeds = await getLineEmbeddings(searchLines, task);
114
  const cleanGroups = getCleanGroups(groups);
115
  const { allLines, allEmbeds } = await getAllLinesAndEmbeds(cleanGroups, task);
116
  const idxByGroup = getIdxByGroup(cleanGroups);
117
  const score = e => Math.max(...searchEmbeds.map(se => cosine(se, e)));
118
- const sorted = order.map(g =>
 
119
  idxByGroup[g]
120
  .map(i => ({ t: allLines[i], s: score(allEmbeds[i]) }))
121
  .sort((a, b) => b.s - a.s)
122
  .map(o => o.t)
123
  );
124
- const finalText = buildFinalText(order, sorted, clusterNames, n);
125
  document.getElementById("input").value = finalText;
126
  }
127
 
128
- // If search cluster is found and sorting by group, reorder lines in each group by similarity to the search group embedding
129
- if (searchIdx !== -1 && search_by_max_search_group) {
130
- const refEmbed = groupEmbeddings[searchIdx];
131
  const cleanGroups = getCleanGroups(groups);
132
  const { allLines, allEmbeds } = await getAllLinesAndEmbeds(cleanGroups, task);
133
  const idxByGroup = getIdxByGroup(cleanGroups);
134
- const sortedLines = order.map(gIdx =>
 
135
  idxByGroup[gIdx]
136
  .map(i => ({ t: allLines[i], s: cosine(refEmbed, allEmbeds[i]) }))
137
  .sort((a, b) => b.s - a.s)
138
  .map(o => o.t)
139
  );
140
- const finalText = buildFinalText(order, sortedLines, clusterNames, n);
141
  document.getElementById("input").value = finalText;
142
  }
143
  progressBarInner.style.width = "100%";
 
58
  progressBarInner.style.width = "0%";
59
 
60
  const text = document.getElementById("input").value;
61
+ // Get search group from dedicated input (do not use ##search in main input)
62
+ const searchGroupText = document.getElementById("search-group-input")?.value.trim();
63
  // Get search sort mode from dropdown (either 'line' or 'group')
64
  const searchSortMode = document.getElementById("search-sort-mode")?.value || "group";
65
  const search_by_max_search_line = searchSortMode === "line";
66
  const search_by_max_search_group = searchSortMode === "group";
67
 
68
+ // Parse cluster names from main input (ignore any ##search)
69
  const clusterNames = text.split(/\n/)
70
  .map(x => x.trim())
71
  .filter(x => x && x.startsWith('##'))
72
  .map(x => x.replace(/^##\s*/, ''));
 
73
 
74
  const groups = text.split(/\n{3,}/);
75
  // Get group embeddings (removes ## lines internally)
 
92
  sim.push(row);
93
  }
94
  progressBarInner.style.width = "60%";
 
95
  // Always use all group indices in order
96
  let order = Array.from({ length: n }, (_, i) => i);
97
+
98
+ // Only use search group if provided in search-group-input
99
+ let useSearchGroup = !!searchGroupText;
100
+ let searchIdx = -1;
101
+ let searchLines = [];
102
+ let searchEmbeds = [];
103
+ let refEmbed = null;
104
+ if (useSearchGroup) {
105
+ searchLines = searchGroupText.split(/\n/).map(l => l.trim()).filter(l => l);
106
+ if (searchLines.length > 0) {
107
+ searchEmbeds = await getLineEmbeddings(searchLines, task);
108
+ // For group similarity, use the mean embedding of the search group
109
+ refEmbed = searchEmbeds[0].map((_, i) => searchEmbeds.reduce((sum, e) => sum + e[i], 0) / searchEmbeds.length);
110
+ // Compute similarity to each group
111
+ const simToSearch = groupEmbeddings.map((emb, i) => ({ idx: i, sim: cosine(refEmbed, emb) }));
112
+ simToSearch.sort((a, b) => b.sim - a.sim);
113
+ order = [/* search group is not in groupEmbeddings, so just prepend -1 for heatmap */ -1, ...simToSearch.map(x => x.idx)];
114
+ }
115
  }
116
  // Reorder sim matrix and clusterNames for heatmap visualization
117
+ let simOrdered, xLabels;
118
+ if (useSearchGroup && searchLines.length > 0) {
119
+ // Insert search group as first row/col in heatmap, with similarity 1 to itself and to other groups
120
+ simOrdered = [
121
+ [1, ...order.slice(1).map(idx => idx === -1 ? 1 : cosine(refEmbed, groupEmbeddings[idx]))],
122
+ ...order.slice(1).map(i => [cosine(refEmbed, groupEmbeddings[i]), ...order.slice(1).map(j => sim[i][j])])
123
+ ];
124
+ xLabels = ["Search Group", ...order.slice(1).map(i => (clusterNames && clusterNames[i]) ? clusterNames[i] : `Group ${i + 1}`)];
125
+ } else {
126
+ simOrdered = order.map(i => order.map(j => sim[i][j]));
127
+ xLabels = order.map(i => (clusterNames && clusterNames[i]) ? clusterNames[i] : `Group ${i + 1}`);
128
+ }
129
  plotHeatmap(simOrdered, xLabels, xLabels);
130
 
131
+ // If search group is provided and sorting by line, reorder lines in each group by similarity to search lines
132
+ if (useSearchGroup && search_by_max_search_line && searchEmbeds.length > 0) {
 
 
133
  const cleanGroups = getCleanGroups(groups);
134
  const { allLines, allEmbeds } = await getAllLinesAndEmbeds(cleanGroups, task);
135
  const idxByGroup = getIdxByGroup(cleanGroups);
136
  const score = e => Math.max(...searchEmbeds.map(se => cosine(se, e)));
137
+ // Skip -1 (search group) in order for main input reordering
138
+ const sorted = (order[0] === -1 ? order.slice(1) : order).map(g =>
139
  idxByGroup[g]
140
  .map(i => ({ t: allLines[i], s: score(allEmbeds[i]) }))
141
  .sort((a, b) => b.s - a.s)
142
  .map(o => o.t)
143
  );
144
+ const finalText = buildFinalText(order[0] === -1 ? order.slice(1) : order, sorted, clusterNames, n);
145
  document.getElementById("input").value = finalText;
146
  }
147
 
148
+ // If search group is provided and sorting by group, reorder lines in each group by similarity to the search group embedding
149
+ if (useSearchGroup && search_by_max_search_group && refEmbed) {
 
150
  const cleanGroups = getCleanGroups(groups);
151
  const { allLines, allEmbeds } = await getAllLinesAndEmbeds(cleanGroups, task);
152
  const idxByGroup = getIdxByGroup(cleanGroups);
153
+ // Skip -1 (search group) in order for main input reordering
154
+ const sortedLines = (order[0] === -1 ? order.slice(1) : order).map(gIdx =>
155
  idxByGroup[gIdx]
156
  .map(i => ({ t: allLines[i], s: cosine(refEmbed, allEmbeds[i]) }))
157
  .sort((a, b) => b.s - a.s)
158
  .map(o => o.t)
159
  );
160
+ const finalText = buildFinalText(order[0] === -1 ? order.slice(1) : order, sortedLines, clusterNames, n);
161
  document.getElementById("input").value = finalText;
162
  }
163
  progressBarInner.style.width = "100%";