Rework AI

This commit is contained in:
Aslan 2025-12-28 23:11:33 +01:00
parent e46c4427cc
commit aebee54562
10 changed files with 79 additions and 20 deletions

View file

@ -1,6 +1,6 @@
{ {
"name": "aslobot-matrix", "name": "aslobot-matrix",
"version": "0.7.2", "version": "0.8.0",
"description": "", "description": "",
"license": "ISC", "license": "ISC",
"author": "", "author": "",

View file

@ -1,5 +1,6 @@
{ {
"baseUrl": "https://", "baseUrl": "https://",
"server": "",
"userId": "@", "userId": "@",
"authPath": "auth.json", "authPath": "auth.json",
"storePath": "store.json", "storePath": "store.json",
@ -25,7 +26,14 @@
"api": { "api": {
"key": "" "key": ""
}, },
"prompt": "Your name is Aslobot. Be concise, try to keep text as short as possible. Be helpful." "personalities": [
{
"personality": "You are Aslobot. Be helpful. Be concise, keep text as short as possible.",
"likes": [],
"dislikes": [],
"timeout": 3600000
}
]
} }
} }
} }

View file

@ -3,9 +3,10 @@ import type { ICallbackStore } from "../types.js";
import { config } from "../../config.js"; import { config } from "../../config.js";
import { getTextGemini, getImageGemini } from "../../services/ai/ai.js"; import { getTextGemini, getImageGemini } from "../../services/ai/ai.js";
import { alts } from "./alts.js"; import { alts } from "./alts.js";
import type { IAdminInstructions, IAIAlt } from "./types.js"; import type { IAIInstructions } from "./types.js";
import { getUserById, getUserName } from "../../helpers.js"; import { getUserById, getUserName } from "../../helpers.js";
import { prices } from "./prices.js"; import { prices } from "./prices.js";
import { state } from "../../store/store.js";
let client: MatrixClient; let client: MatrixClient;
@ -34,21 +35,41 @@ const onAI = async (text: string, roomId: string, sender: string) => {
return; return;
} }
let personality = config.app.ai.personalities[state.personality.index];
if (
Date.now() >
state.personality.startTime + (personality?.timeout ?? 0)
) {
const randomInt = Math.floor(
Math.random() * (config.app.ai.personalities.length + 1),
);
state.personality = {
index: randomInt,
startTime: Date.now(),
};
}
personality = config.app.ai.personalities[state.personality.index];
let textMod = text.replace("!ai", "").trim().toLowerCase(); let textMod = text.replace("!ai", "").trim().toLowerCase();
let instructions = { let instructions = {
prefferedLanguages: ["english", "slovak"], prefferedLanguages: ["english", "slovak"],
adminText: config.app.ai.prompt, users: alts.map((alt) => ({
alts: alts.map((alt) => ({ names: alt.keys,
keys: alt.keys,
alt: alt.alt, alt: alt.alt,
information: user.information, backstory: alt.id
? getUserById(`${alt.id}:${config.server}`).information
: undefined,
})), })),
} as IAdminInstructions; aiPersonality: personality?.personality ?? "",
aiLikes: personality?.likes ?? "",
aiDislikes: personality?.dislikes ?? "",
} as IAIInstructions;
const username = getUserName(user); const username = getUserName(user);
textMod = `Admin Instructions:\n${JSON.stringify(instructions)}\nPrompt by ${username}:\n${textMod}`; textMod = `${username}:\n${textMod}`;
const responseAI = await getTextGemini(textMod); const responseAI = await getTextGemini(instructions, textMod);
user.aiCost += responseAI.tokens * prices.text; user.aiCost += responseAI.tokens * prices.text;

View file

@ -2,6 +2,7 @@ import type { IAIAlt } from "./types.js";
const alts: IAIAlt[] = [ const alts: IAIAlt[] = [
{ {
id: "@coty",
keys: [ keys: [
"satek", "satek",
"sateg", "sateg",
@ -22,10 +23,12 @@ const alts: IAIAlt[] = [
alt: "white cat", alt: "white cat",
}, },
{ {
id: "@marketing",
keys: ["gabor", "gaber", "martin", "marting"], keys: ["gabor", "gaber", "martin", "marting"],
alt: "hedgehog", alt: "hedgehog",
}, },
{ {
id: "@madys",
keys: [ keys: [
"madys", "madys",
"mandak", "mandak",
@ -39,10 +42,12 @@ const alts: IAIAlt[] = [
alt: "beaver", alt: "beaver",
}, },
{ {
id: "@aslan2142",
keys: ["janys", "jano", "janeg", "janek", "aslanek", "aslan", "aslo"], keys: ["janys", "jano", "janeg", "janek", "aslanek", "aslan", "aslo"],
alt: "lion", alt: "lion",
}, },
{ {
id: "@rod",
keys: ["marek", "mareg", "macek", "maceg", "rod"], keys: ["marek", "mareg", "macek", "maceg", "rod"],
alt: "purple snake", alt: "purple snake",
}, },
@ -56,7 +61,7 @@ const alts: IAIAlt[] = [
}, },
{ {
keys: ["mama", "monika", "monik"], keys: ["mama", "monika", "monik"],
alt: "god's peasant", alt: "god's peasant woman",
}, },
{ {
keys: ["puk", "pucik", "pucig"], keys: ["puk", "pucik", "pucig"],

View file

@ -1,13 +1,21 @@
interface IAIAlt { interface IAIAlt {
id?: string;
keys: string[]; keys: string[];
alt: string; alt: string;
information?: string | undefined;
} }
interface IAdminInstructions { interface IAIUser {
names: string[];
alt: string;
backstory?: string | undefined;
}
interface IAIInstructions {
prefferedLanguages: string[]; prefferedLanguages: string[];
adminText: string; users: IAIUser[];
alts: IAIAlt[]; aiPersonality: string;
aiLikes: string;
aiDislikes: string;
} }
export { type IAIAlt, type IAdminInstructions }; export { type IAIAlt, type IAIUser, type IAIInstructions };

View file

@ -61,7 +61,7 @@ const onMissingRole = (
client.sendHtmlMessage( client.sendHtmlMessage(
roomId, roomId,
"", "",
`You are missing the required role.<br/>Your current role is <b>${userRole}</b>`, `You don't have a permission to do that!<br/>Your current role is <b>${userRole}</b>`,
); );
}; };

View file

@ -98,7 +98,7 @@ const onAILeaderboard = (_text: string, roomId: string) => {
const cost = user.aiCost; const cost = user.aiCost;
const username = getUserName(user); const username = getUserName(user);
return `<li>${username}: cost <b>${cost.toFixed(2)}$</b></li>`; return `<li>${username}: <b>${cost.toFixed(2)}$</b></li>`;
}; };
const users = state.users.sort( const users = state.users.sort(

View file

@ -1,15 +1,22 @@
import { GoogleGenAI } from "@google/genai"; import { GoogleGenAI } from "@google/genai";
import { config } from "../../config.js"; import { config } from "../../config.js";
import type { AIResponseImage, AIResponseText } from "./types.js"; import type { AIResponseImage, AIResponseText } from "./types.js";
import type { IAIInstructions } from "../../modules/ai/types.js";
const googleAI = new GoogleGenAI({ const googleAI = new GoogleGenAI({
apiKey: config.app.ai.api.key, apiKey: config.app.ai.api.key,
}); });
const getTextGemini = async (input: string): Promise<AIResponseText> => { const getTextGemini = async (
instructions: IAIInstructions,
input: string,
): Promise<AIResponseText> => {
const response = await googleAI.models.generateContent({ const response = await googleAI.models.generateContent({
model: "gemini-3-flash-preview", model: "gemini-3-flash-preview",
contents: input, contents: input,
config: {
systemInstruction: JSON.stringify(instructions),
},
}); });
return { return {

View file

@ -6,6 +6,10 @@ import type { IState } from "./types.js";
let state: IState = { let state: IState = {
users: [], users: [],
personality: {
index: 0,
startTime: 0,
},
}; };
const load = () => { const load = () => {

View file

@ -1,5 +1,6 @@
interface IState { interface IState {
users: IUser[]; users: IUser[];
personality: IPersonality;
} }
interface IUser { interface IUser {
@ -16,4 +17,9 @@ interface IUser {
type TRole = "NONE" | "USER" | "MODERATOR" | "ADMIN"; type TRole = "NONE" | "USER" | "MODERATOR" | "ADMIN";
export { type IState, type IUser, type TRole }; interface IPersonality {
index: number;
startTime: number;
}
export { type IState, type IUser, type TRole, type IPersonality };