Skip to content

Commit 741a5de

Browse files
fix: simplify logic for backend by using the new prompt. Display error toast in /upload using the message sent by backend
1 parent 9161fe3 commit 741a5de

File tree

7 files changed

+67
-293
lines changed

7 files changed

+67
-293
lines changed

src/app/api/ai-upload/map.ts

Lines changed: 0 additions & 5 deletions
This file was deleted.

src/app/api/ai-upload/route.ts

Lines changed: 19 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,9 @@ import type {
1616
ExamDetail,
1717
IAdminPaper,
1818
} from "@/interface";
19-
import Paper, { PaperAdmin } from "@/db/papers";
19+
import { PaperAdmin } from "@/db/papers";
2020
import axios from "axios";
2121
import processAndAnalyze from "@/util/gemini";
22-
import { examMap } from "./map";
2322
import Fuse from "fuse.js";
2423
// import processAndAnalyze from "./mistral";
2524
// TODO: REMOVE THUMBNAIL FROM admin-buffer DB
@@ -68,17 +67,22 @@ export async function POST(req: Request) {
6867
const bytes = await files[0]?.arrayBuffer();
6968
if (bytes) {
7069
const buffer = Buffer.from(bytes);
71-
imageURL = buffer.toString("base64"); // Plain Base64 string, no data URL prefix
70+
imageURL = buffer.toString("base64");
7271
}
7372
}
7473
const tags = await processAndAnalyze({ imageURL });
7574

7675
console.log(" tags:", tags);
7776

7877
const finalTags = await setTagsFromCurrentLists(tags);
79-
const subject = finalTags["course-name"];
78+
console.log(" tags:", finalTags);
79+
if(!tags)
80+
{
81+
return null;
82+
}
83+
const subject = finalTags.subject;
8084
const slot = finalTags.slot;
81-
const exam = finalTags["exam-type"];
85+
const exam = finalTags.exam
8286
const year = finalTags.year;
8387
const campus = formData.get("campus") as string;
8488
const semester = finalTags.semester;
@@ -267,37 +271,40 @@ async function setTagsFromCurrentLists(
267271
}
268272

269273
const newTags: ExamDetail = {
270-
"course-name": courses[0],
274+
"subject": courses[0],
271275
slot: slots[0],
272276
"course-code": "notInUse",
273-
"exam-type": exams[0],
277+
"exam": exams[0],
274278
semester: semesters[0] as SemesterType,
275279
year: years[0],
276280
};
281+
277282
const coursesFuzy = new Fuse(courses);
278283
if (!tags) {
279284
console.log("Anaylsis failed setting random courses as fields");
280285
return newTags;
281286
} else {
282287
const subjectSearch = coursesFuzy.search(
283-
tags["course-name"] + "|" + tags["course-code"],
288+
tags.subject ,
284289
)[0];
285290
if (subjectSearch) {
286-
newTags["course-name"] = subjectSearch.item;
291+
newTags.subject = subjectSearch.item;
287292
}
288293
const slotSearchResult = findMatch(slots, tags.slot);
289294
if (slotSearchResult) {
290295
newTags.slot = slotSearchResult;
291296
}
292-
if ("exam-type" in tags && tags["exam-type"] in examMap) {
293-
const examType = tags["exam-type"] as keyof typeof examMap;
294-
newTags["exam-type"] = examMap[examType];
297+
const examSearchResult = findMatch(exams, tags.exam);
298+
if (examSearchResult) {
299+
newTags.exam = examSearchResult;
295300
}
296301
const semesterSearchResult = findMatch(semesters, tags.semester);
297302
if (semesterSearchResult) {
298303
newTags.semester = semesterSearchResult as SemesterType;
304+
299305
}
300306
const yearSearchResult = findMatch(years, tags.year);
307+
301308
if (yearSearchResult) {
302309
newTags.year = yearSearchResult;
303310
}

src/app/upload/page.tsx

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,18 @@
11
"use client";
22
import React, { useState } from "react";
3-
import axios from "axios";
3+
import axios, { AxiosError } from "axios";
44
import toast from "react-hot-toast";
55
import { handleAPIError } from "../../util/error";
66
import { Button } from "@/components/ui/button";
77
import Navbar from "@/components/Navbar";
88
import Footer from "@/components/Footer";
9-
import { type PostPDFToCloudinary } from "@/interface";
9+
import { type APIResponse } from "@/interface";
1010
import Dropzone from "react-dropzone";
1111

1212
import { createCanvas } from "canvas";
1313
import { getDocument, GlobalWorkerOptions } from "pdfjs-dist";
1414
import { PDFDocument } from "pdf-lib";
15+
import { ApiError } from "next/dist/server/api-utils";
1516
async function pdfToImage(file: File) {
1617
GlobalWorkerOptions.workerSrc =
1718
"https://unpkg.com/[email protected]/build/pdf.worker.min.js";
@@ -120,7 +121,7 @@ const Page = () => {
120121
if (isPdf && files[0]) {
121122
formData.append("image", await pdfToImage(files[0]));
122123
}
123-
124+
124125
// formData.append("exam", exam);
125126
formData.append("campus", campus);
126127

@@ -130,11 +131,27 @@ const Page = () => {
130131

131132
try {
132133
await toast.promise(
133-
axios.post<PostPDFToCloudinary>("/api/ai-upload", formData),
134+
async () => {
135+
try {
136+
await axios.post<APIResponse>(
137+
"/api/ai-upload",
138+
formData,
139+
);
140+
} catch (error) {
141+
if (error instanceof AxiosError && error.response?.data ) {
142+
const errorData = error.response.data as APIResponse;
143+
const errorMessage = errorData.message || "Failed to upload papers";
144+
throw new Error(errorMessage);
145+
}
146+
throw new Error("Failed to upload papers");
147+
}
148+
},
134149
{
135150
loading: "Uploading papers...",
136151
success: "Papers uploaded successfully!",
137-
error: "Failed to upload papers. Please try again.",
152+
error: (error: Error) => {
153+
return error.message;
154+
},
138155
},
139156
);
140157

@@ -207,4 +224,4 @@ const Page = () => {
207224
);
208225
};
209226

210-
export default Page;
227+
export default Page;

src/app/upload/page_not_AI.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import { handleAPIError } from "../../util/error";
77
import { Button } from "@/components/ui/button";
88
import Navbar from "@/components/Navbar";
99
import Footer from "@/components/Footer";
10-
import { type PostPDFToCloudinary } from "@/interface";
10+
import { type APIResponse } from "@/interface";
1111
import { slots, years, campuses, semesters, exams } from "@/components/select_options";
1212
import SearchBar from "@/components/searchbarSubjectList";
1313
import Dropzone from "react-dropzone";
@@ -170,7 +170,7 @@ const Page = () => {
170170

171171
try {
172172
await toast.promise(
173-
axios.post<PostPDFToCloudinary>("/api/upload", formData),
173+
axios.post<APIResponse>("/api/upload", formData),
174174
{
175175
loading: "Uploading papers...",
176176
success: "Papers uploaded successfully!",

src/interface.ts

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,8 +96,9 @@ export interface IAdminUpload {
9696
exam: "CAT-1" | "CAT-2" | "FAT";
9797
isPdf: boolean;
9898
}
99-
export interface PostPDFToCloudinary {
100-
status: boolean;
99+
export interface APIResponse {
100+
message: string;
101+
status: number;
101102
}
102103
export interface ConverttoPDFResponse {
103104
url: string;
@@ -147,10 +148,10 @@ export interface IPaper {
147148
answerKeyIncluded?: boolean;
148149
}
149150
export type ExamDetail = {
150-
"course-name": string;
151+
subject: string;
151152
slot: string;
152153
"course-code": string;
153-
"exam-type": string;
154+
"exam": string;
154155
semester: "Fall Semester" | "Winter Semester" | "Summer Semester" | "Weekend Semester";
155156
year: string;
156157
};

src/util/gemini.ts

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -73,14 +73,14 @@ function parseExamDetail(analysis: string): ExamDetail {
7373
if (examDetail.semester) {
7474
const validSemesters = ["Fall Semester", "Winter Semester", "Summer Semester", "Weekend Semester"];
7575
if (!validSemesters.includes(examDetail.semester)) {
76-
examDetail.semester = "Fall Semester"; // Default to Fall Semester if invalid
76+
examDetail.semester = "Fall Semester";
7777
}
7878
}
7979

8080
if (examDetail.year) {
8181
const yearPattern = /^\d{4}$/;
8282
if (!yearPattern.test(examDetail.year)) {
83-
examDetail.year = new Date().getFullYear().toString(); // Default to current year if invalid
83+
examDetail.year = new Date().getFullYear().toString();
8484
}
8585
}
8686
return examDetail
@@ -90,10 +90,10 @@ function parseExamDetail(analysis: string): ExamDetail {
9090
} catch (error) {
9191
console.error("Error parsing exam details:", error);
9292
return {
93-
"course-name": "Unknown",
93+
"subject": "Unknown",
9494
slot: "Unknown",
9595
"course-code": "Unknown",
96-
"exam-type": "Unknown",
96+
"exam": "Unknown",
9797
semester: "Fall Semester",
9898
year: new Date().getFullYear().toString()
9999
};
@@ -114,8 +114,18 @@ async function analyzeImage(dataUrl: string): Promise<AnalysisResult[]> {
114114

115115
// const dataUrl = `data:image/png;base64,${imageBase64}`;
116116

117-
const prompt = `This is an image of a question paper. I want you to extract the Exam name, there can be three: final assessment test, continuous assessment test 1, continuous assessment test 2.Now Final assessment should be labelled as FAT, Continuous assessment 1 should be labelled as CAT1 and Continuous assessment 2 should be labelled as CAT2. Also I want you to find me the semester it is from, there can be four: Fall Semester, Winter Semester, Summer Semester, Weekend Semester. Fall semester lasts form july to end of the year and winter from january to april, rest is summer semester.Do not put weekend semester if you dont see it in the image. Also find me the year of the exam and the slot of the exam, they look something like this : A1, A1+TA1, B2+BT2, C1+TC1+TCC1 etc.Instead of the entire slot though i just require the initial, alphaber and number part before the plus sign. And I also require the course title and the course code from the paper. Course code looks something like : BCSE202P, BCSE307L etc. if you unable to find return NOT FOUND also format your output into a .json format. most importantly if you are unsure of anything at all just return NOT FOUND`;
117+
const prompt = `This is an image of a question paper. I want you to extract the Exam name, there can be three: final assessment test, continuous assessment test 1, continuous assessment test 2.Now Final assessment should be labelled as FAT, Continuous assessment 1 should be labelled as CAT-1 and Continuous assessment 2 should be labelled as CAT-2. Also I want you to find me the semester it is from, there can be four: Fall Semester, Winter Semester, Summer Semester, Weekend Semester. Fall semester lasts form july to end of the year and winter from january to May inclusive , summer semester is from june to july. Do not put weekend semester if you dont see it in the image. Also find me the year of the exam and the slot of the exam, they look something like this : A1, A1+TA1, B2+BT2, C1+TC1+TCC1 etc.Instead of the entire slot though i just require the initial, alphaber and number part before the plus sign. And I also require the course title and the course code from the paper. Course code looks something like : BCSE202P, BCSE307L etc. if you unable to find return NOT FOUND also format your output into a .json format. most importantly if you are unsure of anything at all just return NOT FOUND
118118
119+
make sure to return the output in the following format:
120+
{
121+
subject: "course title [course code]"
122+
exam: "exam type"
123+
year: year
124+
slot: "A1/A2/B1 etc "
125+
semester: "semester"
126+
}
127+
128+
`;
119129
const image = {
120130
inlineData: {
121131
data: dataUrl,
@@ -128,8 +138,8 @@ async function analyzeImage(dataUrl: string): Promise<AnalysisResult[]> {
128138
const chatResponse = result.response.text();
129139
const rawAnalysis = chatResponse;
130140

141+
console.log(rawAnalysis)
131142
const examDetail: ExamDetail = parseExamDetail(rawAnalysis);
132-
133143
results.push({
134144
examDetail,
135145
rawAnalysis,
@@ -144,10 +154,10 @@ async function analyzeImage(dataUrl: string): Promise<AnalysisResult[]> {
144154
return [
145155
{
146156
examDetail: {
147-
"course-name": "Error",
157+
"subject": "Error",
148158
slot: "Error",
149159
"course-code": "Error",
150-
"exam-type": "Error",
160+
"exam": "Error",
151161
semester: "Fall Semester",
152162
year: new Date().getFullYear().toString()
153163
},

0 commit comments

Comments
 (0)