console.log("--> SERVER STARTING...");
import express from 'express';
// --- DYNAMIC IMPORT ---
let SystemMessage, HumanMessage, AIMessage, LlamaCppLLM;
try {
const module = await import('./src/index.js');
SystemMessage = module.SystemMessage;
HumanMessage = module.HumanMessage;
AIMessage = module.AIMessage;
LlamaCppLLM = module.LlamaCppLLM;
console.log("--> Modules loaded successfully");
} catch (e) {
console.error("--> FATAL IMPORT ERROR:", e);
}
import bodyParser from 'body-parser';
import fs from 'fs';
import path from 'path';
// --- CONFIGURATION ---
const PORT = 7860;
const MODEL_PATH = './models/Qwen3-1.7B-Q8_0.gguf';
const MODEL_NAME = "dahanhstd-1.0"; // Tên model tùy chỉnh
// --- LOAD PROMPTS ---
const PROMPTS = {
"default": "You are a helpful AI assistant. Answer concisely.",
"talk2people": fs.existsSync('MasterPrompt_Talk2People.txt')
? fs.readFileSync('MasterPrompt_Talk2People.txt', 'utf-8')
: "You are a creative Video Director specializing in realistic Vietnamese scenes.",
"coder": "You are an expert programmer."
};
// --- HTML TEMPLATE (GIAO DIỆN CHAT) ---
const HTML_PAGE = `
Dạ Hành AI Studio
`;
// --- AI ENGINE ---
let llm = null;
async function initModel() {
if (!LlamaCppLLM) return;
try {
console.log('--> Loading model...');
if (!fs.existsSync(MODEL_PATH)) {
console.error(`--> Model not found at ${MODEL_PATH}`);
// Fallback: check if we are in /app
return;
}
llm = new LlamaCppLLM({
modelPath: MODEL_PATH,
temperature: 0.7,
maxTokens: 1024,
contextSize: 4096, // Limit context for speed
threads: 4, // Maximize CPU usage (HF Space usually has 2-4 vCPU)
batchSize: 512, // Process inputs faster
f16Kv: true // Faster KV cache
});
await llm.invoke("Hello");
console.log('--> Model loaded successfully.');
} catch (err) {
console.error('--> FATAL MODEL ERROR:', err.message);
}
}
// --- SERVER SETUP ---
const app = express();
app.use(bodyParser.json());
// 1. API: CHAT (Public API for other apps)
app.post('/chat', async (req, res) => {
// API Response Format
const apiResponse = {
model: MODEL_NAME,
created: Date.now(),
reply: "",
error: null
};
if (!llm) {
apiResponse.error = "System initializing or Model missing";
return res.status(503).json(apiResponse);
}
try {
const { message, history = [], role = 'default' } = req.body;
const systemInstruction = PROMPTS[role] || PROMPTS['default'];
const messages = [new SystemMessage(systemInstruction)];
history.forEach(msg => {
if (msg.role === 'user') messages.push(new HumanMessage(msg.content));
if (msg.role === 'ai') messages.push(new AIMessage(msg.content));
});
messages.push(new HumanMessage(message));
const response = await llm.invoke(messages);
apiResponse.reply = response.content;
res.json(apiResponse);
} catch (error) {
apiResponse.error = error.message;
res.status(500).json(apiResponse);
}
});
// 2. API: INFO
app.get('/info', (req, res) => {
res.json({
model: MODEL_NAME,
status: llm ? "ready" : "loading",
roles: Object.keys(PROMPTS)
});
});
// 3. UI: HOME PAGE (Direct HTML Render)
app.get('/', (req, res) => {
res.send(HTML_PAGE);
});
app.listen(PORT, '0.0.0.0', () => {
console.log(`--> Server listening on ${PORT}`);
initModel();
});