senlinyy commited on
Commit
65afa7b
Β·
1 Parent(s): 8ac2dd1

feat: UI updated

Browse files
backend/personas.json CHANGED
@@ -7,9 +7,9 @@
7
  },
8
  {
9
  "id": "strict_grader",
10
- "name": "Strict Grader",
11
- "description": "Rigorous, terse, and demanding of evidence.",
12
- "prompt": "You are a strict grader. Be concise and uncompromising. Demand evidence from the course material for every claim. Point out logical gaps, missing citations, and imprecise terminology. Award no partial credit silently."
13
  },
14
  {
15
  "id": "explainer",
 
7
  },
8
  {
9
  "id": "strict_grader",
10
+ "name": "Scholarly Reviewer",
11
+ "description": "Rigorous, clear, and demanding of evidence.",
12
+ "prompt": "You are a scholarly reviewer. Be concise and exacting. Demand evidence from the course material for every claim. Point out logical gaps, missing citations, and imprecise terminology. Avoid softening unsupported claims."
13
  },
14
  {
15
  "id": "explainer",
frontend/app/layout.tsx CHANGED
@@ -2,8 +2,8 @@ import "./globals.css";
2
  import type { Metadata } from "next";
3
 
4
  export const metadata: Metadata = {
5
- title: "IamEarthDev β€” Course Assistant",
6
- description: "RAG chatbot for course materials, hosted on Hugging Face Spaces.",
7
  };
8
 
9
  export default function RootLayout({ children }: { children: React.ReactNode }) {
 
2
  import type { Metadata } from "next";
3
 
4
  export const metadata: Metadata = {
5
+ title: "IamEarthDev β€” Educational Luminary",
6
+ description: "A learning exploration supported by curated resources and customised AI.",
7
  };
8
 
9
  export default function RootLayout({ children }: { children: React.ReactNode }) {
frontend/app/page.tsx CHANGED
@@ -8,9 +8,9 @@ export default function Page() {
8
  <main className="mx-auto flex h-full max-w-6xl flex-col gap-4 p-4 sm:p-6">
9
  <header className="flex items-center justify-between">
10
  <div>
11
- <h1 className="text-xl font-semibold tracking-tight">Course Assistant</h1>
12
  <p className="text-sm text-muted-foreground">
13
- Ask questions grounded in the uploaded course materials.
14
  </p>
15
  </div>
16
  <div className="flex items-center gap-3">
 
8
  <main className="mx-auto flex h-full max-w-6xl flex-col gap-4 p-4 sm:p-6">
9
  <header className="flex items-center justify-between">
10
  <div>
11
+ <h1 className="text-xl font-semibold tracking-tight">Educational Luminary</h1>
12
  <p className="text-sm text-muted-foreground">
13
+ A learning exploration supported by curated resources and customised AI.
14
  </p>
15
  </div>
16
  <div className="flex items-center gap-3">
frontend/components/chat-interface.tsx CHANGED
@@ -1,6 +1,6 @@
1
  "use client";
2
  import { useState, useRef, useEffect } from "react";
3
- import { BookOpen, FileText, Loader2, Plus, RefreshCw, Send, Trash2 } from "lucide-react";
4
  import { Button } from "@/components/ui/button";
5
  import { Input } from "@/components/ui/input";
6
  import { Card, CardContent } from "@/components/ui/card";
@@ -360,9 +360,13 @@ export function ChatInterface() {
360
  <div ref={scrollRef} className="flex-1 space-y-4 overflow-y-auto p-6">
361
  {messages.length === 0 && (
362
  <div className="flex h-full flex-col items-center justify-center text-center text-muted-foreground">
363
- <BookOpen className="mb-3 h-10 w-10 opacity-50" />
 
 
 
 
364
  <p className="text-sm">
365
- Ask a question about your course material to get started.
366
  </p>
367
  </div>
368
  )}
@@ -429,7 +433,7 @@ export function ChatInterface() {
429
  }}
430
  >
431
  <Input
432
- placeholder="Ask about the course material..."
433
  value={input}
434
  onChange={(e) => setInput(e.target.value)}
435
  disabled={busy}
 
1
  "use client";
2
  import { useState, useRef, useEffect } from "react";
3
+ import { FileText, Loader2, Plus, RefreshCw, Send, Trash2 } from "lucide-react";
4
  import { Button } from "@/components/ui/button";
5
  import { Input } from "@/components/ui/input";
6
  import { Card, CardContent } from "@/components/ui/card";
 
360
  <div ref={scrollRef} className="flex-1 space-y-4 overflow-y-auto p-6">
361
  {messages.length === 0 && (
362
  <div className="flex h-full flex-col items-center justify-center text-center text-muted-foreground">
363
+ <img
364
+ src="/luminaria.svg"
365
+ alt="Luminaria holding a light"
366
+ className="mb-4 h-28 w-28 rounded-lg object-contain"
367
+ />
368
  <p className="text-sm">
369
+ Ask a question or share a thought.
370
  </p>
371
  </div>
372
  )}
 
433
  }}
434
  >
435
  <Input
436
+ placeholder="Ask a question or share a thought"
437
  value={input}
438
  onChange={(e) => setInput(e.target.value)}
439
  disabled={busy}
frontend/components/temperature-slider.tsx CHANGED
@@ -25,7 +25,7 @@ export function TemperatureSlider({
25
  onValueChange={(v) => onChange(v[0] ?? 0)}
26
  />
27
  <p className="text-xs text-muted-foreground">
28
- Lower = more focused on the source material. Higher = more creative.
29
  </p>
30
  </div>
31
  );
 
25
  onValueChange={(v) => onChange(v[0] ?? 0)}
26
  />
27
  <p className="text-xs text-muted-foreground">
28
+ Lower = more focused on the source material. Higher = more creative, but higher risk of hallucinations.
29
  </p>
30
  </div>
31
  );
frontend/lib/personas.ts CHANGED
@@ -5,6 +5,15 @@ export type Persona = {
5
  prompt: string;
6
  };
7
 
 
 
 
 
 
 
 
 
 
8
  // Bundled fallback β€” shown before the API responds.
9
  // The canonical list lives on the server (backend/personas.json β†’ HF Dataset).
10
  export const DEFAULT_PERSONAS: Persona[] = [
@@ -19,12 +28,7 @@ export const DEFAULT_PERSONAS: Persona[] = [
19
  },
20
  {
21
  id: "strict_grader",
22
- name: "Strict Grader",
23
- description: "Rigorous, terse, and demanding of evidence.",
24
- prompt:
25
- "You are a strict grader. Be concise and uncompromising. Demand evidence " +
26
- "from the course material for every claim. Point out logical gaps, missing " +
27
- "citations, and imprecise terminology. Award no partial credit silently.",
28
  },
29
  {
30
  id: "explainer",
@@ -48,16 +52,23 @@ export const DEFAULT_PERSONAS: Persona[] = [
48
 
49
  export const DEFAULT_PERSONA_ID = "explainer";
50
 
 
 
 
 
 
 
51
  /** Fetch the live persona list from the backend. Falls back to DEFAULT_PERSONAS. */
52
  export async function fetchPersonas(): Promise<Persona[]> {
53
  try {
54
  const r = await fetch("/api/personas");
55
  if (!r.ok) throw new Error("non-ok");
56
  const data = await r.json();
57
- if (Array.isArray(data.personas) && data.personas.length > 0) return data.personas;
 
 
58
  } catch {
59
  // swallow β€” use bundled fallback
60
  }
61
- return DEFAULT_PERSONAS;
62
  }
63
-
 
5
  prompt: string;
6
  };
7
 
8
+ const SCHOLARLY_REVIEWER: Omit<Persona, "id"> = {
9
+ name: "Scholarly Reviewer",
10
+ description: "Rigorous, clear, and demanding of evidence.",
11
+ prompt:
12
+ "You are a scholarly reviewer. Be concise and exacting. Demand evidence " +
13
+ "from the course material for every claim. Point out logical gaps, missing " +
14
+ "citations, and imprecise terminology. Avoid softening unsupported claims.",
15
+ };
16
+
17
  // Bundled fallback β€” shown before the API responds.
18
  // The canonical list lives on the server (backend/personas.json β†’ HF Dataset).
19
  export const DEFAULT_PERSONAS: Persona[] = [
 
28
  },
29
  {
30
  id: "strict_grader",
31
+ ...SCHOLARLY_REVIEWER,
 
 
 
 
 
32
  },
33
  {
34
  id: "explainer",
 
52
 
53
  export const DEFAULT_PERSONA_ID = "explainer";
54
 
55
+ function normalizePersonas(personas: Persona[]): Persona[] {
56
+ return personas.map((persona) =>
57
+ persona.id === "strict_grader" ? { ...persona, ...SCHOLARLY_REVIEWER } : persona
58
+ );
59
+ }
60
+
61
  /** Fetch the live persona list from the backend. Falls back to DEFAULT_PERSONAS. */
62
  export async function fetchPersonas(): Promise<Persona[]> {
63
  try {
64
  const r = await fetch("/api/personas");
65
  if (!r.ok) throw new Error("non-ok");
66
  const data = await r.json();
67
+ if (Array.isArray(data.personas) && data.personas.length > 0) {
68
+ return normalizePersonas(data.personas);
69
+ }
70
  } catch {
71
  // swallow β€” use bundled fallback
72
  }
73
+ return normalizePersonas(DEFAULT_PERSONAS);
74
  }
 
frontend/public/luminaria.svg ADDED