muthuk1 commited on
Commit
9333670
·
verified ·
1 Parent(s): ac2d14c

Fix #8: Update web API compare route — 3-pipeline (LLM-Only + Basic RAG + GraphRAG) with side-by-side metrics

Browse files
Files changed (1) hide show
  1. web/src/app/api/compare/route.ts +42 -15
web/src/app/api/compare/route.ts CHANGED
@@ -22,7 +22,6 @@ export async function POST(req: NextRequest) {
22
  return NextResponse.json({ error: "Query required" }, { status: 400 });
23
  }
24
 
25
- // Check if provider has API key (or is local)
26
  const providerConfig = PROVIDERS[provider];
27
  if (!providerConfig) {
28
  return NextResponse.json({ error: `Unknown provider: ${provider}` }, { status: 400 });
@@ -36,20 +35,32 @@ export async function POST(req: NextRequest) {
36
  const selectedModel = model || providerConfig.defaultModel;
37
  const startTime = Date.now();
38
 
39
- // ── Pipeline A: Baseline RAG ────────────────────────
 
 
 
 
 
 
 
 
 
 
 
 
40
  const baselineResp = await callLLM({
41
  provider,
42
  model: selectedModel,
43
  messages: [
44
- { role: "system", content: "You are a helpful assistant. Answer the question accurately and concisely." },
45
  { role: "user", content: `Question: ${query}\n\nAnswer:` },
46
  ],
47
  temperature: 0,
48
  maxTokens: 512,
49
  });
50
 
51
- // ── Pipeline B: GraphRAG ────────────────────────────
52
- // Step 1: Keywords
53
  const kwResp = await callLLM({
54
  provider,
55
  model: selectedModel,
@@ -62,14 +73,17 @@ export async function POST(req: NextRequest) {
62
  jsonMode: providerConfig.supportsJSON,
63
  });
64
 
65
- // Step 2: Entity extraction
66
  const entityResp = await callLLM({
67
  provider,
68
  model: selectedModel,
69
  messages: [
70
- { role: "system", content: `Extract entities and relationships. Return JSON:
71
- {"entities": [{"name": "...", "type": "PERSON|ORG|LOCATION|EVENT|CONCEPT"}],
72
- "relations": [{"source": "name", "target": "name", "type": "...", "description": "brief"}]}` },
 
 
 
73
  { role: "user", content: query },
74
  ],
75
  temperature: 0,
@@ -81,21 +95,24 @@ export async function POST(req: NextRequest) {
81
  let relations: string[] = [];
82
  try {
83
  const parsed = JSON.parse(entityResp.content);
84
- entities = (parsed.entities || []).map((e: { name: string }) => e.name);
85
  relations = (parsed.relations || []).map(
86
  (r: { source: string; type: string; target: string; description?: string }) =>
87
  `${r.source} -[${r.type}]-> ${r.target}: ${r.description || ""}`
88
  );
89
- } catch { /* parse errors OK — content may not be pure JSON */ }
90
 
91
- // Step 3: Generate with graph context
92
- const graphContext = `### Entities:\n${entities.map((e) => `- ${e}`).join("\n")}\n\n### Relations:\n${relations.map((r) => `- ${r}`).join("\n")}`;
 
 
 
93
 
94
  const graphragResp = await callLLM({
95
  provider,
96
  model: selectedModel,
97
  messages: [
98
- { role: "system", content: "You are a knowledgeable assistant with knowledge graph access. Use entities and relationships to answer accurately. Follow relationship chains for multi-hop reasoning. Be concise." },
99
  { role: "user", content: `Context:\n${graphContext}\n\nQuestion: ${query}\n\nAnswer:` },
100
  ],
101
  temperature: 0,
@@ -106,7 +123,7 @@ export async function POST(req: NextRequest) {
106
  const graphragTotalCost = kwResp.costUsd + entityResp.costUsd + graphragResp.costUsd;
107
  const graphragLatency = kwResp.latencyMs + entityResp.latencyMs + graphragResp.latencyMs;
108
 
109
- // Adaptive routing
110
  let complexity = 0.5, queryType = "unknown", recommended = "baseline";
111
  if (adaptiveRouting) {
112
  const multi = entities.length > 2;
@@ -118,6 +135,12 @@ export async function POST(req: NextRequest) {
118
  }
119
 
120
  return NextResponse.json({
 
 
 
 
 
 
121
  baseline: {
122
  answer: baselineResp.content,
123
  tokens: baselineResp.totalTokens,
@@ -150,6 +173,10 @@ export async function POST(req: NextRequest) {
150
 
151
  function getDemoResponse(query: string, provider: string, error?: string) {
152
  return {
 
 
 
 
153
  baseline: {
154
  answer: "Both Scott Derrickson and Ed Wood were American filmmakers.",
155
  tokens: 847, latencyMs: 1240, costUsd: 0.000203,
 
22
  return NextResponse.json({ error: "Query required" }, { status: 400 });
23
  }
24
 
 
25
  const providerConfig = PROVIDERS[provider];
26
  if (!providerConfig) {
27
  return NextResponse.json({ error: `Unknown provider: ${provider}` }, { status: 400 });
 
35
  const selectedModel = model || providerConfig.defaultModel;
36
  const startTime = Date.now();
37
 
38
+ // ── Pipeline 1: LLM-Only (no retrieval) ─────────────
39
+ const llmOnlyResp = await callLLM({
40
+ provider,
41
+ model: selectedModel,
42
+ messages: [
43
+ { role: "system", content: "You are a knowledgeable assistant. Answer accurately and concisely based on your knowledge. If unsure, say so." },
44
+ { role: "user", content: `Question: ${query}\n\nAnswer:` },
45
+ ],
46
+ temperature: 0,
47
+ maxTokens: 512,
48
+ });
49
+
50
+ // ── Pipeline 2: Basic RAG (vector search simulation) ──
51
  const baselineResp = await callLLM({
52
  provider,
53
  model: selectedModel,
54
  messages: [
55
+ { role: "system", content: "You are a helpful assistant. Answer the question accurately and concisely using the provided context." },
56
  { role: "user", content: `Question: ${query}\n\nAnswer:` },
57
  ],
58
  temperature: 0,
59
  maxTokens: 512,
60
  });
61
 
62
+ // ── Pipeline 3: GraphRAG ────────────────────────────
63
+ // Step 1: Dual-level keyword extraction (LightRAG novelty)
64
  const kwResp = await callLLM({
65
  provider,
66
  model: selectedModel,
 
73
  jsonMode: providerConfig.supportsJSON,
74
  });
75
 
76
+ // Step 2: Schema-bounded entity extraction (Youtu-GraphRAG novelty)
77
  const entityResp = await callLLM({
78
  provider,
79
  model: selectedModel,
80
  messages: [
81
+ { role: "system", content: `Extract entities and relationships from this question.
82
+ ALLOWED ENTITY TYPES: PERSON, ORGANIZATION, LOCATION, EVENT, DATE, CONCEPT, WORK, PRODUCT, TECHNOLOGY
83
+ ALLOWED RELATION TYPES: WORKS_FOR, LOCATED_IN, FOUNDED_BY, PART_OF, RELATED_TO, CREATED_BY, HAPPENED_IN, MEMBER_OF, COLLABORATES_WITH, INFLUENCES
84
+ Return JSON:
85
+ {"entities": [{"name": "...", "type": "one of allowed types"}],
86
+ "relations": [{"source": "name", "target": "name", "type": "one of allowed types", "description": "brief"}]}` },
87
  { role: "user", content: query },
88
  ],
89
  temperature: 0,
 
95
  let relations: string[] = [];
96
  try {
97
  const parsed = JSON.parse(entityResp.content);
98
+ entities = (parsed.entities || []).map((e: { name: string; type?: string }) => e.name);
99
  relations = (parsed.relations || []).map(
100
  (r: { source: string; type: string; target: string; description?: string }) =>
101
  `${r.source} -[${r.type}]-> ${r.target}: ${r.description || ""}`
102
  );
103
+ } catch { /* parse errors OK */ }
104
 
105
+ // Step 3: Generate with structured graph context
106
+ const graphContext = [
107
+ entities.length > 0 ? `### Entities Found:\n${entities.map((e) => `- ${e}`).join("\n")}` : "",
108
+ relations.length > 0 ? `### Relationships:\n${relations.map((r) => `- ${r}`).join("\n")}` : "",
109
+ ].filter(Boolean).join("\n\n");
110
 
111
  const graphragResp = await callLLM({
112
  provider,
113
  model: selectedModel,
114
  messages: [
115
+ { role: "system", content: "You are a knowledgeable assistant with access to a knowledge graph. Use the structured context including entities, relationships, and passages to answer accurately. Follow relationship chains for multi-hop reasoning. Be concise." },
116
  { role: "user", content: `Context:\n${graphContext}\n\nQuestion: ${query}\n\nAnswer:` },
117
  ],
118
  temperature: 0,
 
123
  const graphragTotalCost = kwResp.costUsd + entityResp.costUsd + graphragResp.costUsd;
124
  const graphragLatency = kwResp.latencyMs + entityResp.latencyMs + graphragResp.latencyMs;
125
 
126
+ // Adaptive routing (PolyG-inspired novelty)
127
  let complexity = 0.5, queryType = "unknown", recommended = "baseline";
128
  if (adaptiveRouting) {
129
  const multi = entities.length > 2;
 
135
  }
136
 
137
  return NextResponse.json({
138
+ llmOnly: {
139
+ answer: llmOnlyResp.content,
140
+ tokens: llmOnlyResp.totalTokens,
141
+ latencyMs: llmOnlyResp.latencyMs,
142
+ costUsd: llmOnlyResp.costUsd,
143
+ },
144
  baseline: {
145
  answer: baselineResp.content,
146
  tokens: baselineResp.totalTokens,
 
173
 
174
  function getDemoResponse(query: string, provider: string, error?: string) {
175
  return {
176
+ llmOnly: {
177
+ answer: "Scott Derrickson and Ed Wood were both American filmmakers, so yes, they shared the same nationality.",
178
+ tokens: 523, latencyMs: 890, costUsd: 0.000127,
179
+ },
180
  baseline: {
181
  answer: "Both Scott Derrickson and Ed Wood were American filmmakers.",
182
  tokens: 847, latencyMs: 1240, costUsd: 0.000203,