profileShare

rasmusjy / roundtable

Read-only snapshot

No repository description.

main default branch 181 files Expires Sep 13, 2026, 9:06 AM
synthesis.ts 2,736 bytes
1 import type { AnonymizedPeer } from '../anonymize';
2 import type { LlmMessage } from '../llm-client';
3 import { jsonInstruction, ROUNDTABLE_PREAMBLE } from './index';
4
5 const SYNTHESIS_SHAPE = `{
6 "finalAnswer": "the single best answer to the question, synthesized from the council",
7 "dissent": [
8 {
9 "topic": "short label for an unresolved disagreement",
10 "positions": [
11 { "label": "A", "position": "what response A maintains" },
12 { "label": "B", "position": "what response B maintains" }
13 ]
14 }
15 ]
16 }`;
17
18 /**
19 * Chairman synthesis (final stage).
20 *
21 * The chairman receives the anonymized final answers, the outstanding
22 * disagreements from the convergence check, and produces the authoritative
23 * answer plus an explicit dissent report. Answers are anonymized to the chairman
24 * as well - this is deliberate self-preference mitigation: even a chairman drawn
25 * from the same provider family as a council member cannot favor "its own"
26 * answer if it cannot identify it. Labels are mapped back to real models only
27 * after the chairman has committed its judgment.
28 */
29 export function buildSynthesisPrompt(
30 question: string,
31 finalAnswers: AnonymizedPeer[],
32 remainingDisagreements: Array<{ topic: string; summary: string }>,
33 ): LlmMessage[] {
34 const answersBlock = finalAnswers
35 .map((a) => `--- Response ${a.label} ---\n${a.content}`)
36 .join('\n\n');
37
38 const disagreementBlock =
39 remainingDisagreements.length === 0
40 ? 'The council largely converged; no major disagreements were flagged.'
41 : remainingDisagreements.map((d) => `- ${d.topic}: ${d.summary}`).join('\n');
42
43 return [
44 {
45 role: 'system',
46 content:
47 'You are the chairman of an expert roundtable. Several anonymized experts have ' +
48 'answered a question and revised their answers after mutual critique. Your job ' +
49 'is to deliver the single best final answer and an honest dissent report.\n\n' +
50 `${ROUNDTABLE_PREAMBLE}\n\n` +
51 'Synthesize - do not merely pick one answer or average them. Take the strongest, ' +
52 'best-supported reasoning from across the council. Where the council genuinely ' +
53 'disagrees and the evidence does not settle it, do NOT paper over it: record it ' +
54 "in the dissent report with each side's position. The responses are anonymized; " +
55 'judge only on merit.\n\n' +
56 jsonInstruction(SYNTHESIS_SHAPE),
57 },
58 {
59 role: 'user',
60 content:
61 `Question:\n${question}\n\n` +
62 `Final answers from the council:\n\n${answersBlock}\n\n` +
63 `Points still in dispute after deliberation:\n${disagreementBlock}\n\n` +
64 'Return your JSON synthesis now.',
65 },
66 ];
67 }
68