diff --git a/README.md b/README.md index 308a380..a3c8ac6 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ TODO: move rpbot to own repo - `RPBot`, `system_prompt`(, opt contact ID) - type: `string` - System prompt that is prefixed - - can contain spcific formatters + - can contain specific formatters: - `{self_name}` username for specified chat - default: `Transcript of a group chat, where {self_name} talks to online strangers.\n{self_name} is creative and curious. {self_name} is writing with precision, but also with occasional typos.\n` @@ -25,6 +25,11 @@ TODO: move rpbot to own repo - TODO: implement per ID - default: `4` +- `RPBot`, `max_cont_messages`(, opt contact ID) + - type: `int` + - TODO: implement per ID + - default: '4' + - `RPBot`, `max_interactive_delay`(, opt contact ID) - type: `float` - TODO: implement per ID diff --git a/src/solanaceae/rpbot/rpbot.cpp b/src/solanaceae/rpbot/rpbot.cpp index dc29b86..f8aa63e 100644 --- a/src/solanaceae/rpbot/rpbot.cpp +++ b/src/solanaceae/rpbot/rpbot.cpp @@ -48,6 +48,12 @@ void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextAc return; } + if (mpb.names.size() < 2) { + // early exit for too small groups + to.future = std::async(std::launch::async, [self]() -> int64_t { return -10; }); + return; + } + { // - system promp (needs self name etc) if (const auto* id_comp = _cr.try_get(c); id_comp != nullptr) { const auto id_hex = bin2hex(id_comp->data); @@ -171,27 +177,51 @@ float RPBot::doAllIdle(float time_delta) { } state.timeout -= time_delta; - if (state.timeout <= 0.f) { - std::cout << "RPBot: idle timed out\n"; - // TODO: use multiprompt and better system promp to start immediatly - // TODO: per id min_messages - if (auto* mreg = _rmm.get(c); mreg != nullptr && mreg->view().size() >= _conf.get_int("RPBot", "min_messages").value_or(4)) { - to_remove_stateidle.push_back(c); - min_tick_interval = 0.1f; + if (state.timeout > 0.f) { + return; + } + std::cout << "RPBot: idle timed out\n"; - // transition to Next - emplaceStateTransition(_cr, c, state); - } else { - // check-in in another 15-45s - state.timeout = std::uniform_real_distribution<>{15.f, 45.f}(_rng); - std::cout << "RPBot: not ready yet, back to ideling\n"; - if (mreg == nullptr) { - std::cout << "mreg is null\n"; - } else { - std::cout << "size(): " << mreg->view().size() << "\n"; + // TODO: use multi-shot-prompt and better system promp to start immediatly + auto* mreg = _rmm.get(c); + if (mreg != nullptr) { + // TODO: per id min_messages + if (mreg->view().size() >= _conf.get_int("RPBot", "min_messages").value_or(4)) { + // maximum amount of messages the bot can send, before someone else needs to send a message + // TODO: per id max_cont_messages + const size_t max_cont_messages = _conf.get_int("RPBot", "max_cont_messages").value_or(4); + auto tmp_view = mreg->view(); + tmp_view.use(); + bool other_sender {false}; + auto view_it = tmp_view.begin(), view_last = tmp_view.end(); + for (size_t i = 0; i < max_cont_messages && view_it != view_last; view_it++, i++) { + // TODO: also test for weak self? + if (!_cr.any_of(tmp_view.get(*view_it).c)) { + other_sender = true; + break; + } + } + + if (other_sender) { + to_remove_stateidle.push_back(c); + min_tick_interval = 0.1f; + + // transition to Next + emplaceStateTransition(_cr, c, state); + return; } } } + + // if not handled yet + // check-in in another 15-45s + state.timeout = std::uniform_real_distribution<>{15.f, 45.f}(_rng); + std::cout << "RPBot: not ready yet, back to ideling\n"; + if (mreg == nullptr) { + std::cout << "mreg is null\n"; + } else { + std::cout << "size(): " << mreg->view().size() << "\n"; + } }); _cr.remove(to_remove_stateidle.cbegin(), to_remove_stateidle.cend());