Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions kits/research-paper-explainer/.env.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Lamatic.ai Configuration
# Get these from https://studio.lamatic.ai → your project settings

LAMATIC_API_KEY=your_lamatic_api_key_here
LAMATIC_PROJECT_ID=your_project_id_here

# Flow endpoint URLs (from your Lamatic Studio deployment)
EXPLAIN_FLOW_URL=https://your-project.lamatic.app/api/explain
QUIZ_FLOW_URL=https://your-project.lamatic.app/api/quiz

# Optional: Customize the app title
NEXT_PUBLIC_APP_TITLE=Research Paper Explainer
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Verify unquoted env values containing whitespace in .env example files.
rg -nP '^[A-Z0-9_]+=.*\s+.*$' --glob '**/.env.example' -C1

Repository: Lamatic/AgentKit

Length of output: 892


Quote env values that contain spaces.

At line 12, the unquoted value can cause dotenv tooling inconsistencies; quote it for portability and consistency with similar values elsewhere in the codebase.

Suggested patch
-NEXT_PUBLIC_APP_TITLE=Research Paper Explainer
+NEXT_PUBLIC_APP_TITLE="Research Paper Explainer"
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
NEXT_PUBLIC_APP_TITLE=Research Paper Explainer
NEXT_PUBLIC_APP_TITLE="Research Paper Explainer"
🧰 Tools
🪛 dotenv-linter (4.0.0)

[warning] 12-12: [ValueWithoutQuotes] This value needs to be surrounded in quotes

(ValueWithoutQuotes)

35 changes: 35 additions & 0 deletions kits/research-paper-explainer/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# dependencies
/node_modules
/.pnp
.pnp.js
.yarn/install-state.gz

# testing
/coverage

# next.js
/.next/
/out/

# production
/build

# misc
.DS_Store
*.pem

# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# local env files
.env
.env*.local

# vercel
.vercel

# typescript
*.tsbuildinfo
next-env.d.ts
155 changes: 155 additions & 0 deletions kits/research-paper-explainer/README.md
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you add a live demo link to this file? would allow us to view the functionality better, and allow users to see the kit before forking it. otherwise, LGTM. Thanks!

Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
# 📚 Research Paper Explainer & Quiz Agent

> A Next.js kit built on [Lamatic AgentKit](https://github.com/Lamatic/AgentKit) that takes any research paper abstract or full text, explains it at your chosen comprehension level, and generates an interactive multiple-choice quiz to test understanding.
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence says the kit accepts a research paper "(URL or abstract)", but the UI currently only supports pasting text into a textarea (no URL fetching/parsing). Either implement URL ingestion or adjust the docs to match the actual input method.

Suggested change
> A Next.js kit built on [Lamatic AgentKit](https://github.com/Lamatic/AgentKit) that takes any research paper abstract or full text, explains it at your chosen comprehension level, and generates an interactive multiple-choice quiz to test understanding.
> A Next.js kit built on [Lamatic AgentKit](https://github.com/Lamatic/AgentKit) that lets you paste any research paper abstract or full text into the app, explains it at your chosen comprehension level, and generates an interactive multiple-choice quiz to test understanding.

Copilot uses AI. Check for mistakes.

[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/Mortarion002/AgentKit/tree/main/apps/research-paper-explainer)
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The Vercel deploy button URL points to a personal fork and to /apps/research-paper-explainer, but this kit lives under kits/research-paper-explainer in the main Lamatic/AgentKit repo. This link will fail or deploy the wrong directory; update it to use repository-url=https://github.com/Lamatic/AgentKit plus root-directory=kits/research-paper-explainer (and ideally include required env vars like other kits do).

Suggested change
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/Mortarion002/AgentKit/tree/main/apps/research-paper-explainer)
[![Deploy with Vercel](https://vercel.com/button)](https://vercel.com/new/clone?repository-url=https://github.com/Lamatic/AgentKit&root-directory=kits/research-paper-explainer)

Copilot uses AI. Check for mistakes.

---

## 🧠 Problem Statement

Reading academic research papers is hard. Dense jargon, complex methodologies, and assumed domain knowledge make papers inaccessible to students, curious learners, and even professionals stepping outside their niche.

**PaperLens** solves this with two AI-powered agents:
1. **Explainer Agent** — Breaks down a paper into plain language at high-school, undergraduate, or expert level, structured around: Core Problem → Methodology → Key Findings → Real-World Impact.
2. **Quiz Agent** — Generates a custom multiple-choice quiz from the paper to reinforce learning and test comprehension.

---

## ✨ Features

- 📄 Paste any research paper abstract or full text
- 🎓 Choose explanation level: Simple / Intermediate / Expert
- 🧩 Generate 3–10 quiz questions with answer feedback & explanations
- 📊 Live score tracking after quiz submission
- ⚡ Two independent Lamatic Flows (explain + quiz)
- 🎨 Clean, distraction-free editorial UI

---

## 🗂 Folder Structure

```
research-paper-explainer/
├── app/
│ ├── page.tsx # Main UI (input + output panels)
│ ├── layout.tsx # Root layout with fonts
│ ├── globals.css # Design system & animations
│ └── api/
│ ├── explain/route.ts # Calls the Lamatic explain flow
│ └── quiz/route.ts # Calls the Lamatic quiz flow
├── lamatic-config.json # Flow definitions for Lamatic Studio
├── .env.example # Required environment variables
├── package.json
├── tailwind.config.ts
├── tsconfig.json
└── README.md
```
Comment on lines +32 to +54
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

The folder structure code block is missing a language specifier. While this doesn't affect rendering, it helps with accessibility and linting compliance.

Suggested fix
-```
+```text
 research-paper-explainer/
 ├── app/
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```
research-paper-explainer/
├── app/
│ ├── page.tsx # Main UI (input + output panels)
│ ├── layout.tsx # Root layout with fonts
│ ├── globals.css # Design system & animations
│ └── api/
│ ├── explain/route.ts # Calls the Lamatic explain flow
│ └── quiz/route.ts # Calls the Lamatic quiz flow
├── lamatic-config.json # Flow definitions for Lamatic Studio
├── .env.example # Required environment variables
├── package.json
├── tailwind.config.ts
├── tsconfig.json
└── README.md
```
🧰 Tools
🪛 markdownlint-cli2 (0.21.0)

[warning] 32-32: Fenced code blocks should have a language specified

(MD040, fenced-code-language)


---

## 🚀 Getting Started

### 1. Clone the Repository

```bash
git clone https://github.com/Lamatic/AgentKit.git
cd AgentKit/kits/research-paper-explainer
```

### 2. Install Dependencies

```bash
npm install
```

### 3. Set Up Lamatic Flows

1. Sign up at [lamatic.ai](https://lamatic.ai) and create a new project
2. In Lamatic Studio, create **two flows** using the definitions in `lamatic-config.json`:
- **Explain Flow** — accepts `paperContent` + `level`, returns a markdown explanation
- **Quiz Flow** — accepts `paperContent` + `numQuestions`, returns a JSON quiz
3. Deploy both flows and copy their endpoint URLs

### 4. Configure Environment Variables

```bash
cp .env.example .env
```

Edit `.env` and fill in:

```env
LAMATIC_API_KEY=your_lamatic_api_key
LAMATIC_PROJECT_ID=your_project_id
EXPLAIN_FLOW_URL=https://your-project.lamatic.app/api/explain
QUIZ_FLOW_URL=https://your-project.lamatic.app/api/quiz
```

### 5. Run Locally

```bash
npm run dev
```

Open [http://localhost:3000](http://localhost:3000)

---

## 🌐 Deploy to Vercel

```bash
npm run build
vercel --prod
```

Or use the one-click deploy button at the top of this README.

---

## 🔧 Lamatic Flow Configuration

The `lamatic-config.json` defines both flows. Key configuration:

| Flow | Input Fields | Output |
|---|---|---|
| `explain-flow` | `paperContent`, `level` | Markdown explanation string |
| `quiz-flow` | `paperContent`, `numQuestions` | JSON: `{ questions: [...] }` |

**Quiz JSON shape expected from Lamatic:**

```json
{
"questions": [
{
"question": "What problem does this paper solve?",
"options": ["A) ...", "B) ...", "C) ...", "D) ..."],
"correct": 0,
"explanation": "The paper focuses on..."
}
]
}
```

---

## 🛠 Tech Stack

| Layer | Tech |
|---|---|
| Frontend | Next.js 14, TypeScript, Tailwind CSS |
| AI Agent | Lamatic Flow (GPT-4o-mini via Lamatic Studio) |
| Markdown Rendering | `react-markdown` + `remark-gfm` |
| Deployment | Vercel |

---

## 🤝 Contributing

Found a bug or want to improve this kit? Open an issue or PR on the [AgentKit repository](https://github.com/Lamatic/AgentKit).

---

## 📄 License

MIT — Built by [Aman Kumar](https://github.com/Mortarion002) as part of the Lamatic AgentKit community.
48 changes: 48 additions & 0 deletions kits/research-paper-explainer/app/api/explain/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
try {
const { paperContent, level } = await req.json();

if (!paperContent || paperContent.trim().length < 50) {
return NextResponse.json(
{ error: "Please provide a research paper abstract or content (at least 50 characters)." },
{ status: 400 }
);
}
Comment on lines +6 to +13
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Guard input types before calling .trim().

At Line 7, non-string paperContent (e.g., object/null) will throw and end up as a 500. Validate type and return 400 for invalid payloads.

Suggested patch
-    const { paperContent, level } = await req.json();
+    const body = await req.json();
+    const paperContent = typeof body?.paperContent === "string" ? body.paperContent : "";
+    const level = typeof body?.level === "string" ? body.level : undefined;
 
-    if (!paperContent || paperContent.trim().length < 50) {
+    if (!paperContent || paperContent.trim().length < 50) {
       return NextResponse.json(
         { error: "Please provide a research paper abstract or content (at least 50 characters)." },
         { status: 400 }
       );
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const { paperContent, level } = await req.json();
if (!paperContent || paperContent.trim().length < 50) {
return NextResponse.json(
{ error: "Please provide a research paper abstract or content (at least 50 characters)." },
{ status: 400 }
);
}
const body = await req.json();
const paperContent = typeof body?.paperContent === "string" ? body.paperContent : "";
const level = typeof body?.level === "string" ? body.level : undefined;
if (!paperContent || paperContent.trim().length < 50) {
return NextResponse.json(
{ error: "Please provide a research paper abstract or content (at least 50 characters)." },
{ status: 400 }
);
}


const flowUrl = process.env.EXPLAIN_FLOW_URL;
const apiKey = process.env.LAMATIC_API_KEY;

if (!flowUrl || !apiKey) {
return NextResponse.json(
{ error: "Server misconfiguration: missing EXPLAIN_FLOW_URL or LAMATIC_API_KEY." },
{ status: 500 }
);
}

const response = await fetch(flowUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({ paperContent, level: level || "undergraduate" }),
});
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

level is passed through to the Lamatic flow without validation. To avoid unexpected prompts/behavior, validate that level is one of the supported values (high-school/undergraduate/expert) and return 400 (or default safely) when it isn’t.

Copilot uses AI. Check for mistakes.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add a timeout to the Lamatic upstream call.

At Line 24, the external fetch has no timeout/abort path. A slow upstream can stall this route and degrade availability.

Suggested patch
-    const response = await fetch(flowUrl, {
+    const controller = new AbortController();
+    const timeout = setTimeout(() => controller.abort(), 15000);
+    const response = await fetch(flowUrl, {
       method: "POST",
       headers: {
         "Content-Type": "application/json",
         Authorization: `Bearer ${apiKey}`,
       },
       body: JSON.stringify({ paperContent, level: level || "undergraduate" }),
+      signal: controller.signal,
     });
+    clearTimeout(timeout);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
const response = await fetch(flowUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({ paperContent, level: level || "undergraduate" }),
});
const controller = new AbortController();
const timeout = setTimeout(() => controller.abort(), 15000);
const response = await fetch(flowUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({ paperContent, level: level || "undergraduate" }),
signal: controller.signal,
});
clearTimeout(timeout);


if (!response.ok) {
const errText = await response.text();
console.error("Lamatic explain flow error:", errText);
return NextResponse.json(
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
{ error: "The AI agent failed to process the request. Please try again." },
{ status: 502 }
);
}

const data = await response.json();
return NextResponse.json({ explanation: data?.result || data?.output || data });
Comment thread
coderabbitai[bot] marked this conversation as resolved.
Outdated
} catch (err) {
console.error("Explain API error:", err);
return NextResponse.json({ error: "Internal server error." }, { status: 500 });
}
}
69 changes: 69 additions & 0 deletions kits/research-paper-explainer/app/api/quiz/route.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { NextRequest, NextResponse } from "next/server";

export async function POST(req: NextRequest) {
try {
const { paperContent, numQuestions } = await req.json();

if (!paperContent || paperContent.trim().length < 50) {
return NextResponse.json(
{ error: "Please provide paper content before generating a quiz." },
{ status: 400 }
);
}

const flowUrl = process.env.QUIZ_FLOW_URL;
const apiKey = process.env.LAMATIC_API_KEY;

if (!flowUrl || !apiKey) {
return NextResponse.json(
{ error: "Server misconfiguration: missing QUIZ_FLOW_URL or LAMATIC_API_KEY." },
{ status: 500 }
);
}

const response = await fetch(flowUrl, {
method: "POST",
headers: {
"Content-Type": "application/json",
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify({
paperContent,
numQuestions: numQuestions || 5,
}),
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

numQuestions is forwarded to the Lamatic flow without type/range validation. Since request JSON can provide a string/float/negative/very large value, consider coercing to a number and clamping to the supported UI range (3–10) before calling the flow (and returning 400 on invalid input).

Copilot uses AI. Check for mistakes.
});

if (!response.ok) {
const errText = await response.text();
console.error("Lamatic quiz flow error:", errText);
return NextResponse.json(
{ error: "The AI agent failed to generate the quiz. Please try again." },
{ status: 502 }
);
}

const data = await response.json();
const raw = data?.result || data?.output || data;

// Parse if the LLM returned a JSON string
let parsed: { questions: QuizQuestion[] };
if (typeof raw === "string") {
const match = raw.match(/\{[\s\S]*\}/);
parsed = JSON.parse(match ? match[0] : raw);
} else {
parsed = raw;
}
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Validate parsed quiz structure before returning.

The QuizQuestion interface is defined but never used for runtime validation. If the LLM returns malformed JSON (e.g., missing questions array, wrong types), the client will crash. Consider adding basic structure validation.

Suggested validation
     let parsed: { questions: QuizQuestion[] };
     if (typeof raw === "string") {
       const match = raw.match(/\{[\s\S]*\}/);
       parsed = JSON.parse(match ? match[0] : raw);
     } else {
       parsed = raw;
     }

+    if (!Array.isArray(parsed?.questions) || parsed.questions.length === 0) {
+      console.error("Invalid quiz structure:", parsed);
+      return NextResponse.json(
+        { error: "The AI returned an invalid quiz format. Please try again." },
+        { status: 502 }
+      );
+    }
+
     return NextResponse.json(parsed);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// Parse if the LLM returned a JSON string
let parsed: { questions: QuizQuestion[] };
if (typeof raw === "string") {
const match = raw.match(/\{[\s\S]*\}/);
parsed = JSON.parse(match ? match[0] : raw);
} else {
parsed = raw;
}
// Parse if the LLM returned a JSON string
let parsed: { questions: QuizQuestion[] };
if (typeof raw === "string") {
const match = raw.match(/\{[\s\S]*\}/);
parsed = JSON.parse(match ? match[0] : raw);
} else {
parsed = raw;
}
if (!Array.isArray(parsed?.questions) || parsed.questions.length === 0) {
console.error("Invalid quiz structure:", parsed);
return NextResponse.json(
{ error: "The AI returned an invalid quiz format. Please try again." },
{ status: 502 }
);
}
return NextResponse.json(parsed);


return NextResponse.json(parsed);
Copy link

Copilot AI Mar 20, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The quiz endpoint can return invalid data to the client: parsed is assumed to be { questions: QuizQuestion[] } without validating that raw actually has a questions array (and JSON.parse failures fall through to the generic 500). Please add explicit parsing/validation (e.g., try/catch around JSON.parse, ensure parsed.questions is an array with the expected fields, and return a 502 with a clear error when Lamatic returns malformed output) so the UI doesn’t crash on unexpected responses.

Copilot uses AI. Check for mistakes.
} catch (err) {
console.error("Quiz API error:", err);
return NextResponse.json({ error: "Internal server error." }, { status: 500 });
}
}

interface QuizQuestion {
question: string;
options: string[];
correct: number;
explanation: string;
}
Loading
Loading