Compare commits

..

7 Commits

Author SHA1 Message Date
7e1b424adb make contact store version visible 2025-03-10 20:58:24 +01:00
f321cea6eb port to contact4 2025-03-10 16:45:16 +01:00
998ba002e4 update cpp-httplib to v0.19.0 2025-03-10 16:43:23 +01:00
48b4e6ae95 Create LICENSE 2025-02-07 12:32:24 +01:00
31855cd1b1 use sr 2024-10-25 12:54:04 +02:00
301900c507 update to rmmi 2024-10-06 11:46:15 +02:00
55e3a8a6f8 forgotten wip changes 2024-10-06 11:44:19 +02:00
12 changed files with 160 additions and 116 deletions

21
LICENSE Normal file
View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2025 Erik Scholz
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -53,7 +53,7 @@ endif()
if (NOT TARGET httplib::httplib)
FetchContent_Declare(httplib
GIT_REPOSITORY https://github.com/yhirose/cpp-httplib.git
GIT_TAG v0.15.3
GIT_TAG v0.19.0
EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(httplib)

View File

@ -1,6 +1,7 @@
#include <solanaceae/plugin/solana_plugin_v1.h>
#include <solanaceae/util/config_model.hpp>
#include <solanaceae/contact/contact_store_i.hpp>
#include <solanaceae/llama-cpp-web/text_completion_interface.hpp>
#include <solanaceae/rpbot/rpbot.hpp>
#include <solanaceae/message3/message_command_dispatcher.hpp>
@ -36,13 +37,13 @@ SOLANA_PLUGIN_EXPORT uint32_t solana_plugin_start(struct SolanaAPI* solana_api)
try {
auto* completion = PLUG_RESOLVE_INSTANCE(TextCompletionI);
auto* conf = PLUG_RESOLVE_INSTANCE(ConfigModelI);
auto* cr = PLUG_RESOLVE_INSTANCE_VERSIONED(Contact3Registry, "1");
auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModel);
auto* cs = PLUG_RESOLVE_INSTANCE(ContactStore4I);
auto* rmm = PLUG_RESOLVE_INSTANCE(RegistryMessageModelI);
auto* mcd = PLUG_RESOLVE_INSTANCE(MessageCommandDispatcher);
// static store, could be anywhere tho
// construct with fetched dependencies
g_rpbot = std::make_unique<RPBot>(*completion, *conf, *cr, *rmm, mcd);
g_rpbot = std::make_unique<RPBot>(*completion, *conf, *cs, *rmm, mcd);
// register types
PLUG_PROVIDE_INSTANCE(RPBot, plugin_name, g_rpbot.get());

View File

@ -77,7 +77,7 @@ int64_t LlamaCppWeb::completeSelect(const std::string_view prompt, const std::ve
}
//grammar += ")";
//std::cout << "generated grammar:\n" << grammar << "\n";
std::cerr << "generated grammar:\n" << grammar << "\n";
auto ret = complete(nlohmann::json{
{"prompt", prompt},
@ -89,19 +89,23 @@ int64_t LlamaCppWeb::completeSelect(const std::string_view prompt, const std::ve
{"top_p", 1.0}, // disable
{"n_predict", 256}, // unlikely to ever be so high
{"seed", _rng()},
{"ignore_eos", true},
{"cache_prompt", static_cast<bool>(_use_server_cache)},
});
if (ret.empty()) {
assert("ret empty" && false);
return -2;
}
if (!ret.count("content")) {
assert("no content" && false);
return -3;
}
std::string selected = ret.at("content");
if (selected.empty()) {
assert("content empty" && false);
return -4;
}
@ -111,6 +115,7 @@ int64_t LlamaCppWeb::completeSelect(const std::string_view prompt, const std::ve
}
}
std::cerr << "content does not contain match\n";
std::cerr << "complete failed j:'" << ret.dump() << "'\n";
return -5;
}
@ -125,7 +130,7 @@ std::string LlamaCppWeb::completeLine(const std::string_view prompt) {
{"top_p", 1.0}, // disable
{"n_predict", 400},
{"seed", _rng()},
{"stop", {"\n"}},
{"stop", nlohmann::json::array({"\n"})},
{"cache_prompt", static_cast<bool>(_use_server_cache)},
});
@ -147,7 +152,7 @@ nlohmann::json LlamaCppWeb::complete(const nlohmann::json& request_j) {
// steaming instead would be better
_cli.set_read_timeout(std::chrono::minutes(10));
//std::cout << "j dump: '" << request_j.dump(-1, ' ', true) << "'\n";
std::cerr << "j dump: '" << request_j.dump(-1, ' ', true) << "'\n";
auto res = _cli.Post("/completion", request_j.dump(-1, ' ', true), "application/json");
@ -159,7 +164,7 @@ nlohmann::json LlamaCppWeb::complete(const nlohmann::json& request_j) {
//res->body.empty() ||
//res->get_header_value("Content-Type") != "application/json"
) {
std::cerr << "error posting\n";
std::cerr << "error posting: '" << res->body << "'\n";
return {};
}

View File

@ -19,7 +19,7 @@ struct LlamaCppWeb : public TextCompletionI {
// this is a bad idea
static std::minstd_rand thread_local _rng;
std::atomic<bool> _use_server_cache {true};
std::atomic<bool> _use_server_cache {false};
LlamaCppWeb(
ConfigModelI& conf

View File

@ -2,30 +2,32 @@
#include "./rpbot.hpp"
#include <solanaceae/contact/contact_store_i.hpp>
#include <solanaceae/contact/components.hpp>
#include <solanaceae/message3/components.hpp>
bool MessagePromptBuilder::buildNameLookup(void) {
if (_cr.all_of<Contact::Components::ParentOf>(_c)) { // group rpbot
const auto& subs = _cr.get<Contact::Components::ParentOf>(_c).subs;
const auto& cr = _cs.registry();
if (cr.all_of<Contact::Components::ParentOf>(_c)) { // group rpbot
const auto& subs = cr.get<Contact::Components::ParentOf>(_c).subs;
// should include self
for (const auto sub_c : subs) {
if (_cr.all_of<Contact::Components::Name>(sub_c)) {
names[sub_c] = _cr.get<Contact::Components::Name>(sub_c).name;
if (cr.all_of<Contact::Components::Name>(sub_c)) {
names[sub_c] = cr.get<Contact::Components::Name>(sub_c).name;
}
}
} else { // pm rpbot
if (_cr.all_of<Contact::Components::Name>(_c)) {
names[_c] = _cr.get<Contact::Components::Name>(_c).name;
if (cr.all_of<Contact::Components::Name>(_c)) {
names[_c] = cr.get<Contact::Components::Name>(_c).name;
} else {
std::cerr << "RPBot error: other missing name\n";
return false;
}
if (_cr.all_of<Contact::Components::Self>(_c)) {
const auto self = _cr.get<Contact::Components::Self>(_c).self;
if (_cr.all_of<Contact::Components::Name>(self)) {
names[self] = _cr.get<Contact::Components::Name>(self).name;
if (cr.all_of<Contact::Components::Self>(_c)) {
const auto self = cr.get<Contact::Components::Self>(_c).self;
if (cr.all_of<Contact::Components::Name>(self)) {
names[self] = cr.get<Contact::Components::Name>(self).name;
} else {
std::cerr << "RPBot error: self missing name\n";
return false;
@ -87,7 +89,7 @@ std::string MessagePromptBuilder::buildPromptMessage(const Message3Handle m) {
}
std::string MessagePromptBuilder::promptMessagePrefixSimple(const Message3Handle m) {
const Contact3 from = m.get<Message::Components::ContactFrom>().c;
const Contact4 from = m.get<Message::Components::ContactFrom>().c;
if (names.count(from)) {
return std::string{names[from]};
} else {
@ -98,8 +100,8 @@ std::string MessagePromptBuilder::promptMessagePrefixSimple(const Message3Handle
std::string MessagePromptBuilder::promptMessagePrefixDirected(const Message3Handle m) {
// with both contacts (eg: "Name1 to Name2"; or "Name1 to Everyone"
const Contact3 from = m.get<Message::Components::ContactFrom>().c;
const Contact3 to = m.get<Message::Components::ContactTo>().c;
const Contact4 from = m.get<Message::Components::ContactFrom>().c;
const Contact4 to = m.get<Message::Components::ContactTo>().c;
std::string res;

View File

@ -1,19 +1,19 @@
#pragma once
#include <solanaceae/util/config_model.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <solanaceae/contact/fwd.hpp>
#include <solanaceae/message3/registry_message_model.hpp>
#include <entt/container/dense_map.hpp>
// TODO: improve caching
struct MessagePromptBuilder {
Contact3Registry& _cr;
const Contact3 _c;
RegistryMessageModel& _rmm;
ContactStore4I& _cs;
const Contact4 _c;
RegistryMessageModelI& _rmm;
// lookup table, string_view since no name-components are changed
entt::dense_map<Contact3, std::string_view> names;
entt::dense_map<Contact4, std::string_view> names;
bool buildNameLookup(void);

View File

@ -18,22 +18,24 @@
#include <cstdint>
template<>
void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextActor& to) {
void RPBot::stateTransition(const Contact4 c, const StateIdle& from, StateNextActor& to) {
// collect promp
MessagePromptBuilder mpb{_cr, c, _rmm, {}};
MessagePromptBuilder mpb{_cs, c, _rmm, {}};
mpb.buildNameLookup();
const auto& cr = _cs.registry();
int64_t self {-1};
{ // get set of possible usernames (even if forced, just to make sure)
// copy mpb.names (contains string views, needs copies)
for (const auto& [name_c, name] : mpb.names) {
if (_cr.all_of<Contact::Components::TagSelfStrong>(name_c)) {
if (cr.all_of<Contact::Components::TagSelfStrong>(name_c)) {
self = to.possible_contacts.size();
to.possible_names.push_back(std::string{name});
to.possible_contacts.push_back(name_c);
} else if (_cr.all_of<Contact::Components::ConnectionState>(name_c)) {
if (_cr.get<Contact::Components::ConnectionState>(name_c).state != Contact::Components::ConnectionState::disconnected) {
} else if (cr.all_of<Contact::Components::ConnectionState>(name_c)) {
if (cr.get<Contact::Components::ConnectionState>(name_c).state != Contact::Components::ConnectionState::disconnected) {
// online
to.possible_names.push_back(std::string{name});
to.possible_contacts.push_back(name_c);
@ -55,7 +57,7 @@ void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextAc
}
{ // - system promp (needs self name etc)
if (const auto* id_comp = _cr.try_get<Contact::Components::ID>(c); id_comp != nullptr) {
if (const auto* id_comp = cr.try_get<Contact::Components::ID>(c); id_comp != nullptr) {
const auto id_hex = bin2hex(id_comp->data);
to.prompt = _conf.get_string("RPBot", "system_prompt", id_hex).value();
} else {
@ -109,17 +111,18 @@ void RPBot::stateTransition(const Contact3 c, const StateIdle& from, StateNextAc
}
template<>
void RPBot::stateTransition(const Contact3, const StateNextActor&, StateIdle& to) {
void RPBot::stateTransition(const Contact4, const StateNextActor&, StateIdle& to) {
to.timeout = std::uniform_real_distribution<>{30.f, 5.f*60.f}(_rng);
}
template<>
void RPBot::stateTransition(const Contact3 c, const StateNextActor& from, StateGenerateMsg& to) {
void RPBot::stateTransition(const Contact4 c, const StateNextActor& from, StateGenerateMsg& to) {
const auto& cr = _cs.registry();
to.prompt = from.prompt; // TODO: move from?
assert(_cr.all_of<Contact::Components::Self>(c));
const Contact3 self = _cr.get<Contact::Components::Self>(c).self;
assert(cr.all_of<Contact::Components::Self>(c));
const Contact4 self = cr.get<Contact::Components::Self>(c).self;
to.prompt += _cr.get<Contact::Components::Name>(self).name + ":"; // TODO: remove space
to.prompt += cr.get<Contact::Components::Name>(self).name + ":"; // TODO: remove space
{ // launch async
to.future = std::async(std::launch::async, [&to, this]() -> std::string {
@ -129,7 +132,7 @@ void RPBot::stateTransition(const Contact3 c, const StateNextActor& from, StateG
}
template<>
void RPBot::stateTransition(const Contact3, const StateGenerateMsg&, StateIdle& to) {
void RPBot::stateTransition(const Contact4, const StateGenerateMsg&, StateIdle& to) {
// relativly slow delay for multi line messages
to.timeout = std::uniform_real_distribution<>{2.f, 15.f}(_rng);
}
@ -137,10 +140,10 @@ void RPBot::stateTransition(const Contact3, const StateGenerateMsg&, StateIdle&
RPBot::RPBot(
TextCompletionI& completion,
ConfigModelI& conf,
Contact3Registry& cr,
RegistryMessageModel& rmm,
ContactStore4I& cs,
RegistryMessageModelI& rmm,
MessageCommandDispatcher* mcd
) : _completion(completion), _conf(conf), _cr(cr), _rmm(rmm), _mcd(mcd) {
) : _completion(completion), _conf(conf), _cs(cs), _rmm(rmm), _rmm_sr(_rmm.newSubRef(this)), _mcd(mcd) {
//system_prompt = R"sys(Transcript of a group chat, where Bob talks to online strangers.
//)sys";
@ -157,7 +160,7 @@ R"sys(Transcript of a group chat, where {self_name} talks to online strangers.
registerCommands();
_rmm.subscribe(this, RegistryMessageModel_Event::message_construct);
_rmm_sr.subscribe(RegistryMessageModel_Event::message_construct);
}
float RPBot::tick(float time_delta) {
@ -172,15 +175,16 @@ float RPBot::tick(float time_delta) {
}
float RPBot::doAllIdle(float time_delta) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove_stateidle;
auto view = _cr.view<StateIdle>();
std::vector<Contact4> to_remove_stateidle;
auto view = cr.view<StateIdle>();
view.each([this, time_delta, &to_remove_stateidle, &min_tick_interval](const Contact3 c, StateIdle& state) {
if (_cr.all_of<TagStopRPBot>(c)) {
view.each([this, &cr, time_delta, &to_remove_stateidle, &min_tick_interval](const Contact4 c, StateIdle& state) {
if (cr.all_of<TagStopRPBot>(c)) {
// marked for deletion, in idle (here) we remove them without adding next state
to_remove_stateidle.push_back(c);
_cr.remove<TagStopRPBot>(c);
cr.remove<TagStopRPBot>(c);
return;
}
@ -204,7 +208,7 @@ float RPBot::doAllIdle(float time_delta) {
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<Contact::Components::TagSelfStrong>(tmp_view.get<Message::Components::ContactFrom>(*view_it).c)) {
if (!cr.any_of<Contact::Components::TagSelfStrong>(tmp_view.get<Message::Components::ContactFrom>(*view_it).c)) {
other_sender = true;
break;
}
@ -215,7 +219,7 @@ float RPBot::doAllIdle(float time_delta) {
min_tick_interval = 0.1f;
// transition to Next
emplaceStateTransition<StateNextActor>(_cr, c, state);
emplaceStateTransition<StateNextActor>(_cs, c, state);
return;
}
}
@ -232,16 +236,17 @@ float RPBot::doAllIdle(float time_delta) {
}
});
_cr.remove<StateIdle>(to_remove_stateidle.cbegin(), to_remove_stateidle.cend());
cr.remove<StateIdle>(to_remove_stateidle.cbegin(), to_remove_stateidle.cend());
return min_tick_interval;
}
float RPBot::doAllNext(float) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove;
auto view = _cr.view<StateNextActor>();
std::vector<Contact4> to_remove;
auto view = cr.view<StateNextActor>();
view.each([this, &to_remove, &min_tick_interval](const Contact3 c, StateNextActor& state) {
view.each([this, &cr, &to_remove, &min_tick_interval](const Contact4 c, StateNextActor& state) {
// TODO: how to timeout?
if (state.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
to_remove.push_back(c);
@ -251,9 +256,9 @@ float RPBot::doAllNext(float) {
const auto selected = state.future.get();
if (selected >= 0 && size_t(selected) < state.possible_names.size()) {
std::cout << "next is " << state.possible_names.at(selected) << "(" << selected << ")\n";
if (_cr.all_of<Contact::Components::TagSelfStrong>(state.possible_contacts.at(selected))) {
if (cr.all_of<Contact::Components::TagSelfStrong>(state.possible_contacts.at(selected))) {
// we predicted ourselfs
emplaceStateTransition<StateGenerateMsg>(_cr, c, state);
emplaceStateTransition<StateGenerateMsg>(_cs, c, state);
return;
}
} else {
@ -261,21 +266,22 @@ float RPBot::doAllNext(float) {
}
// transition to Idle
emplaceStateTransition<StateIdle>(_cr, c, state);
emplaceStateTransition<StateIdle>(_cs, c, state);
}
});
_cr.remove<StateNextActor>(to_remove.cbegin(), to_remove.cend());
cr.remove<StateNextActor>(to_remove.cbegin(), to_remove.cend());
return min_tick_interval;
}
float RPBot::doAllGenerateMsg(float) {
auto& cr = _cs.registry();
float min_tick_interval = std::numeric_limits<float>::max();
std::vector<Contact3> to_remove;
auto view = _cr.view<StateGenerateMsg>();
std::vector<Contact4> to_remove;
auto view = cr.view<StateGenerateMsg>();
_cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
view.each([this, &to_remove, &min_tick_interval](const Contact3 c, StateGenerateMsg& state) {
cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
view.each([this, &to_remove, &min_tick_interval](const Contact4 c, StateGenerateMsg& state) {
// TODO: how to timeout?
if (state.future.wait_for(std::chrono::milliseconds(0)) == std::future_status::ready) {
to_remove.push_back(c);
@ -293,11 +299,11 @@ float RPBot::doAllGenerateMsg(float) {
// TODO: timing check?
// transition to Idle
emplaceStateTransition<StateIdle>(_cr, c, state);
emplaceStateTransition<StateIdle>(_cs, c, state);
}
});
_cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
cr.remove<StateGenerateMsg>(to_remove.cbegin(), to_remove.cend());
return min_tick_interval;
}
@ -311,39 +317,41 @@ bool RPBot::onEvent(const Message::Events::MessageConstruct& e) {
return false;
}
auto& cr = _cs.registry();
const auto contact_to = e.e.get<Message::Components::ContactTo>().c;
const auto contact_from = e.e.get<Message::Components::ContactFrom>().c;
if (!_cr.valid(contact_to) || !_cr.valid(contact_from)) {
if (!cr.valid(contact_to) || !cr.valid(contact_from)) {
std::cerr << "RPBot error: invalid contact in message\n";
return false;
}
if (_cr.any_of<Contact::Components::TagSelfStrong>(contact_from)) {
if (cr.any_of<Contact::Components::TagSelfStrong>(contact_from)) {
return false; // ignore own messages
}
Contact3 rpbot_contact = entt::null;
Contact4 rpbot_contact = entt::null;
// check ContactTo (public)
// check ContactTo parent (group private)
// check ContactFrom (private)
if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_to)) {
if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_to)) {
rpbot_contact = contact_to;
} else if (_cr.all_of<Contact::Components::Parent>(contact_to)) {
rpbot_contact = _cr.get<Contact::Components::Parent>(contact_to).parent;
} else if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_from)) {
} else if (cr.all_of<Contact::Components::Parent>(contact_to)) {
rpbot_contact = cr.get<Contact::Components::Parent>(contact_to).parent;
} else if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(contact_from)) {
rpbot_contact = contact_from;
} else {
return false; // not a rpbot related message
}
if (!_cr.all_of<StateIdle>(rpbot_contact)) {
if (!cr.all_of<StateIdle>(rpbot_contact)) {
return false; // not idle
}
auto& timeout = _cr.get<StateIdle>(rpbot_contact).timeout;
auto& timeout = cr.get<StateIdle>(rpbot_contact).timeout;
// TODO: config with id
timeout = std::clamp<float>(
timeout,

View File

@ -2,7 +2,7 @@
#include <solanaceae/util/config_model.hpp>
#include <solanaceae/llama-cpp-web/text_completion_interface.hpp>
#include <solanaceae/contact/contact_model3.hpp>
#include <solanaceae/contact/contact_store_i.hpp>
#include <solanaceae/message3/registry_message_model.hpp>
#include <solanaceae/message3/message_command_dispatcher.hpp>
@ -19,8 +19,9 @@ struct StateTimingCheck;
struct RPBot : public RegistryMessageModelEventI {
TextCompletionI& _completion;
ConfigModelI& _conf;
Contact3Registry& _cr;
RegistryMessageModel& _rmm;
ContactStore4I& _cs;
RegistryMessageModelI& _rmm;
RegistryMessageModelI::SubscriptionReference _rmm_sr;
MessageCommandDispatcher* _mcd;
std::minstd_rand _rng{std::random_device{}()};
@ -29,8 +30,8 @@ struct RPBot : public RegistryMessageModelEventI {
RPBot(
TextCompletionI& completion,
ConfigModelI& conf,
Contact3Registry& cr,
RegistryMessageModel& rmm,
ContactStore4I& cs,
RegistryMessageModelI& rmm,
MessageCommandDispatcher* mcd
);
@ -41,13 +42,13 @@ struct RPBot : public RegistryMessageModelEventI {
protected: // state transitions
// all transitions need to be explicitly declared
template<typename To, typename From>
void stateTransition(const Contact3 c, const From& from, To& to) = delete;
void stateTransition(const Contact4 c, const From& from, To& to) = delete;
// reg helper
template<typename To, typename From>
To& emplaceStateTransition(Contact3Registry& cr, Contact3 c, const From& state) {
To& emplaceStateTransition(ContactStore4I& cs, Contact4 c, const From& state) {
std::cout << "RPBot: transition from " << From::name << " to " << To::name << "\n";
To& to = cr.emplace_or_replace<To>(c);
To& to = cs.registry().emplace_or_replace<To>(c);
stateTransition<To>(c, state, to);
return to;
}

View File

@ -18,16 +18,18 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
_rmm.sendText(
contact_from,
"error: already running"
);
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
_rmm.sendText(
contact_from,
"error: already running"
@ -35,13 +37,13 @@ void RPBot::registerCommands(void) {
return true;
}
if (_cr.all_of<Contact::Components::ParentOf>(contact_to)) {
if (cr.all_of<Contact::Components::ParentOf>(contact_to)) {
// group
auto& new_state = _cr.emplace<StateIdle>(contact_to);
auto& new_state = cr.emplace<StateIdle>(contact_to);
new_state.timeout = 10.f;
} else {
// pm
auto& new_state = _cr.emplace<StateIdle>(contact_from);
auto& new_state = cr.emplace<StateIdle>(contact_from);
new_state.timeout = 10.f;
}
@ -62,10 +64,10 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(*it)) {
if (cr.any_of<StateIdle, StateNextActor, StateGenerateMsg, StateTimingCheck>(*it)) {
_rmm.sendText(
contact_from,
"RPBot already running"
@ -73,7 +75,7 @@ void RPBot::registerCommands(void) {
return true;
}
auto& new_state = _cr.emplace<StateIdle>(*it);
auto& new_state = cr.emplace<StateIdle>(*it);
new_state.timeout = 10.f;
_rmm.sendText(
@ -102,18 +104,20 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
_cr.emplace_or_replace<TagStopRPBot>(contact_to);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
cr.emplace_or_replace<TagStopRPBot>(contact_to);
_rmm.sendText(
contact_from,
"stopped"
);
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
_cr.emplace_or_replace<TagStopRPBot>(contact_from);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
cr.emplace_or_replace<TagStopRPBot>(contact_from);
_rmm.sendText(
contact_from,
"stopped"
@ -138,11 +142,11 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
_cr.emplace_or_replace<TagStopRPBot>(*it);
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
cr.emplace_or_replace<TagStopRPBot>(*it);
_rmm.sendText(
contact_from,
"stopped"
@ -176,12 +180,14 @@ void RPBot::registerCommands(void) {
const auto contact_from = m.get<Message::Components::ContactFrom>().c;
const auto contact_to = m.get<Message::Components::ContactTo>().c;
auto& cr = _cs.registry();
if (params.empty()) {
// contact_to should be the contact this is for
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (_cr.all_of<StateIdle>(contact_to)) {
_cr.get<StateIdle>(contact_to).force = true;
_cr.get<StateIdle>(contact_to).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_to)) {
if (cr.all_of<StateIdle>(contact_to)) {
cr.get<StateIdle>(contact_to).force = true;
cr.get<StateIdle>(contact_to).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"
@ -189,10 +195,10 @@ void RPBot::registerCommands(void) {
}
return true;
}
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (_cr.all_of<StateIdle>(contact_from)) {
_cr.get<StateIdle>(contact_from).force = true;
_cr.get<StateIdle>(contact_from).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(contact_from)) {
if (cr.all_of<StateIdle>(contact_from)) {
cr.get<StateIdle>(contact_from).force = true;
cr.get<StateIdle>(contact_from).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"
@ -218,13 +224,13 @@ void RPBot::registerCommands(void) {
auto id_bin = hex2bin(params);
auto view = _cr.view<Contact::Components::ID>();
auto view = cr.view<Contact::Components::ID>();
for (auto it = view.begin(), it_end = view.end(); it != it_end; it++) {
if (view.get<Contact::Components::ID>(*it).data == id_bin) {
if (_cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
if (_cr.all_of<StateIdle>(*it)) {
_cr.get<StateIdle>(*it).force = true;
_cr.get<StateIdle>(*it).timeout = 2.f;
if (cr.any_of<StateIdle, StateGenerateMsg, StateNextActor, StateTimingCheck>(*it)) {
if (cr.all_of<StateIdle>(*it)) {
cr.get<StateIdle>(*it).force = true;
cr.get<StateIdle>(*it).timeout = 2.f;
_rmm.sendText(
contact_from,
"forced its hand"

View File

@ -22,7 +22,7 @@ struct StateNextActor {
std::string prompt;
std::vector<std::string> possible_names;
std::vector<Contact3> possible_contacts;
std::vector<Contact4> possible_contacts;
std::future<int64_t> future;
};

View File

@ -20,7 +20,7 @@ int main(void) {
}
std::cerr << lcw._cli.host() << " " << lcw._cli.port() << " endpoint healthy\n";
std::cout << "The meaning of life is to"
std::cerr << "The meaning of life is to"
<< lcw.complete(nlohmann::json{
{"prompt", "The meaning of life is to"},
{"min_p", 0.1}, // model dependent
@ -34,9 +34,9 @@ int main(void) {
})
<< "\n";
std::cout << "-------------------------\n";
std::cerr << "-------------------------\n";
std::cout << "complete from select:\n";
std::cerr << "complete from select:\n";
std::vector<std::string_view> possible {
" die",
" die.",
@ -46,12 +46,12 @@ int main(void) {
" Hi",
};
for (size_t i = 0; i < 10; i++) {
std::cout << "The meaning of life is to";
std::cerr << "The meaning of life is to";
auto res = lcw.completeSelect("The meaning of life is to", possible);
if (res < 0) {
std::cout << " error--\n";
std::cerr << " error\n";
} else {
std::cout << possible[res] << "\n";
std::cerr << possible[res] << "\n";
}
}