Skip to content

Commit 6099585

Browse files
Merge pull request #218 from ReDI-School/Feature/ai_integration
Feature/ai integration
2 parents bc1e5ab + 3dc3a56 commit 6099585

File tree

4 files changed

+77
-2
lines changed

4 files changed

+77
-2
lines changed

backend/src/controllers/pinController.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
} from "../constants/http.js";
1111

1212
import { uploadToS3 } from "../services/uploadService.js";
13-
// import * as tagGenerationService from "../services/tagGenerationService.js";
13+
import { generateData } from "../services/dataGenerationService.js";
1414

1515
/**
1616
* POST /api/pin/upload-and-tag
@@ -33,7 +33,7 @@ export const uploadAndTag = async (req, res) => {
3333
// AI tags generation Part
3434
// TODO : replace the empty array [] with a call to generateTags from tagGenService which should take image url and return an array of tags
3535
// TODO : Create tagGenService in the services folder
36-
const aiTags = [];
36+
const aiTags = await generateData(imageUrl);
3737
console.info("AI generated tags:", aiTags);
3838

3939
res.json({
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
// services/tagGenerationService.js
2+
import axios from "axios";
3+
import dotenv from "dotenv";
4+
dotenv.config();
5+
6+
const BASE_URL = "https://api-inference.huggingface.co/models";
7+
const MODEL = "google/vit-base-patch16-224";
8+
const API_KEY = process.env.HUGGING_FACE_API_KEY || null;
9+
10+
/**
11+
* Clean a label from Hugging Face API
12+
*/
13+
const cleanLabel = label =>
14+
label
15+
.split(",")[0]
16+
.toLowerCase()
17+
.replace(/[^a-z0-9\s]/g, "") // Remove special characters
18+
.replace(/\s+/g, " ") // Normalize whitespace
19+
.trim();
20+
21+
/**
22+
* Hugging Face model call
23+
*/
24+
const generateTagsWithHuggingFace = async imageUrl => {
25+
try {
26+
console.log("Generating tags with Hugging Face...");
27+
28+
// Download image from URL should change this later
29+
const imageResponse = await axios.get(imageUrl, {
30+
responseType: "arraybuffer"
31+
});
32+
33+
const imageBuffer = Buffer.from(imageResponse.data, "binary");
34+
35+
const headers = {
36+
"Content-Type": "application/octet-stream"
37+
};
38+
39+
if (API_KEY) {
40+
headers["Authorization"] = `Bearer ${API_KEY}`;
41+
}
42+
43+
// Send image buffer as binary
44+
const response = await axios.post(`${BASE_URL}/${MODEL}`, imageBuffer, {
45+
headers,
46+
timeout: 15000
47+
});
48+
console.log("response . data ", response.data);
49+
if (Array.isArray(response.data)) {
50+
const tags = response.data.map(item => cleanLabel(item.label));
51+
console.log("Tags generated:", tags);
52+
return tags;
53+
}
54+
55+
return [];
56+
} catch (err) {
57+
console.error("Hugging Face API error:", err);
58+
throw err;
59+
}
60+
};
61+
62+
/**
63+
* Main entry function
64+
*/
65+
export const generateData = async imageUrl => {
66+
try {
67+
const tags = await generateTagsWithHuggingFace(imageUrl);
68+
if (tags && tags.length > 0) return tags;
69+
} catch (err) {
70+
console.error("generateTags error:", err);
71+
}
72+
};

package-lock.json

Lines changed: 2 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
"prettier": "^3.5.3"
2525
},
2626
"dependencies": {
27+
2728
"axios": "^1.10.0"
2829
}
2930
}

0 commit comments

Comments
 (0)