gaurv007 commited on
Commit
79665bc
·
verified ·
1 Parent(s): fdc2957

fix: web/app/api/chat/route.ts

Browse files
Files changed (1) hide show
  1. web/app/api/chat/route.ts +37 -64
web/app/api/chat/route.ts CHANGED
@@ -1,22 +1,23 @@
1
  import { NextRequest, NextResponse } from "next/server";
2
  import { createClient } from "@/lib/supabase/server";
3
 
4
- const GRADIO_URL = process.env.CLAUSEGUARD_GRADIO_URL || "https://gaurv007-clauseguard.hf.space";
5
-
6
  /**
7
- * FIX v4.1: The chat endpoint now properly documents its limitations.
8
  *
9
- * ARCHITECTURE NOTE:
10
- * The Gradio ChatInterface uses gr.State to store RAG embeddings per-session.
11
- * This state is NOT accessible via the Gradio API from an external caller —
12
- * each API call creates a new session with empty state.
 
13
  *
14
- * For the Next.js web app, chat should either:
15
- * 1. Use the FastAPI backend (/api/chat) which manages its own RAG sessions, OR
16
- * 2. Embed the Gradio Space in an iframe for direct interaction
 
 
17
  *
18
- * This route attempts to use the Gradio API as a best-effort fallback,
19
- * but will clearly communicate to the user if the session is unavailable.
20
  */
21
  export async function POST(req: NextRequest) {
22
  try {
@@ -37,7 +38,6 @@ export async function POST(req: NextRequest) {
37
  );
38
  }
39
 
40
- // FIX v4.1: Input validation
41
  if (message.length > 2000) {
42
  return NextResponse.json(
43
  { error: "Message too long (max 2000 characters)" },
@@ -45,7 +45,7 @@ export async function POST(req: NextRequest) {
45
  );
46
  }
47
 
48
- // Try the FastAPI backend first (it has proper RAG session management)
49
  const apiUrl = process.env.CLAUSEGUARD_API_URL || "";
50
  if (apiUrl && session_id) {
51
  try {
@@ -58,67 +58,40 @@ export async function POST(req: NextRequest) {
58
  const data = await apiRes.json();
59
  return NextResponse.json({ response: data.response });
60
  }
 
 
 
 
 
 
 
61
  } catch {
62
- // Fall through to Gradio attempt
63
  }
64
  }
65
 
66
- // Fallback: Try the Gradio API
67
- const submitRes = await fetch(`${GRADIO_URL}/gradio_api/call/chat`, {
68
- method: "POST",
69
- headers: { "Content-Type": "application/json" },
70
- body: JSON.stringify({ data: [message] }),
71
- });
72
-
73
- if (!submitRes.ok) {
74
- const errText = await submitRes.text().catch(() => "");
75
- throw new Error(`Chat submit failed (${submitRes.status}): ${errText}`);
76
- }
77
-
78
- const { event_id } = await submitRes.json();
79
- if (!event_id) throw new Error("No event_id from Gradio chat");
80
-
81
- // Poll for result with timeout
82
- let resultText = "";
83
- let attempts = 0;
84
- const maxAttempts = 30;
85
-
86
- while (attempts < maxAttempts) {
87
- const resultRes = await fetch(
88
- `${GRADIO_URL}/gradio_api/call/chat/${event_id}`,
89
- { headers: { Accept: "text/event-stream" } }
90
- );
91
-
92
- if (!resultRes.ok) {
93
- throw new Error(`Chat result failed: ${resultRes.status}`);
94
- }
95
-
96
- resultText = await resultRes.text();
97
-
98
- if (resultText.includes("event: complete")) break;
99
- if (resultText.includes("event: error")) {
100
- const errMatch = resultText.match(/event:\s*error\s*\ndata:\s*(.+)/);
101
- if (errMatch) throw new Error(`Chat error: ${errMatch[1]}`);
102
- throw new Error("Chat error from backend");
103
- }
104
-
105
- await new Promise(r => setTimeout(r, 1000));
106
- attempts++;
107
  }
108
 
109
- // Find the complete event data
110
- const dataMatch = resultText.match(/event:\s*complete\s*\ndata:\s*(.+)/);
111
- if (!dataMatch) {
112
  return NextResponse.json({
113
- response: "⚠️ Chat is unavailable. The contract needs to be analyzed in the same session. " +
114
- "Please analyze a contract first in the Gradio Space, then use the chat tab there directly."
115
  });
116
  }
117
 
118
- const responseData = JSON.parse(dataMatch[1]);
119
- const responseText = typeof responseData === "string" ? responseData : responseData[0] || "";
 
 
120
 
121
- return NextResponse.json({ response: responseText });
122
  } catch (error: any) {
123
  console.error("Chat error:", error.message);
124
  return NextResponse.json(
 
1
  import { NextRequest, NextResponse } from "next/server";
2
  import { createClient } from "@/lib/supabase/server";
3
 
 
 
4
  /**
5
+ * FIX v4.3: Chat route completely rewritten.
6
  *
7
+ * ARCHITECTURE:
8
+ * The Gradio ChatInterface uses gr.State for RAG embeddings — these are
9
+ * per-browser-session and NOT accessible via the Gradio REST API. Every API
10
+ * call creates a new session with empty state, so chat via Gradio API will
11
+ * NEVER have contract context.
12
  *
13
+ * The correct approach:
14
+ * 1. PRIMARY: Use the FastAPI backend (/api/chat) which manages RAG sessions
15
+ * with proper TTL-based expiry. The session_id comes from /api/analyze.
16
+ * 2. FALLBACK: If FastAPI is unavailable, return a clear error directing
17
+ * the user to use the Gradio Space directly.
18
  *
19
+ * The old code tried to call a non-existent Gradio "chat" endpoint which
20
+ * always failed. Removed the broken Gradio fallback entirely.
21
  */
22
  export async function POST(req: NextRequest) {
23
  try {
 
38
  );
39
  }
40
 
 
41
  if (message.length > 2000) {
42
  return NextResponse.json(
43
  { error: "Message too long (max 2000 characters)" },
 
45
  );
46
  }
47
 
48
+ // Try the FastAPI backend (it has proper RAG session management)
49
  const apiUrl = process.env.CLAUSEGUARD_API_URL || "";
50
  if (apiUrl && session_id) {
51
  try {
 
58
  const data = await apiRes.json();
59
  return NextResponse.json({ response: data.response });
60
  }
61
+ // If 404, session expired
62
+ if (apiRes.status === 404) {
63
+ return NextResponse.json({
64
+ response: "⚠️ Your chat session has expired (sessions last 1 hour). " +
65
+ "Please analyze the contract again to start a new chat session."
66
+ });
67
+ }
68
  } catch {
69
+ // FastAPI backend unreachable — fall through to error message
70
  }
71
  }
72
 
73
+ // No FastAPI backend available or no session_id
74
+ // FIX v4.3: Return a clear, helpful message instead of trying a broken Gradio endpoint
75
+ if (!apiUrl) {
76
+ return NextResponse.json({
77
+ response: "⚠️ Contract Q&A chat requires the FastAPI backend which is not currently deployed. " +
78
+ "You can use the chat feature directly in the [Gradio Space](https://gaurv007-clauseguard.hf.space) " +
79
+ "— analyze a contract there, then switch to the Q&A tab."
80
+ });
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  }
82
 
83
+ if (!session_id) {
 
 
84
  return NextResponse.json({
85
+ response: "⚠️ No active chat session. Please analyze a contract first " +
86
+ "the chat session is created when you run analysis."
87
  });
88
  }
89
 
90
+ return NextResponse.json({
91
+ response: "⚠️ Chat service is temporarily unavailable. Please try again, or use the " +
92
+ "[Gradio Space](https://gaurv007-clauseguard.hf.space) directly."
93
+ });
94
 
 
95
  } catch (error: any) {
96
  console.error("Chat error:", error.message);
97
  return NextResponse.json(