Update efficiency 3 pickaxes
This commit is contained in:
@@ -7,6 +7,17 @@ import bodyParser from "body-parser";
|
|||||||
import Database from "better-sqlite3";
|
import Database from "better-sqlite3";
|
||||||
import FileStoreFactory from "session-file-store";
|
import FileStoreFactory from "session-file-store";
|
||||||
import {exec} from "child_process";
|
import {exec} from "child_process";
|
||||||
|
import {performance} from "perf_hooks";
|
||||||
|
|
||||||
|
let last = performance.now();
|
||||||
|
setInterval(() => {
|
||||||
|
const now = performance.now();
|
||||||
|
const drift = now - last - 1000;
|
||||||
|
last = now;
|
||||||
|
if (drift > 50) {
|
||||||
|
console.log("EVENT LOOP LAG", Math.round(drift), "ms", new Date().toISOString());
|
||||||
|
}
|
||||||
|
}, 1000);
|
||||||
|
|
||||||
const modelState = new Map();
|
const modelState = new Map();
|
||||||
const app = express();
|
const app = express();
|
||||||
@@ -14,6 +25,18 @@ const PORT = 3000;
|
|||||||
const DB_PATH = "./data/app.db";
|
const DB_PATH = "./data/app.db";
|
||||||
const SESSIONS_DIR = path.resolve("sessions");
|
const SESSIONS_DIR = path.resolve("sessions");
|
||||||
const UNLOAD_AFTER_MS = 30 * 1000;
|
const UNLOAD_AFTER_MS = 30 * 1000;
|
||||||
|
let modelsCache = null;
|
||||||
|
let modelsCacheAt = 0;
|
||||||
|
const MODELS_TTL_MS = 5 * 60 * 1000;
|
||||||
|
|
||||||
|
app.use((req, res, next) => {
|
||||||
|
const start = Date.now();
|
||||||
|
res.on("finish", () => {
|
||||||
|
const ms = Date.now() - start;
|
||||||
|
if (ms > 50) console.log("SLOW REQ", ms + "ms", req.method, req.url);
|
||||||
|
});
|
||||||
|
next();
|
||||||
|
});
|
||||||
|
|
||||||
if (!fs.existsSync("./data")) {
|
if (!fs.existsSync("./data")) {
|
||||||
fs.mkdirSync("./data", {recursive: true});
|
fs.mkdirSync("./data", {recursive: true});
|
||||||
@@ -57,212 +80,212 @@ db.prepare(`
|
|||||||
CREATE TABLE IF NOT EXISTS users
|
CREATE TABLE IF NOT EXISTS users
|
||||||
(
|
(
|
||||||
username
|
username
|
||||||
TEXT
|
TEXT
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY,
|
KEY,
|
||||||
password
|
password
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL
|
NULL
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS chats
|
CREATE TABLE IF NOT EXISTS chats
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
INTEGER
|
INTEGER
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY
|
KEY
|
||||||
AUTOINCREMENT,
|
AUTOINCREMENT,
|
||||||
username
|
username
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
role
|
role
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
content
|
content
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
created_at
|
created_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP
|
CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS chat_sessions
|
CREATE TABLE IF NOT EXISTS chat_sessions
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
INTEGER
|
INTEGER
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY
|
KEY
|
||||||
AUTOINCREMENT,
|
AUTOINCREMENT,
|
||||||
username
|
username
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
title
|
title
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
created_at
|
created_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP,
|
CURRENT_TIMESTAMP,
|
||||||
updated_at
|
updated_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP
|
CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS chat_messages
|
CREATE TABLE IF NOT EXISTS chat_messages
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
INTEGER
|
INTEGER
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY
|
KEY
|
||||||
AUTOINCREMENT,
|
AUTOINCREMENT,
|
||||||
chat_id
|
chat_id
|
||||||
INTEGER
|
INTEGER
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
role
|
role
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
content
|
content
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
created_at
|
created_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP,
|
CURRENT_TIMESTAMP,
|
||||||
FOREIGN
|
FOREIGN
|
||||||
KEY
|
KEY
|
||||||
(
|
(
|
||||||
chat_id
|
chat_id
|
||||||
) REFERENCES chat_sessions
|
) REFERENCES chat_sessions
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
) ON DELETE CASCADE
|
) ON DELETE CASCADE
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS personas
|
CREATE TABLE IF NOT EXISTS personas
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
INTEGER
|
INTEGER
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY
|
KEY
|
||||||
AUTOINCREMENT,
|
AUTOINCREMENT,
|
||||||
username
|
username
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
name
|
name
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
pronouns
|
pronouns
|
||||||
TEXT,
|
TEXT,
|
||||||
appearance
|
appearance
|
||||||
TEXT,
|
TEXT,
|
||||||
background
|
background
|
||||||
TEXT,
|
TEXT,
|
||||||
details
|
details
|
||||||
TEXT,
|
TEXT,
|
||||||
persona_type
|
persona_type
|
||||||
TEXT
|
TEXT
|
||||||
DEFAULT
|
DEFAULT
|
||||||
'assistant',
|
'assistant',
|
||||||
created_at
|
created_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP,
|
CURRENT_TIMESTAMP,
|
||||||
updated_at
|
updated_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP
|
CURRENT_TIMESTAMP
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS user_settings
|
CREATE TABLE IF NOT EXISTS user_settings
|
||||||
(
|
(
|
||||||
username
|
username
|
||||||
TEXT
|
TEXT
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY,
|
KEY,
|
||||||
active_persona_id
|
active_persona_id
|
||||||
INTEGER,
|
INTEGER,
|
||||||
active_user_persona_id
|
active_user_persona_id
|
||||||
INTEGER,
|
INTEGER,
|
||||||
FOREIGN
|
FOREIGN
|
||||||
KEY
|
KEY
|
||||||
(
|
(
|
||||||
active_persona_id
|
active_persona_id
|
||||||
) REFERENCES personas
|
) REFERENCES personas
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
) ON DELETE SET NULL,
|
) ON DELETE SET NULL,
|
||||||
FOREIGN
|
FOREIGN
|
||||||
KEY
|
KEY
|
||||||
(
|
(
|
||||||
active_user_persona_id
|
active_user_persona_id
|
||||||
) REFERENCES personas
|
) REFERENCES personas
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
) ON DELETE SET NULL
|
) ON DELETE SET NULL
|
||||||
)
|
)
|
||||||
`).run();
|
`).run();
|
||||||
db.prepare(`
|
db.prepare(`
|
||||||
CREATE TABLE IF NOT EXISTS persona_market
|
CREATE TABLE IF NOT EXISTS persona_market
|
||||||
(
|
(
|
||||||
id
|
id
|
||||||
INTEGER
|
INTEGER
|
||||||
PRIMARY
|
PRIMARY
|
||||||
KEY
|
KEY
|
||||||
AUTOINCREMENT,
|
AUTOINCREMENT,
|
||||||
persona_id
|
persona_id
|
||||||
INTEGER,
|
INTEGER,
|
||||||
creator_username
|
creator_username
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
name
|
name
|
||||||
TEXT
|
TEXT
|
||||||
NOT
|
NOT
|
||||||
NULL,
|
NULL,
|
||||||
pronouns
|
pronouns
|
||||||
TEXT,
|
TEXT,
|
||||||
appearance
|
appearance
|
||||||
TEXT,
|
TEXT,
|
||||||
background
|
background
|
||||||
TEXT,
|
TEXT,
|
||||||
details
|
details
|
||||||
TEXT,
|
TEXT,
|
||||||
persona_type
|
persona_type
|
||||||
TEXT
|
TEXT
|
||||||
DEFAULT
|
DEFAULT
|
||||||
'assistant',
|
'assistant',
|
||||||
created_at
|
created_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP,
|
CURRENT_TIMESTAMP,
|
||||||
updated_at
|
updated_at
|
||||||
DATETIME
|
DATETIME
|
||||||
DEFAULT
|
DEFAULT
|
||||||
CURRENT_TIMESTAMP,
|
CURRENT_TIMESTAMP,
|
||||||
UNIQUE
|
UNIQUE
|
||||||
(
|
(
|
||||||
persona_id,
|
persona_id,
|
||||||
creator_username
|
creator_username
|
||||||
|
)
|
||||||
)
|
)
|
||||||
)
|
|
||||||
`).run();
|
`).run();
|
||||||
|
|
||||||
const insertUserStmt = db.prepare("INSERT INTO users (username, password) VALUES (?, ?)");
|
const insertUserStmt = db.prepare("INSERT INTO users (username, password) VALUES (?, ?)");
|
||||||
@@ -273,7 +296,6 @@ const getLegacyChatsStmt = db.prepare(`
|
|||||||
WHERE username = ?
|
WHERE username = ?
|
||||||
ORDER BY datetime(created_at)
|
ORDER BY datetime(created_at)
|
||||||
`);
|
`);
|
||||||
const deleteLegacyChatsStmt = db.prepare("DELETE FROM chats WHERE username = ?");
|
|
||||||
const insertChatSessionStmt = db.prepare(
|
const insertChatSessionStmt = db.prepare(
|
||||||
"INSERT INTO chat_sessions (username, title) VALUES (?, ?)"
|
"INSERT INTO chat_sessions (username, title) VALUES (?, ?)"
|
||||||
);
|
);
|
||||||
@@ -306,10 +328,6 @@ const deleteChatSessionStmt = db.prepare(
|
|||||||
"DELETE FROM chat_sessions WHERE id = ? AND username = ?"
|
"DELETE FROM chat_sessions WHERE id = ? AND username = ?"
|
||||||
);
|
);
|
||||||
|
|
||||||
const deleteAllChatSessionsStmt = db.prepare(
|
|
||||||
"DELETE FROM chat_sessions WHERE username = ?"
|
|
||||||
);
|
|
||||||
|
|
||||||
const insertChatMessageStmt = db.prepare(
|
const insertChatMessageStmt = db.prepare(
|
||||||
"INSERT INTO chat_messages (chat_id, role, content) VALUES (?, ?, ?)"
|
"INSERT INTO chat_messages (chat_id, role, content) VALUES (?, ?, ?)"
|
||||||
);
|
);
|
||||||
@@ -326,7 +344,8 @@ const getRecentChatMessagesStmt = db.prepare(`
|
|||||||
SELECT role, content
|
SELECT role, content
|
||||||
FROM chat_messages
|
FROM chat_messages
|
||||||
WHERE chat_id = ?
|
WHERE chat_id = ?
|
||||||
ORDER BY datetime(created_at) DESC LIMIT 20
|
ORDER BY datetime(created_at) DESC
|
||||||
|
LIMIT 20
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
@@ -336,16 +355,26 @@ const deleteChatMessagesStmt = db.prepare(
|
|||||||
);
|
);
|
||||||
|
|
||||||
const listPersonasByTypeStmt = db.prepare(`
|
const listPersonasByTypeStmt = db.prepare(`
|
||||||
SELECT id, name, pronouns, appearance, background, details, persona_type, created_at, updated_at
|
SELECT id,
|
||||||
|
name,
|
||||||
|
pronouns,
|
||||||
|
appearance,
|
||||||
|
background,
|
||||||
|
details,
|
||||||
|
persona_type,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
FROM personas
|
FROM personas
|
||||||
WHERE username = ? AND persona_type = ?
|
WHERE username = ?
|
||||||
|
AND persona_type = ?
|
||||||
ORDER BY datetime(updated_at) DESC
|
ORDER BY datetime(updated_at) DESC
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const getPersonaStmt = db.prepare(`
|
const getPersonaStmt = db.prepare(`
|
||||||
SELECT id, name, pronouns, appearance, background, details, persona_type
|
SELECT id, name, pronouns, appearance, background, details, persona_type
|
||||||
FROM personas
|
FROM personas
|
||||||
WHERE id = ? AND username = ?
|
WHERE id = ?
|
||||||
|
AND username = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const insertPersonaStmt = db.prepare(
|
const insertPersonaStmt = db.prepare(
|
||||||
@@ -354,8 +383,14 @@ const insertPersonaStmt = db.prepare(
|
|||||||
|
|
||||||
const updatePersonaStmt = db.prepare(`
|
const updatePersonaStmt = db.prepare(`
|
||||||
UPDATE personas
|
UPDATE personas
|
||||||
SET name = ?, pronouns = ?, appearance = ?, background = ?, details = ?, updated_at = CURRENT_TIMESTAMP
|
SET name = ?,
|
||||||
WHERE id = ? AND username = ?
|
pronouns = ?,
|
||||||
|
appearance = ?,
|
||||||
|
background = ?,
|
||||||
|
details = ?,
|
||||||
|
updated_at = CURRENT_TIMESTAMP
|
||||||
|
WHERE id = ?
|
||||||
|
AND username = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const deletePersonaStmt = db.prepare(
|
const deletePersonaStmt = db.prepare(
|
||||||
@@ -381,46 +416,73 @@ const setActiveUserPersonaStmt = db.prepare(`
|
|||||||
const getActivePersonaStmt = db.prepare(`
|
const getActivePersonaStmt = db.prepare(`
|
||||||
SELECT p.id, p.name, p.pronouns, p.appearance, p.background, p.details
|
SELECT p.id, p.name, p.pronouns, p.appearance, p.background, p.details
|
||||||
FROM user_settings us
|
FROM user_settings us
|
||||||
JOIN personas p ON p.id = us.active_persona_id
|
JOIN personas p ON p.id = us.active_persona_id
|
||||||
WHERE us.username = ?
|
WHERE us.username = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const getActiveUserPersonaStmt = db.prepare(`
|
const getActiveUserPersonaStmt = db.prepare(`
|
||||||
SELECT p.id, p.name, p.pronouns, p.appearance, p.background, p.details
|
SELECT p.id, p.name, p.pronouns, p.appearance, p.background, p.details
|
||||||
FROM user_settings us
|
FROM user_settings us
|
||||||
JOIN personas p ON p.id = us.active_user_persona_id
|
JOIN personas p ON p.id = us.active_user_persona_id
|
||||||
WHERE us.username = ?
|
WHERE us.username = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const listMarketPersonasStmt = db.prepare(`
|
const listMarketPersonasStmt = db.prepare(`
|
||||||
SELECT id, persona_id, creator_username, name, pronouns, appearance, background, details, persona_type, created_at, updated_at
|
SELECT id,
|
||||||
|
persona_id,
|
||||||
|
creator_username,
|
||||||
|
name,
|
||||||
|
pronouns,
|
||||||
|
appearance,
|
||||||
|
background,
|
||||||
|
details,
|
||||||
|
persona_type,
|
||||||
|
created_at,
|
||||||
|
updated_at
|
||||||
FROM persona_market
|
FROM persona_market
|
||||||
ORDER BY datetime(updated_at) DESC
|
ORDER BY datetime(updated_at) DESC
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const getMarketPersonaStmt = db.prepare(`
|
const getMarketPersonaStmt = db.prepare(`
|
||||||
SELECT id, persona_id, creator_username, name, pronouns, appearance, background, details, persona_type
|
SELECT id,
|
||||||
|
persona_id,
|
||||||
|
creator_username,
|
||||||
|
name,
|
||||||
|
pronouns,
|
||||||
|
appearance,
|
||||||
|
background,
|
||||||
|
details,
|
||||||
|
persona_type
|
||||||
FROM persona_market
|
FROM persona_market
|
||||||
WHERE id = ?
|
WHERE id = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const getMarketPersonaByPersonaIdStmt = db.prepare(`
|
const getMarketPersonaByPersonaIdStmt = db.prepare(`
|
||||||
SELECT id, persona_id, creator_username, name, pronouns, appearance, background, details, persona_type
|
SELECT id,
|
||||||
|
persona_id,
|
||||||
|
creator_username,
|
||||||
|
name,
|
||||||
|
pronouns,
|
||||||
|
appearance,
|
||||||
|
background,
|
||||||
|
details,
|
||||||
|
persona_type
|
||||||
FROM persona_market
|
FROM persona_market
|
||||||
WHERE persona_id = ? AND creator_username = ?
|
WHERE persona_id = ?
|
||||||
|
AND creator_username = ?
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const upsertMarketPersonaStmt = db.prepare(`
|
const upsertMarketPersonaStmt = db.prepare(`
|
||||||
INSERT INTO persona_market (persona_id, creator_username, name, pronouns, appearance, background, details, persona_type)
|
INSERT INTO persona_market (persona_id, creator_username, name, pronouns, appearance, background, details,
|
||||||
|
persona_type)
|
||||||
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||||
ON CONFLICT(persona_id, creator_username) DO UPDATE SET
|
ON CONFLICT(persona_id, creator_username) DO UPDATE SET name = excluded.name,
|
||||||
name = excluded.name,
|
pronouns = excluded.pronouns,
|
||||||
pronouns = excluded.pronouns,
|
appearance = excluded.appearance,
|
||||||
appearance = excluded.appearance,
|
background = excluded.background,
|
||||||
background = excluded.background,
|
details = excluded.details,
|
||||||
details = excluded.details,
|
persona_type = excluded.persona_type,
|
||||||
persona_type = excluded.persona_type,
|
updated_at = CURRENT_TIMESTAMP
|
||||||
updated_at = CURRENT_TIMESTAMP
|
|
||||||
`);
|
`);
|
||||||
|
|
||||||
const listPublishedPersonaIdsStmt = db.prepare(`
|
const listPublishedPersonaIdsStmt = db.prepare(`
|
||||||
@@ -475,7 +537,10 @@ app.use(bodyParser.json());
|
|||||||
app.use(express.static("public"));
|
app.use(express.static("public"));
|
||||||
app.use(
|
app.use(
|
||||||
session({
|
session({
|
||||||
store: new FileStore({path: SESSIONS_DIR}),
|
store: new FileStore({
|
||||||
|
path: SESSIONS_DIR,
|
||||||
|
reapInterval: 3600
|
||||||
|
}),
|
||||||
secret: "-secret-key-here-",
|
secret: "-secret-key-here-",
|
||||||
resave: false,
|
resave: false,
|
||||||
saveUninitialized: false,
|
saveUninitialized: false,
|
||||||
@@ -548,12 +613,18 @@ const requireLogin = (req, res, next) => {
|
|||||||
|
|
||||||
app.get("/models", async (req, res) => {
|
app.get("/models", async (req, res) => {
|
||||||
try {
|
try {
|
||||||
const response = await fetch("https://ai.krishd.ch/api/tags");
|
if (modelsCache && (Date.now() - modelsCacheAt) < MODELS_TTL_MS) {
|
||||||
if (!response.ok) {
|
return res.json(modelsCache);
|
||||||
return res.status(500).json({error: "Failed to load models"});
|
|
||||||
}
|
}
|
||||||
res.json(await response.json());
|
const controller = new AbortController();
|
||||||
} catch (error) {
|
const t = setTimeout(() => controller.abort(), 4000);
|
||||||
|
const response = await fetch("https://ai.krishd.ch/api/tags", {signal: controller.signal});
|
||||||
|
clearTimeout(t);
|
||||||
|
if (!response.ok) return res.status(500).json({error: "Failed to load models"});
|
||||||
|
modelsCache = await response.json();
|
||||||
|
modelsCacheAt = Date.now();
|
||||||
|
res.json(modelsCache);
|
||||||
|
} catch (e) {
|
||||||
res.status(500).json({error: "Failed to load models"});
|
res.status(500).json({error: "Failed to load models"});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user