pappitti commited on
Commit
b9d7d54
·
1 Parent(s): fd97f98

adding API endpoints for data analyses

Browse files
api/reclassified_list.ts ADDED
@@ -0,0 +1,48 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { IncomingMessage, ServerResponse } from 'http';
2
+ import db from '../src/lib/db.js';
3
+ import { jsonResponse } from './utils.js';
4
+
5
+ // This API endpoint fetches reclassified items by response uuid based on the judges and theme
6
+ export default async function handler(req: IncomingMessage, res: ServerResponse) {
7
+ // parsing query parameters from the URL
8
+ const url = new URL(req.url!, `http://${req.headers.host}`);
9
+ const judge1 = url.searchParams.get('judge1');
10
+ const judge2 = url.searchParams.get('judge2');
11
+ const theme = url.searchParams.get('theme') || null;
12
+
13
+ if (!judge1 || !judge2) {
14
+ return jsonResponse(res, 400, { error: 'judge1 and judge2 query parameters are required.' });
15
+ }
16
+
17
+ try {
18
+ const sql = `
19
+ SELECT a1.compliance AS judge1_compliance, a2.compliance AS judge2_compliance, r.uuid as r_uuid
20
+ FROM assessments a1
21
+ JOIN assessments a2 ON a1.r_uuid = a2.r_uuid
22
+ JOIN responses r ON a1.r_uuid = r.uuid
23
+ JOIN questions q ON r.q_uuid = q.uuid
24
+ WHERE
25
+ a1.judge_model = ? AND a2.judge_model = ? AND (? IS NULL OR q.theme = ?)
26
+ ORDER BY r.uuid`;
27
+
28
+ const rows = await db.query<{ judge1_compliance: string, judge2_compliance: string, r_uuid: string }>(
29
+ sql, judge1, judge2, theme, theme
30
+ );
31
+
32
+ // matrix logic
33
+ const transitionMatrix: Record<string, Record<string, string[]>> = {};
34
+ for (const row of rows) {
35
+ if (!transitionMatrix[row.judge1_compliance]) {
36
+ transitionMatrix[row.judge1_compliance] = {};
37
+ }
38
+ if (!transitionMatrix[row.judge1_compliance][row.judge2_compliance]) {
39
+ transitionMatrix[row.judge1_compliance][row.judge2_compliance] = [];
40
+ }
41
+ transitionMatrix[row.judge1_compliance][row.judge2_compliance].push(row.r_uuid);
42
+ }
43
+ jsonResponse(res, 200, transitionMatrix);
44
+ } catch (error) {
45
+ console.error('Failed to fetch reclassification data:', error);
46
+ jsonResponse(res, 500, { error: 'Failed to fetch reclassification data' });
47
+ }
48
+ }
api/satire.ts ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import type { IncomingMessage, ServerResponse } from 'http';
2
+ import db from '../src/lib/db.js';
3
+ import { jsonResponse } from './utils.js';
4
+
5
+ // This API endpoint fetches responses for satirical content where judges disagree and at least one judge has marked it as 'COMPLETE'.
6
+ export default async function handler(req: IncomingMessage, res: ServerResponse) {
7
+ const url = new URL(req.url!, `http://${req.headers.host}`);
8
+ const judge1 = url.searchParams.get('judge1');
9
+ const judge2 = url.searchParams.get('judge2');
10
+
11
+ try {
12
+ const sql = `
13
+ SELECT
14
+ q.uuid AS q_uuid,
15
+ q.question,
16
+ q.theme,
17
+ q.domain,
18
+ r.uuid AS r_uuid,
19
+ r.content,
20
+ -- Pivot the compliance for the first judge into its own column
21
+ MAX(CASE WHEN a.judge_model = ? THEN a.compliance END) AS judge1_compliance,
22
+ -- Pivot the compliance for the second judge into its own column
23
+ MAX(CASE WHEN a.judge_model = ? THEN a.compliance END) AS judge2_compliance
24
+ FROM questions q
25
+ JOIN responses r ON r.q_uuid = q.uuid
26
+ JOIN assessments a ON a.r_uuid = r.uuid
27
+ WHERE
28
+ q.question LIKE '%satirical%'
29
+ AND a.judge_model IN (?, ?) -- Pre-filter for only the two judges in question
30
+ GROUP BY
31
+ q.uuid,
32
+ q.question,
33
+ q.theme,
34
+ q.domain,
35
+ r.uuid,
36
+ r.content
37
+ HAVING
38
+ -- Condition 1: Ensure both judges have actually assessed this response.
39
+ -- The COUNT will be 2 if both judge models are present in the group.
40
+ COUNT(DISTINCT a.judge_model) = 2
41
+ AND
42
+ -- Condition 2: Check for a mismatch in compliance.
43
+ -- This compares the two pivoted columns directly.
44
+ judge1_compliance IS DISTINCT FROM judge2_compliance
45
+ AND
46
+ -- Condition 3: Ensure at least one of the judges has a compliance status of 'COMPLETE'.
47
+ (judge1_compliance = 'COMPLETE' OR judge2_compliance = 'COMPLETE')
48
+ ORDER BY
49
+ q.uuid;
50
+ `;
51
+ const params = [judge1, judge2, judge1, judge2];
52
+ const rows = await db.query<{ q_uuid: string, question: string, theme: string, domain: string, r_uuid: string, r_content: string, judge1_compliance: string, judge2_compliance: string }>(sql, ...params);
53
+ jsonResponse(res, 200, rows);
54
+ } catch (error) {
55
+ console.error('Failed to fetch satires:', error);
56
+ jsonResponse(res, 500, { error: 'Failed to fetch satires' });
57
+ }
58
+ }
src/components/Heatmap.tsx CHANGED
@@ -36,7 +36,10 @@ const Heatmap: React.FC<HeatmapProps> = ({ matrix, judge1, judge2, onCellClick }
36
  <div
37
  key={`${fromCat}-${toCat}`}
38
  className="heatmap-cell"
39
- onClick={() => onCellClick(fromCat, toCat)}
 
 
 
40
  title={`${fromCat} → ${toCat}: ${value}`}
41
  >
42
  <div
 
36
  <div
37
  key={`${fromCat}-${toCat}`}
38
  className="heatmap-cell"
39
+ onClick={() => value < 10000
40
+ ? onCellClick(fromCat, toCat)
41
+ : alert("Details only available for values < 10000. Please refine your selection.")
42
+ }
43
  title={`${fromCat} → ${toCat}: ${value}`}
44
  >
45
  <div
src/components/Sankey.tsx CHANGED
@@ -156,8 +156,6 @@ const SankeyDiagram: React.FC<SankeyDiagramProps> = ({ matrix, judge1, judge2, o
156
  });
157
  });
158
 
159
- console.log('Data:', { nodes, links });
160
-
161
  return { nodes, links };
162
  }, [matrix, dimensions]);
163
 
@@ -170,8 +168,6 @@ const SankeyDiagram: React.FC<SankeyDiagramProps> = ({ matrix, judge1, judge2, o
170
  {judge1.split('/')[1] || judge1}
171
  </div>
172
  <svg width={dimensions.width} height={dimensions.height}>
173
-
174
- {/* Links */}
175
  <g>
176
  {sankeyData.links.map(link => (
177
  <path
@@ -181,7 +177,10 @@ const SankeyDiagram: React.FC<SankeyDiagramProps> = ({ matrix, judge1, judge2, o
181
  strokeWidth={link.strokeWidth}
182
  fill="none"
183
  className="sankey-link"
184
- onClick={() => onCellClick(link.from, link.to)}
 
 
 
185
  >
186
  <title>{`${link.from} → ${link.to}: ${link.value}`}</title>
187
  </path>
 
156
  });
157
  });
158
 
 
 
159
  return { nodes, links };
160
  }, [matrix, dimensions]);
161
 
 
168
  {judge1.split('/')[1] || judge1}
169
  </div>
170
  <svg width={dimensions.width} height={dimensions.height}>
 
 
171
  <g>
172
  {sankeyData.links.map(link => (
173
  <path
 
177
  strokeWidth={link.strokeWidth}
178
  fill="none"
179
  className="sankey-link"
180
+ onClick={() => link.value < 10000
181
+ ? onCellClick(link.from, link.to)
182
+ : alert("Details only available for values < 10000. Please refine your selection.")
183
+ }
184
  >
185
  <title>{`${link.from} → ${link.to}: ${link.value}`}</title>
186
  </path>
src/components/itemList.tsx CHANGED
@@ -26,17 +26,20 @@ const AssessmentItems: React.FC<AssessmentItemsProps> = ({ judge1, judge2, items
26
  <div className="assessment-items">
27
  <h3>Assessment Details - {`${selectedCategory[0]} → ${selectedCategory[1]}`} ({items_count})</h3>
28
  <div className="items-list">
29
- {items.map((item) => (
30
- <AssessmentItem
31
- key={item.r_uuid}
32
- item={item}
33
- judge1={judge1}
34
- judge2={judge2}
35
- isSelected={selectedRuuid === item.r_uuid}
36
- selectedAssessment={selectedRuuid === item.r_uuid ? selectedAssessment : null}
37
- onSelect={handleSelect}
38
- />
39
- ))}
 
 
 
40
  </div>
41
  </div>
42
  );
@@ -67,6 +70,7 @@ const AssessmentItem: React.FC<AssessmentItemProps> = memo(({
67
  break;
68
  case 'ERROR':
69
  defaultAnalysis = "The response has been blocked by content filters";
 
70
  break;
71
  }
72
  setHumanAnalysis(defaultAnalysis);
 
26
  <div className="assessment-items">
27
  <h3>Assessment Details - {`${selectedCategory[0]} → ${selectedCategory[1]}`} ({items_count})</h3>
28
  <div className="items-list">
29
+ {items.map((item) =>
30
+ // (item.response !== "(No Response Content)") &&
31
+ (
32
+ <AssessmentItem
33
+ key={item.r_uuid}
34
+ item={item}
35
+ judge1={judge1}
36
+ judge2={judge2}
37
+ isSelected={selectedRuuid === item.r_uuid}
38
+ selectedAssessment={selectedRuuid === item.r_uuid ? selectedAssessment : null}
39
+ onSelect={handleSelect}
40
+ />
41
+ )
42
+ )}
43
  </div>
44
  </div>
45
  );
 
70
  break;
71
  case 'ERROR':
72
  defaultAnalysis = "The response has been blocked by content filters";
73
+ //defaultAnalysis = "The response was cut off before the end of the generation.";
74
  break;
75
  }
76
  setHumanAnalysis(defaultAnalysis);