File size: 2,771 Bytes
32cf8db
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
import express from 'express';
import { SystemMessage, HumanMessage, Runnable, LlamaCppLLM } from './src/index.js';
import bodyParser from 'body-parser';
import path from 'path';
import fs from 'fs';

// Classify Logic
class EmailClassifierRunnable extends Runnable {
    constructor(llm) {
        super();
        this.llm = llm;
    }
    async _call(input, config) {
        // Mock fallback if model fails
        if (!this.llm) return { category: "Error", confidence: 0, reason: "Model not initialized" };
        
        const messages = this._buildPrompt(input);
        const response = await this.llm.invoke(messages, config);
        return this._parseClassification(response.content);
    }
    _buildPrompt(email) {
        return [
            new SystemMessage(`You are an email classification assistant. Classify into: Spam, Invoice, Meeting Request, Urgent, Personal, Other. Respond in JSON like {"category": "X", "confidence": 0.9, "reason": "Y"}.`),
            new HumanMessage(`Classify:\nSubject: ${email.subject}\nBody: ${email.body}`)
        ];
    }
    _parseClassification(response) {
        try {
            const jsonMatch = response.match(/\{[\s\S]*\}/);
            if (!jsonMatch) throw new Error('No JSON found');
            return JSON.parse(jsonMatch[0]);
        } catch (e) { return { category: 'Other', confidence: 0, reason: 'Failed to parse JSON', raw: response }; }
    }
}

const app = express();
const PORT = 7860;

app.use(bodyParser.json());

let classifier = null;

async function initModel() {
    try {
        console.log("Loading model...");
        // Ensure model exists
        if (!fs.existsSync('./models/Qwen3-1.7B-Q8_0.gguf')) {
            console.error("Model file missing!");
            return;
        }

        const llm = new LlamaCppLLM({
            modelPath: './models/Qwen3-1.7B-Q8_0.gguf',
            temperature: 0.1,
            maxTokens: 200
        });
        
        // Warmup
        await llm.invoke("Hi");
        
        classifier = new EmailClassifierRunnable(llm);
        console.log("Model loaded successfully!");
    } catch (err) {
        console.error("Failed to load model:", err);
    }
}

app.post('/classify', async (req, res) => {
    if (!classifier) return res.status(503).json({ error: "Model loading or failed" });
    try {
        const { subject, body } = req.body;
        const result = await classifier.invoke({ subject, body, from: 'api' });
        res.json(result);
    } catch (error) {
        res.status(500).json({ error: error.message });
    }
});

app.get('/', (req, res) => res.send('AI Email Classifier Running. POST /classify to use.'));

app.listen(PORT, '0.0.0.0', () => {
    console.log(`Server listening on ${PORT}`);
    initModel();
});