src/src/main.cpp
Classes
Functions
Functions Documentation
function PrintHelp
static void PrintHelp(
const char * prog
)
function LoadConfigFile
static void LoadConfigFile(
const std::string & path,
Args & args
)
function ParseArgs
static Args ParseArgs(
int argc,
char ** argv
)
function ParseMode
static ExecutionMode ParseMode(
const std::string & mode
)
function RunInteractive
static void RunInteractive(
api::ApiServer & server,
ExecutionMode mode,
int max_tokens,
float temperature
)
function main
int main(
int argc,
char ** argv
)
Source code
#include "api/api_server.hpp"
#include "common/logging.hpp"
#include <fstream>
#include <iostream>
#include <nlohmann/json.hpp>
#include <stdexcept>
#include <string>
using namespace sgns::neoswarm;
// ---------------------------------------------------------------------------
// Argument parser
// ---------------------------------------------------------------------------
struct Args
{
std::string m_modelPath;
std::string m_grammarModelPath;
std::string m_mathModelPath;
std::string m_mode = "auto";
std::string m_prompt;
int port_ = 50051;
std::string db_path_ = "./reputation.db";
std::string key_file_ = "./node.key";
std::string m_knowledgePath;
int m_maxTokens = 512;
float m_temperature = 0.7f;
std::string m_sgSdkPath = "./sdk";
std::string config_path_;
bool network_ = false;
bool serve_ = false;
bool verbose_ = false;
bool help_ = false;
};
static void PrintHelp( const char* prog )
{
std::cout << "Usage: " << prog << " --model <path> [options]\n\n"
<< "Options:\n"
<< " --model <path> Core MNN model file (required)\n"
<< " --grammar-model <path> Grammar specialist model\n"
<< " --math-model <path> Math specialist model\n"
<< " --mode single|specialist|swarm Execution mode (default: auto)\n"
<< " --prompt <text> Prompt to process\n"
<< " --port <n> gRPC port (default: 50051)\n"
<< " --db <path> Reputation DB (default: ./reputation.db)\n"
<< " --key <path> Node key file (default: ./node.key)\n"
<< " --config <path> JSON config file (CLI flags override file values)\n"
<< " --sg-sdk-path <path> GeniusSDK data directory (default: ./sdk)\n"
<< " --sg-base-port <n> SDK network port (default: 40001)\n"
<< " --network Enable P2P networking\n"
<< " --knowledge <path> Grokipedia facts CSV\n"
<< " --max-tokens <n> Max tokens (default: 512)\n"
<< " --temperature <f> Temperature (default: 0.7)\n"
<< " --serve Start gRPC server\n"
<< " --verbose Debug logging\n"
<< " --help Show this help\n";
}
// ---------------------------------------------------------------------------
// Config file loader
// ---------------------------------------------------------------------------
static void LoadConfigFile( const std::string& path, Args& args )
{
std::ifstream f( path );
if ( !f.is_open() )
{
std::cerr << "Warning: cannot open config file '" << path << "'\n";
return;
}
nlohmann::json j;
try
{
f >> j;
}
catch ( const std::exception& e )
{
std::cerr << "Warning: invalid JSON in config file '" << path << "': " << e.what() << "\n";
return;
}
// Only set defaults — CLI args will override
if ( j.contains( "model" ) && args.m_modelPath.empty() )
args.m_modelPath = j["model"].get<std::string>();
if ( j.contains( "grammar_model" ) && args.m_grammarModelPath.empty() )
args.m_grammarModelPath = j["grammar_model"].get<std::string>();
if ( j.contains( "math_model" ) && args.m_mathModelPath.empty() )
args.m_mathModelPath = j["math_model"].get<std::string>();
if ( j.contains( "mode" ) && args.m_mode == "auto" )
args.m_mode = j["mode"].get<std::string>();
if ( j.contains( "port" ) && args.port_ == 50051 )
args.port_ = j["port"].get<int>();
if ( j.contains( "db" ) && args.db_path_ == "./reputation.db" )
args.db_path_ = j["db"].get<std::string>();
if ( j.contains( "key" ) && args.key_file_ == "./node.key" )
args.key_file_ = j["key"].get<std::string>();
if ( j.contains( "knowledge" ) && args.m_knowledgePath.empty() )
args.m_knowledgePath = j["knowledge"].get<std::string>();
if ( j.contains( "max_tokens" ) && args.m_maxTokens == 512 )
args.m_maxTokens = j["max_tokens"].get<int>();
if ( j.contains( "temperature" ) && args.m_temperature == 0.7f )
args.m_temperature = j["temperature"].get<float>();
if ( j.contains( "sg_sdk_path" ) && args.m_sgSdkPath == "./sdk" )
args.m_sgSdkPath = j["sg_sdk_path"].get<std::string>();
if ( j.contains( "network" ) && !args.network_ )
args.network_ = j["network"].get<bool>();
if ( j.contains( "verbose" ) && !args.verbose_ )
args.verbose_ = j["verbose"].get<bool>();
std::cout << "Loaded config: " << path << "\n";
}
static Args ParseArgs( int argc, char** argv )
{
Args args;
for ( int i = 1; i < argc; ++i )
{
std::string a = argv[i];
auto next = [&]() -> std::string
{
if ( i + 1 >= argc )
throw std::runtime_error( "missing value for " + a );
return argv[++i];
};
if ( a == "--model" )
args.m_modelPath = next();
else if ( a == "--grammar-model" )
args.m_grammarModelPath = next();
else if ( a == "--math-model" )
args.m_mathModelPath = next();
else if ( a == "--mode" )
args.m_mode = next();
else if ( a == "--prompt" )
args.m_prompt = next();
else if ( a == "--port" )
args.port_ = std::stoi( next() );
else if ( a == "--db" )
args.db_path_ = next();
else if ( a == "--key" )
args.key_file_ = next();
else if ( a == "--knowledge" )
args.m_knowledgePath = next();
else if ( a == "--max-tokens" )
args.m_maxTokens = std::stoi( next() );
else if ( a == "--temperature" )
args.m_temperature = std::stof( next() );
else if ( a == "--config" )
args.config_path_ = next();
else if ( a == "--sg-sdk-path" )
args.m_sgSdkPath = next();
else if ( a == "--network" )
args.network_ = true;
else if ( a == "--serve" )
args.serve_ = true;
else if ( a == "--verbose" )
args.verbose_ = true;
else if ( a == "--help" )
args.help_ = true;
else
std::cerr << "Unknown option: " << a << "\n";
}
return args;
}
static ExecutionMode ParseMode( const std::string& mode )
{
if ( mode == "single" )
return ExecutionMode::SingleNode;
if ( mode == "specialist" )
return ExecutionMode::Specialist;
if ( mode == "swarm" )
return ExecutionMode::Swarm;
return ExecutionMode::SingleNode; // "auto" — router decides
}
// ---------------------------------------------------------------------------
// Interactive REPL
// ---------------------------------------------------------------------------
static void RunInteractive( api::ApiServer& server, ExecutionMode mode, int max_tokens, float temperature )
{
std::cout << "\nNEO SWARM v1 — Interactive Mode\n"
<< "Type your prompt and press Enter. Type 'quit' to exit.\n\n";
std::string line;
while ( true )
{
std::cout << "> ";
if ( !std::getline( std::cin, line ) )
break;
if ( line == "quit" || line == "exit" )
break;
if ( line.empty() )
continue;
Task task;
task.m_prompt = line;
task.m_mode = mode;
task.m_maxTokens = static_cast<uint32_t>( max_tokens );
task.m_temperature = temperature;
auto res = server.Process( task );
if ( !res.has_value() )
{
std::cerr << "[ERROR] inference failed\n";
}
else
{
std::cout << "\n" << res.value().m_output << "\n\n";
std::cout << "[mode=" << static_cast<int>( res.value().m_modeUsed )
<< " latency=" << res.value().m_totalLatencyMs << "ms]\n\n";
}
}
}
// ---------------------------------------------------------------------------
// main
// ---------------------------------------------------------------------------
int main( int argc, char** argv )
{
Args args;
try
{
args = ParseArgs( argc, argv );
}
catch ( const std::exception& e )
{
std::cerr << "Argument error: " << e.what() << "\n";
return 1;
}
if ( args.help_ )
{
PrintHelp( argv[0] );
return 0;
}
// Load config file if specified (CLI flags already parsed, override file values)
if ( !args.config_path_.empty() )
{
LoadConfigFile( args.config_path_, args );
}
if ( args.verbose_ )
{
spdlog::set_level( spdlog::level::debug );
}
// Build server config
api::ApiServer::Config cfg;
cfg.m_modelPath = args.m_modelPath;
cfg.m_grammarModelPath = args.m_grammarModelPath;
cfg.m_mathModelPath = args.m_mathModelPath;
cfg.m_reputationDbPath = args.db_path_;
cfg.m_knowledgeFacts = args.m_knowledgePath;
cfg.m_enableNetwork = args.network_;
cfg.m_enableKnowledge = true;
(void) args.port_;
cfg.m_nodeKeyFile = args.key_file_;
cfg.m_sgSdkBasePath = args.m_sgSdkPath;
api::ApiServer server( cfg );
auto init_res = server.Initialize();
if ( !init_res.has_value() )
{
std::cerr << "[FATAL] Initialization failed\n";
return 1;
}
ExecutionMode mode = ( args.m_mode == "auto" ) ? ExecutionMode::SingleNode : ParseMode( args.m_mode );
if ( args.serve_ )
{
auto serve_res = server.Serve();
if ( !serve_res.has_value() )
{
std::cerr << "[FATAL] Serve failed\n";
return 1;
}
return 0;
}
if ( !args.m_prompt.empty() )
{
Task task;
task.m_prompt = args.m_prompt;
task.m_mode = mode;
task.m_maxTokens = static_cast<uint32_t>( args.m_maxTokens );
task.m_temperature = args.m_temperature;
auto res = server.Process( task );
if ( !res.has_value() )
{
std::cerr << "[ERROR] inference failed\n";
return 1;
}
std::cout << res.value().m_output << "\n";
return 0;
}
RunInteractive( server, mode, args.m_maxTokens, args.m_temperature );
return 0;
}
Updated on 2026-07-25 at 22:56:57 +0000