diff --git a/nodejs/conf/base.js b/nodejs/conf/base.js index 94c602b..4e342ac 100644 --- a/nodejs/conf/base.js +++ b/nodejs/conf/base.js @@ -9,5 +9,12 @@ module.exports = { // } // } }, + 'ai':{ + "key": "...", + "interval": 5, + "prompt0": (name, interval, currentPlayers)=>` +Some stuff here. + ` + }, "playerListDir": "/home/william/test_list/" -} \ No newline at end of file +} diff --git a/nodejs/controller/ai.js b/nodejs/controller/ai.js index 17fc4b2..afc85e2 100644 --- a/nodejs/controller/ai.js +++ b/nodejs/controller/ai.js @@ -1,6 +1,8 @@ 'use strict'; const conf = require('../conf'); +const {sleep} = require('../utils'); + const { GoogleGenerativeAI, @@ -8,23 +10,23 @@ const { HarmBlockThreshold, } = require("@google/generative-ai"); -const genAI = new GoogleGenerativeAI(conf.ai.key); -const model = genAI.getGenerativeModel({ - model: "gemini-1.5-flash", -}); -const generationConfig = { - temperature: 1, - topP: 0.95, - topK: 64, - maxOutputTokens: 8192, - responseMimeType: "application/json", -}; +class Ai{ + constructor(prompt){ + this.prompt = prompt; + this.start(); + } -async function run(name, interval, players) { - const chatSession = model.startChat({ - generationConfig, + __settings(history){ + return { + generationConfig: { + temperature: 1, + topP: 0.95, + topK: 64, + maxOutputTokens: 8192, + responseMimeType: "application/json", + }, safetySettings:[ // See https://ai.google.dev/gemini-api/docs/safety-settings { @@ -44,11 +46,11 @@ async function run(name, interval, players) { threshold: HarmBlockThreshold.BLOCK_NONE, }, ], - history: [ + history: history || [ { role: "user", parts: [ - {text: conf.ai.prompt(name, interval, players)}, + {text: this.prompt}, ], }, { @@ -58,10 +60,48 @@ async function run(name, interval, players) { ], } ], - }); + } + } - return chatSession; + start(history){ + const genAI = new GoogleGenerativeAI(conf.ai.key); + + const model = genAI.getGenerativeModel({ + model: "gemini-1.5-flash", + }); + + this.session = model.startChat({ + ...this.__settings(history), + // systemInstruction: this.prompt, + }); + } + + async chat(message, retryCount=0){ + console.log('chat', retryCount) + try{ + let result = await this.session.sendMessage(message); + + return result + }catch(error){ + console.log('AI chat error', error) + + if(retryCount > 3){ + console.log('hit retry count'); + return ; + }; + await sleep(500); + this.session.params.history.pop(); + console.log('current history', this.session.params.history); + this.start(this.session.params.history); + return await this.chat(message, retryCount++) + } + } } -module.exports = {run}; + + + + + +module.exports = {Ai}; // run(); \ No newline at end of file diff --git a/nodejs/controller/mc-bot.js b/nodejs/controller/mc-bot.js index 72bce66..1677675 100644 --- a/nodejs/controller/mc-bot.js +++ b/nodejs/controller/mc-bot.js @@ -1,5 +1,6 @@ 'use strict'; +const axios = require('axios'); const {sleep} = require('../utils'); const conf = require('../conf'); @@ -8,7 +9,7 @@ const inventoryViewer = require('mineflayer-web-inventory'); const commands = require('./commands'); const {onJoin} = require('./player_list'); -const ai = require('./ai'); +const {Ai} = require('./ai'); for(let name in conf.mc.bots){ @@ -31,7 +32,10 @@ for(let name in conf.mc.bots){ // setTimeout(()=> bot.bot.setControlState('jump', false), 5000); if(bot.hasAi){ console.log(`${bot.bot.entity.username} has AI`); - let messages = []; + let messages = ['']; + + let bulbaItems = await axios.get('https://webstore.bulbastore.uk/api/listings'); + bulbaItems = bulbaItems.data.listings.map(i=>i.listing_name); bot.bot.on('message', (message, type)=>{ if(type === 'game_info') return; @@ -42,18 +46,22 @@ for(let name in conf.mc.bots){ await sleep(500); - let aiChat = await ai.run( + let aiChat = new Ai(conf.ai.prompt( bot.bot.entity.username, conf.ai.interval, - Object.values(bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n') - ); + Object.values(bot.getPlayers()).map(player=>`<[${player.lvl}] ${player.username}>`).join('\n'), + bulbaItems + )) + setInterval(async ()=>{ let result; - if(messages.length ===0) return; + // if(messages.length ===0) return; try{ - result = await aiChat.sendMessage(messages); + result = await aiChat.chat(JSON.stringify({ + messages, currentTime:Date.now()+1} + )); }catch(error){ console.log('error AI API', error, result); messages = []; @@ -61,7 +69,7 @@ for(let name in conf.mc.bots){ } try{ - messages = []; + messages = ['']; if(!result.response.text()) return; for(let message of JSON.parse(result.response.text())){ @@ -73,6 +81,9 @@ for(let name in conf.mc.bots){ } }catch(error){ console.log('Error in AI message loop', error, result); + if(result || result.response || result.response.text()){ + console.log(result.response.text()) + } } }, conf.ai.interval*1000); } diff --git a/nodejs/model/minecraft.js b/nodejs/model/minecraft.js index da42a42..6f1e366 100644 --- a/nodejs/model/minecraft.js +++ b/nodejs/model/minecraft.js @@ -277,11 +277,15 @@ class CJbot{ async say(...messages){ for(let message of messages){ - if(this.nextChatTime > Date.now()){ - await sleep(this.nextChatTime-Date.now()+1) - } + console.log('next chat time:', this.nextChatTime > Date.now(), Date.now()+1, this.nextChatTime-Date.now()+1); + (async (message)=>{ + if(this.nextChatTime > Date.now()){ + console.log('am sleeping'); + await sleep(this.nextChatTime-Date.now()+1) + } + this.bot.chat(message); + })(message); - this.bot.chat(message); this.nextChatTime = Date.now() + this.__chatCoolDown(); } }