Rework AI and add more stats
This commit is contained in:
parent
29832dfce3
commit
c8de53bfc7
14 changed files with 197 additions and 169 deletions
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "aslobot-matrix",
|
"name": "aslobot-matrix",
|
||||||
"version": "0.6.0",
|
"version": "0.7.0",
|
||||||
"description": "",
|
"description": "",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"author": "",
|
"author": "",
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,12 @@
|
||||||
"gain": 5,
|
"gain": 5,
|
||||||
"startingRequirement": 50,
|
"startingRequirement": 50,
|
||||||
"multiplier": 1.25,
|
"multiplier": 1.25,
|
||||||
"timeout": 60000
|
"timeout": 300000
|
||||||
|
},
|
||||||
|
"money": {
|
||||||
|
"gain": 2,
|
||||||
|
"startingValue": 10,
|
||||||
|
"timeout": 3600000
|
||||||
},
|
},
|
||||||
"ai": {
|
"ai": {
|
||||||
"api": {
|
"api": {
|
||||||
|
|
|
||||||
|
|
@ -4,14 +4,31 @@ import { type IUser, type TRole } from "./store/types.js";
|
||||||
import type { ILevel } from "./types.js";
|
import type { ILevel } from "./types.js";
|
||||||
|
|
||||||
const getUserById = (userId: string): IUser => {
|
const getUserById = (userId: string): IUser => {
|
||||||
return (
|
const user = state.users.find((user) => user.id === userId);
|
||||||
state.users.find((user) => user.id === userId) ?? {
|
if (!user) {
|
||||||
|
return {
|
||||||
id: ":",
|
id: ":",
|
||||||
role: "NONE",
|
role: "NONE",
|
||||||
experience: 0,
|
experience: 0,
|
||||||
|
money: 0,
|
||||||
|
aiCost: 0,
|
||||||
lastMessageTimestamp: 0,
|
lastMessageTimestamp: 0,
|
||||||
|
lastExperienceGainTimestamp: 0,
|
||||||
|
lastMoneyGainTimestamp: 0,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
);
|
|
||||||
|
if (!user.experience) {
|
||||||
|
user.experience = 0;
|
||||||
|
}
|
||||||
|
if (!user.money) {
|
||||||
|
user.money = 0;
|
||||||
|
}
|
||||||
|
if (!user.aiCost) {
|
||||||
|
user.aiCost = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return user;
|
||||||
};
|
};
|
||||||
|
|
||||||
const checkRoles = (roles: TRole[], userId: string) => {
|
const checkRoles = (roles: TRole[], userId: string) => {
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,9 @@ 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 } from "./types.js";
|
||||||
|
import { getUserById } from "../../helpers.js";
|
||||||
|
import { prices } from "./prices.js";
|
||||||
|
|
||||||
let client: MatrixClient;
|
let client: MatrixClient;
|
||||||
|
|
||||||
|
|
@ -15,40 +18,58 @@ const registerModuleAI = (
|
||||||
callbackStore.messageCallbacks.push({
|
callbackStore.messageCallbacks.push({
|
||||||
startConditions: [`${config.app.triggerPrefix}ai `],
|
startConditions: [`${config.app.triggerPrefix}ai `],
|
||||||
callbackFunc: onAI,
|
callbackFunc: onAI,
|
||||||
|
allowedRoles: ["USER", "MODERATOR", "ADMIN"],
|
||||||
});
|
});
|
||||||
callbackStore.messageCallbacks.push({
|
callbackStore.messageCallbacks.push({
|
||||||
startConditions: [
|
startConditions: [`${config.app.triggerPrefix}img `],
|
||||||
...alts.map((alt) => `${alt.key} when`),
|
|
||||||
...alts.map((alt) => `${alt.key} ked`),
|
|
||||||
`!img`,
|
|
||||||
],
|
|
||||||
callbackFunc: onImageGen,
|
callbackFunc: onImageGen,
|
||||||
|
allowedRoles: ["USER", "MODERATOR", "ADMIN"],
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onAI = async (text: string, roomId: string) => {
|
const onAI = async (text: string, roomId: string, sender: string) => {
|
||||||
|
const user = getUserById(sender);
|
||||||
|
|
||||||
if (text.trim().length < 5) {
|
if (text.trim().length < 5) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const responseAI = await getTextGemini(text.replace("!ai ", ""));
|
let textMod = text.replace("!ai", "").trim().toLowerCase();
|
||||||
client.sendTextMessage(roomId, responseAI);
|
let instructions = {
|
||||||
|
prefferedLanguages: ["english", "slovak"],
|
||||||
|
adminText: "Be concise, try to keep text as short as possible",
|
||||||
|
alts: alts,
|
||||||
|
} as IAdminInstructions;
|
||||||
|
|
||||||
|
textMod = `Admin Instructions:\n${instructions}\nPrompt:\n${textMod}`;
|
||||||
|
|
||||||
|
const responseAI = await getTextGemini(textMod);
|
||||||
|
|
||||||
|
user.aiCost += responseAI.tokens * prices.text;
|
||||||
|
|
||||||
|
client.sendTextMessage(roomId, responseAI.text);
|
||||||
};
|
};
|
||||||
|
|
||||||
const onImageGen = async (text: string, roomId: string) => {
|
const onImageGen = async (text: string, roomId: string, sender: string) => {
|
||||||
|
const user = getUserById(sender);
|
||||||
|
|
||||||
let textMod = text.replace("!img", "").trim().toLowerCase();
|
let textMod = text.replace("!img", "").trim().toLowerCase();
|
||||||
alts.forEach((alt) => {
|
alts.forEach((alt) => {
|
||||||
textMod = textMod.replaceAll(alt.key, alt.alt);
|
alt.keys.forEach((key) => {
|
||||||
|
textMod = textMod.replaceAll(key, alt.alt);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
const buffer = await getImageGemini(textMod);
|
const responseAI = await getImageGemini(textMod);
|
||||||
if (!buffer || buffer.length < 10) {
|
|
||||||
|
user.aiCost += responseAI.tokens * prices.image;
|
||||||
|
if (!responseAI.image || responseAI.image.length < 10) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const imageName = `photo-img-gen.png`;
|
const imageName = `photo-img-gen.png`;
|
||||||
|
|
||||||
const uploadResult = await client.uploadContent(buffer, {
|
const uploadResult = await client.uploadContent(responseAI.image, {
|
||||||
type: "image/png",
|
type: "image/png",
|
||||||
name: imageName,
|
name: imageName,
|
||||||
});
|
});
|
||||||
|
|
@ -59,7 +80,7 @@ const onImageGen = async (text: string, roomId: string) => {
|
||||||
url: uploadResult.content_uri,
|
url: uploadResult.content_uri,
|
||||||
info: {
|
info: {
|
||||||
mimetype: "image/png",
|
mimetype: "image/png",
|
||||||
size: buffer.length,
|
size: responseAI.image.length,
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -2,164 +2,73 @@ import type { IAIAlt } from "./types.js";
|
||||||
|
|
||||||
const alts: IAIAlt[] = [
|
const alts: IAIAlt[] = [
|
||||||
{
|
{
|
||||||
key: "satek",
|
keys: [
|
||||||
|
"satek",
|
||||||
|
"sateg",
|
||||||
|
"sadeg",
|
||||||
|
"coty",
|
||||||
|
"satko",
|
||||||
|
"sadko",
|
||||||
|
"vlado",
|
||||||
|
"vladko",
|
||||||
|
"vladimir",
|
||||||
|
"macak",
|
||||||
|
"macag",
|
||||||
|
],
|
||||||
alt: "black cat",
|
alt: "black cat",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "sateg",
|
keys: ["macica", "macico"],
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "sadeg",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "satko",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "sadko",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "vlado",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "vladko",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "vladimir",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "macag",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "vladko",
|
|
||||||
alt: "black cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "macica",
|
|
||||||
alt: "white cat",
|
alt: "white cat",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "macico",
|
keys: ["gabor", "gaber", "martin", "marting"],
|
||||||
alt: "white cat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "gabor",
|
|
||||||
alt: "hedgehog",
|
alt: "hedgehog",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "martin",
|
keys: [
|
||||||
alt: "hedgehog",
|
"madys",
|
||||||
},
|
"mandak",
|
||||||
{
|
"mandag",
|
||||||
key: "madys",
|
"mando",
|
||||||
|
"mandik",
|
||||||
|
"madik",
|
||||||
|
"madeg",
|
||||||
|
"madek",
|
||||||
|
],
|
||||||
alt: "beaver",
|
alt: "beaver",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "mandak",
|
keys: ["janys", "jano", "janeg", "janek", "aslanek", "aslan", "aslo"],
|
||||||
alt: "beaver",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "mando",
|
|
||||||
alt: "beaver",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "mandik",
|
|
||||||
alt: "beaver",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "madik",
|
|
||||||
alt: "beaver",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "madeg",
|
|
||||||
alt: "beaver",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "janys",
|
|
||||||
alt: "lion",
|
alt: "lion",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "jano",
|
keys: ["marek", "mareg", "macek", "maceg", "rod"],
|
||||||
alt: "lion",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "janeg",
|
|
||||||
alt: "lion",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "aslan",
|
|
||||||
alt: "lion",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "aslo",
|
|
||||||
alt: "lion",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "marek",
|
|
||||||
alt: "purple snake",
|
alt: "purple snake",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "mareg",
|
keys: ["lara", "kostur", "kosturik"],
|
||||||
alt: "purple snake",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "maceg",
|
|
||||||
alt: "purple snake",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "rod",
|
|
||||||
alt: "purple snake",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "lara",
|
|
||||||
alt: "ginger dog",
|
alt: "ginger dog",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "kostur",
|
keys: ["tato"],
|
||||||
alt: "ginger dog",
|
alt: "green troll",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "kosturik",
|
keys: ["mama", "monika", "monik"],
|
||||||
alt: "ginger dog",
|
alt: "god's peasant",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "tato",
|
keys: ["puk", "pucik", "pucig"],
|
||||||
alt: "troll",
|
alt: "fat rat",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "mama",
|
keys: ["becky", "beky", "beki"],
|
||||||
alt: "angel",
|
alt: "35 year old pink haired giantess",
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
key: "monik",
|
keys: ["veronika", "veronik", "wewe", "wonka"],
|
||||||
alt: "angel",
|
alt: "lgbt princess with curly hair",
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "puk",
|
|
||||||
alt: "rat",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "becky",
|
|
||||||
alt: "giantess",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "beky",
|
|
||||||
alt: "giantess",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "beki",
|
|
||||||
alt: "giantess",
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "veronik",
|
|
||||||
alt: "lgbt princess",
|
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
||||||
6
src/modules/ai/prices.ts
Normal file
6
src/modules/ai/prices.ts
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
const prices = {
|
||||||
|
text: 0.000002,
|
||||||
|
image: 0.00003,
|
||||||
|
};
|
||||||
|
|
||||||
|
export { prices };
|
||||||
|
|
@ -1,6 +1,12 @@
|
||||||
interface IAIAlt {
|
interface IAIAlt {
|
||||||
key: string;
|
keys: string[];
|
||||||
alt: string;
|
alt: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export { type IAIAlt };
|
interface IAdminInstructions {
|
||||||
|
prefferedLanguages: string[];
|
||||||
|
adminText: string;
|
||||||
|
alts: IAIAlt[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type IAIAlt, type IAdminInstructions };
|
||||||
|
|
|
||||||
|
|
@ -61,17 +61,21 @@ const onHelp = (_text: string, roomId: string) => {
|
||||||
client.sendHtmlMessage(
|
client.sendHtmlMessage(
|
||||||
roomId,
|
roomId,
|
||||||
"",
|
"",
|
||||||
`<h3>Role: User</h3>
|
`<h3>Role: Any</h3>
|
||||||
<ul>
|
<ul>
|
||||||
<li><b>!ping</b> - Pong!</li>
|
<li><b>!ping</b> - Pong!</li>
|
||||||
<li><b>!info</b> - Prints information about this bot</li>
|
<li><b>!info</b> - Prints information about this bot</li>
|
||||||
<li><b>!say {text}</b> - Repeats your message</li>
|
<li><b>!say {text}</b> - Repeats your message</li>
|
||||||
<li><b>!bowling {text}</b> - Repeats your message in bowling</li>
|
<li><b>!bowling {text}</b> - Repeats your message in bowling</li>
|
||||||
<li><b>!help</b> - Prints this help message</li>
|
<li><b>!help</b> - Prints this help message</li>
|
||||||
<li><b>!level</b> - Prints your level and experience</li>
|
<li><b>!me</b> - Prints your role, level, experience, money and ai cost</li>
|
||||||
<li><b>!leaderboard</b> - Prints total user ranking</li>
|
<li><b>!leaderboard</b> - Prints total user ranking</li>
|
||||||
|
<li><b>!aileaderboard</b> - Prints total user ai cost</li>
|
||||||
|
</ul>
|
||||||
|
<h3>Role: User</h3>
|
||||||
|
<ul>
|
||||||
<li><b>!ai {text}</b> - Say something to Gemini 3</li>
|
<li><b>!ai {text}</b> - Say something to Gemini 3</li>
|
||||||
<li><b>!img {text}</b> - Generate an image (also works with "{name} when/ked {text}")</li>
|
<li><b>!img {text}</b> - Generate an image</li>
|
||||||
</ul>
|
</ul>
|
||||||
<hr/>
|
<hr/>
|
||||||
<h3>Role: Moderator</h3>
|
<h3>Role: Moderator</h3>
|
||||||
|
|
|
||||||
|
|
@ -18,15 +18,23 @@ const onAnyMessage = (
|
||||||
id: sender,
|
id: sender,
|
||||||
role: "USER",
|
role: "USER",
|
||||||
experience: 0,
|
experience: 0,
|
||||||
|
money: 10,
|
||||||
|
aiCost: 0,
|
||||||
lastMessageTimestamp: date,
|
lastMessageTimestamp: date,
|
||||||
|
lastExperienceGainTimestamp: date,
|
||||||
|
lastMoneyGainTimestamp: date,
|
||||||
});
|
});
|
||||||
return onAnyMessage(client, _text, roomId, sender);
|
return onAnyMessage(client, _text, roomId, sender);
|
||||||
}
|
}
|
||||||
|
|
||||||
const levelBefore = getLevel(user.experience);
|
const levelBefore = getLevel(user.experience);
|
||||||
|
|
||||||
if (date > user.lastMessageTimestamp + config.app.experience.timeout) {
|
if (
|
||||||
|
date >
|
||||||
|
user.lastExperienceGainTimestamp + config.app.experience.timeout
|
||||||
|
) {
|
||||||
user.experience += config.app.experience.gain;
|
user.experience += config.app.experience.gain;
|
||||||
|
user.lastExperienceGainTimestamp = date;
|
||||||
}
|
}
|
||||||
user.lastMessageTimestamp = date;
|
user.lastMessageTimestamp = date;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -13,24 +13,31 @@ const registerModuleUser = (
|
||||||
client = matrixClient;
|
client = matrixClient;
|
||||||
|
|
||||||
callbackStore.messageCallbacks.push({
|
callbackStore.messageCallbacks.push({
|
||||||
startConditions: [`${config.app.triggerPrefix}level`],
|
startConditions: [`${config.app.triggerPrefix}me`],
|
||||||
callbackFunc: onLevel,
|
callbackFunc: onMe,
|
||||||
});
|
});
|
||||||
callbackStore.messageCallbacks.push({
|
callbackStore.messageCallbacks.push({
|
||||||
startConditions: [`${config.app.triggerPrefix}leaderboard`],
|
startConditions: [`${config.app.triggerPrefix}leaderboard`],
|
||||||
callbackFunc: onLeaderboard,
|
callbackFunc: onLeaderboard,
|
||||||
});
|
});
|
||||||
|
callbackStore.messageCallbacks.push({
|
||||||
|
startConditions: [`${config.app.triggerPrefix}aileaderboard`],
|
||||||
|
callbackFunc: onAILeaderboard,
|
||||||
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
const onLevel = (_text: string, roomId: string, sender: string) => {
|
const onMe = (_text: string, roomId: string, sender: string) => {
|
||||||
const level = getLevel(getUserById(sender).experience);
|
const user = getUserById(sender);
|
||||||
|
const level = getLevel(user.experience);
|
||||||
|
|
||||||
client.sendHtmlMessage(
|
client.sendHtmlMessage(
|
||||||
roomId,
|
roomId,
|
||||||
"",
|
"",
|
||||||
`<h3>Your Level: ${level.level}</h3>
|
`<p>Your Role: <b>${user.role}</b></p></br>
|
||||||
</br>
|
<p>Your Money: <b>${user.money}</b></p></br>
|
||||||
<i>Next level progress: ${level.experienceInLevel}/${level.expToNextLevel}xp</i>`,
|
<p>Your AI Cost: <b>${user.aiCost}$</b></p></br>
|
||||||
|
<p>Your Level: <b>${level.level}</b></p></br>
|
||||||
|
<i>Next level progress: <b>${level.experienceInLevel}/${level.expToNextLevel}xp</b></i>`,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -58,4 +65,28 @@ const onLeaderboard = (_text: string, roomId: string) => {
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const onAILeaderboard = (_text: string, roomId: string) => {
|
||||||
|
const mapUsersToLeaderboard = (user: IUser): string => {
|
||||||
|
const cost = user.aiCost;
|
||||||
|
const userName = getUserName(user);
|
||||||
|
const userNameMod =
|
||||||
|
userName.charAt(0).toUpperCase() + userName.slice(1);
|
||||||
|
|
||||||
|
return `<li>${userNameMod}: cost <b>${cost}</b></li>`;
|
||||||
|
};
|
||||||
|
|
||||||
|
const users = state.users.sort(
|
||||||
|
(userA, userB) => userB.aiCost - userA.aiCost,
|
||||||
|
);
|
||||||
|
|
||||||
|
client.sendHtmlMessage(
|
||||||
|
roomId,
|
||||||
|
"",
|
||||||
|
`<h3>AI Cost Leaderboard</h3>
|
||||||
|
<ul>
|
||||||
|
${users.map(mapUsersToLeaderboard).join("")}
|
||||||
|
</ul>`,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
export { registerModuleUser };
|
export { registerModuleUser };
|
||||||
|
|
|
||||||
|
|
@ -1,22 +1,24 @@
|
||||||
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";
|
||||||
|
|
||||||
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<string> => {
|
const getTextGemini = async (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,
|
||||||
});
|
});
|
||||||
|
|
||||||
return response.text ?? "AI Error";
|
return {
|
||||||
|
text: response.text ?? "AI Error",
|
||||||
|
tokens: response.usageMetadata?.totalTokenCount ?? 0,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
const getImageGemini = async (
|
const getImageGemini = async (input: string): Promise<AIResponseImage> => {
|
||||||
input: string,
|
|
||||||
): Promise<Buffer<ArrayBuffer> | undefined> => {
|
|
||||||
const response = await googleAI.models.generateContent({
|
const response = await googleAI.models.generateContent({
|
||||||
model: "gemini-2.5-flash-image",
|
model: "gemini-2.5-flash-image",
|
||||||
contents: input,
|
contents: input,
|
||||||
|
|
@ -38,7 +40,10 @@ const getImageGemini = async (
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return buffer;
|
return {
|
||||||
|
image: buffer,
|
||||||
|
tokens: response.usageMetadata?.totalTokenCount ?? 0,
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
export { getTextGemini, getImageGemini };
|
export { getTextGemini, getImageGemini };
|
||||||
|
|
|
||||||
|
|
@ -1 +1,2 @@
|
||||||
export * from "./ai.js";
|
export * from "./ai.js";
|
||||||
|
export * from "./types.js";
|
||||||
|
|
|
||||||
11
src/services/ai/types.ts
Normal file
11
src/services/ai/types.ts
Normal file
|
|
@ -0,0 +1,11 @@
|
||||||
|
interface AIResponseText {
|
||||||
|
text: string;
|
||||||
|
tokens: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface AIResponseImage {
|
||||||
|
image: Buffer<ArrayBuffer> | undefined;
|
||||||
|
tokens: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export { type AIResponseText, type AIResponseImage };
|
||||||
|
|
@ -6,7 +6,11 @@ interface IUser {
|
||||||
id: string;
|
id: string;
|
||||||
role: TRole;
|
role: TRole;
|
||||||
experience: number;
|
experience: number;
|
||||||
|
money: number;
|
||||||
|
aiCost: number;
|
||||||
lastMessageTimestamp: number;
|
lastMessageTimestamp: number;
|
||||||
|
lastExperienceGainTimestamp: number;
|
||||||
|
lastMoneyGainTimestamp: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
type TRole = "NONE" | "USER" | "MODERATOR" | "ADMIN";
|
type TRole = "NONE" | "USER" | "MODERATOR" | "ADMIN";
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue