Skip to content

Commit bd888cb

Browse files
authored
Merge pull request #151 from AsadAhmedSaiyed/fix/gemini-model-not-found
Fix Gemini API 404 Error by Migrating to Latest @google/genai SDK
2 parents 056333e + 9fa102e commit bd888cb

File tree

3 files changed

+594
-276
lines changed

3 files changed

+594
-276
lines changed
Lines changed: 41 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
1-
const Receipt = require('../models/Receipt');
2-
const IncomeExpense = require('../models/IncomeExpense');
3-
const { GoogleGenerativeAI } = require("@google/generative-ai");
4-
const fs = require('fs');
1+
const Receipt = require("../models/Receipt");
2+
const IncomeExpense = require("../models/IncomeExpense");
3+
const { GoogleGenAI } = require("@google/genai");
54

6-
const genAI = new GoogleGenerativeAI(process.env.GEMINI_API_KEY);
5+
const fs = require("fs");
6+
7+
const client = new GoogleGenAI({
8+
apiKey: process.env.GEMINI_API_KEY,
9+
});
710

811
// Helper function to convert a file to a format Gemini can understand
912
function fileToGenerativePart(path, mimeType) {
1013
return {
1114
inlineData: {
1215
data: fs.readFileSync(path).toString("base64"),
13-
mimeType
16+
mimeType,
1417
},
1518
};
1619
}
@@ -20,12 +23,10 @@ function fileToGenerativePart(path, mimeType) {
2023
// @access Private
2124
const uploadReceipt = async (req, res) => {
2225
if (!req.file) {
23-
return res.status(400).json({ message: 'Please upload a file' });
26+
return res.status(400).json({ message: "Please upload a file" });
2427
}
2528

2629
try {
27-
const model = genAI.getGenerativeModel({ model: "gemini-1.5-flash-latest" });
28-
2930
const prompt = `
3031
Analyze this receipt image. Extract the following details:
3132
- merchant: The name of the store or merchant.
@@ -36,24 +37,39 @@ const uploadReceipt = async (req, res) => {
3637
Return the result as a single, minified JSON object. For example:
3738
{"merchant":"Walmart","amount":42.97,"date":"2025-09-13","category":"Groceries"}
3839
`;
39-
40+
4041
const imagePart = fileToGenerativePart(req.file.path, req.file.mimetype);
4142

42-
const result = await model.generateContent([prompt, imagePart]);
43-
const response = await result.response;
44-
let text = response.text();
43+
const result = await client.models.generateContent({
44+
model: "gemini-2.5-flash-lite",
45+
contents: [{ role: "user", parts: [{ text: prompt }, imagePart] }],
46+
});
47+
48+
const raw =
49+
result.candidates?.[0]?.content?.parts?.map((p) => p.text).join("\n\n") ??
50+
"";
4551

46-
text = text.replace(/```json/g, '').replace(/```/g, '').trim();
47-
const extractedData = JSON.parse(text);
52+
const cleanedText = raw
53+
.replace(/^[\s`]*```json[\s`]*/i, "") // Remove opening ```json with spaces
54+
.replace(/[\s`]*```$/i, "") // Remove closing ```
55+
.trim();
56+
57+
let extractedData;
58+
try {
59+
extractedData = JSON.parse(cleanedText);
60+
} catch (e) {
61+
console.warn("[Gemini] Invalid JSON, fallback to defaults.", e);
62+
extractedData = {};
63+
}
4864

4965
const newReceipt = new Receipt({
5066
user: req.user.id,
5167
fileUrl: `/uploads/${req.file.filename}`,
5268
extractedData: {
5369
amount: extractedData.amount || 0,
54-
category: extractedData.category || 'Miscellaneous',
70+
category: extractedData.category || "Miscellaneous",
5571
date: extractedData.date ? new Date(extractedData.date) : new Date(),
56-
merchant: extractedData.merchant || 'Unknown Merchant',
72+
merchant: extractedData.merchant || "Unknown Merchant",
5773
},
5874
});
5975

@@ -73,10 +89,14 @@ const uploadReceipt = async (req, res) => {
7389
}
7490

7591
res.status(201).json(savedReceipt);
76-
7792
} catch (error) {
78-
console.error('Error with Gemini API:', error);
79-
res.status(500).json({ message: 'Failed to process receipt with AI', error: error.message });
93+
console.error("Error with Gemini API:", error);
94+
res
95+
.status(500)
96+
.json({
97+
message: "Failed to process receipt with AI",
98+
error: error.message,
99+
});
80100
} finally {
81101
// Deleting the temporary file from the server
82102
fs.unlinkSync(req.file.path);
@@ -85,4 +105,4 @@ const uploadReceipt = async (req, res) => {
85105

86106
module.exports = {
87107
uploadReceipt,
88-
};
108+
};

0 commit comments

Comments
 (0)