Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,6 @@
[submodule "libpsirngclient"]
path = libpsirngclient
url = https://github.com/nullspook/libpsirngclient.git
[submodule "meterfeeder"]
path = meterfeeder
url = https://github.com/vfp2/MeterFeeder.git
51 changes: 46 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,17 @@

quantum-llama.cpp is a modified [llama.cpp](https://github.com/ggml-org/llama.cpp)
that uses Quantum World Corporation (QWC) / ComScire QRNGs (Quantum Random
Number Generators) to generate the tokens. While the output may be
indistinguishable from the original llama.cpp, it introduces a poetic idea,
_"the output is co-authored by the universe itself."_
Number Generators) or MeterFeeder hardware RNG devices to generate the tokens.
While the output may be indistinguishable from the original llama.cpp, it introduces
a poetic idea, _"the output is co-authored by the universe itself."_

To use quantum-llama.cpp, you need to have a running [psirng](https://github.com/nullspook/psirng)
## Random Number Generator Options

quantum-llama.cpp supports two RNG systems:

### Option 1: PsiRNG (Network-based Quantum RNG)

To use PsiRNG, you need to have a running [psirng](https://github.com/nullspook/psirng)
server. Set `PSIRNG_HOST`, `PSIRNG_GRPC_PORT`, and `PSIRNG_CERT_PATH`
environment variables before running `llama-*` programs.

Expand All @@ -19,7 +25,7 @@ cd quantum-llama.cpp
cmake -B build
cmake --build build --config Release

# Set environment variables
# Set environment variables for PsiRNG
export PSIRNG_HOST=192.0.2.10
export PSIRNG_GRPC_PORT=50051
export PSIRNG_CERT_PATH=/path/to/cert.pem
Expand All @@ -29,6 +35,41 @@ cd build/bin
./llama-cli -m /path/to/model.gguf -p "I believe the meaning of life is" -n 128
```

### Option 2: MeterFeeder (Hardware RNG)

To use MeterFeeder hardware RNG devices, set the `METERFEEDER_USE_DEVICE`
environment variable with your device serial number.

```bash
# Clone
git clone --recurse-submodules https://github.com/nullspook/quantum-llama.cpp.git
cd quantum-llama.cpp

# Build MeterFeeder library
cd meterfeeder
chmod +x linux-build-lib.sh
./linux-build-lib.sh
cd ..

# Build quantum-llama.cpp
cmake -B build
cmake --build build --config Release

# Set environment variable for MeterFeeder
export METERFEEDER_USE_DEVICE="your_device_serial_number"

# Run
cd build/bin
./llama-cli -m /path/to/model.gguf -p "I believe the meaning of life is" -n 128
```

### Automatic Detection

The system automatically detects which RNG to use based on environment variables:
- If `METERFEEDER_USE_DEVICE` is set, it uses MeterFeeder
- If `PSIRNG_HOST`, `PSIRNG_GRPC_PORT`, and `PSIRNG_CERT_PATH` are set, it uses PsiRNG
- If neither is configured, the system will exit with an error

**Note:** quantum-llama.cpp must be built using `cmake`.

---
Expand Down
6 changes: 6 additions & 0 deletions src/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@ target_compile_features (llama PUBLIC cxx_std_11) # don't bump

target_link_libraries(llama PUBLIC ggml psirngclient)

# Add MeterFeeder library if it exists
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../meterfeeder/builds/linux/libmeterfeeder.so")
target_link_libraries(llama PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../meterfeeder/builds/linux/libmeterfeeder.so")
target_link_directories(llama PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/../meterfeeder/builds/linux")
endif()

if (BUILD_SHARED_LIBS)
set_target_properties(llama PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_compile_definitions(llama PRIVATE LLAMA_SHARED LLAMA_BUILD)
Expand Down
16 changes: 13 additions & 3 deletions src/llama-sampling.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -628,9 +628,19 @@ llama_token llama_sample_token_with_rng_impl(struct llama_sampling * smpl, llama
int idx;
double u;

int rand_result = psirngclient_randuniform(smpl->psirngclient_ptr, &u, 1, 0.0, 1.0);
if (rand_result != PSIRNGCLIENT_RESULT_OK) {
GGML_ABORT("psirngclient_randuniform error: %d", rand_result);
if (smpl->use_meterfeeder) {
// Use MeterFeeder for random number generation
char error_reason[256];
u = MF_RandUniform(smpl->meterfeeder_serial_number, error_reason);
if (strlen(error_reason) > 0) {
GGML_ABORT("MF_RandUniform error: %s", error_reason);
}
} else {
// Use PsiRNGClient for random number generation
int rand_result = psirngclient_randuniform(smpl->psirngclient_ptr, &u, 1, 0.0, 1.0);
if (rand_result != PSIRNGCLIENT_RESULT_OK) {
GGML_ABORT("psirngclient_randuniform error: %d", rand_result);
}
}

idx = static_cast<int>(std::distance(cdf.begin(), std::lower_bound(cdf.begin(), cdf.end(), u)));
Expand Down
30 changes: 30 additions & 0 deletions src/llama-sampling.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,43 @@

#include "psirngclient.h"

// MeterFeeder function declarations
#ifdef __cplusplus
extern "C" {
#endif

// Initialize the connected generators
int MF_Initialize(char* pErrorReason);

// Get the number of connected and successfully initialized generators
int MF_GetNumberGenerators();

// Get the list of connected and successfully initialized generators
// Array element format: <serial number>
int MF_GetSerialListGeneratorsWithSize(char** pGenerators, int arraySize);

// Get a random floating point number between [0,1)
double MF_RandUniform(char* generatorSerialNumber, char* pErrorReason);

// Shutdown and de-initialize all the generators
void MF_Shutdown();

#ifdef __cplusplus
}
#endif

struct llama_sampling {
llama_sampling(int32_t n_vocab) : n_vocab(n_vocab) {}

std::mt19937 rng;

// PsiRNGClient support
psirngclient * psirngclient_ptr;

// MeterFeeder support
char* meterfeeder_serial_number;
bool use_meterfeeder;

int32_t n_vocab = 0;

mutable int64_t t_sample_us = 0;
Expand Down
99 changes: 86 additions & 13 deletions src/llama.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3191,6 +3191,12 @@ struct llama_context {
}

ggml_backend_buffer_free(buf_output);

// Clean up MeterFeeder resources
if (sampling.use_meterfeeder) {
delete[] sampling.meterfeeder_serial_number;
MF_Shutdown();
}
}

const struct llama_model & model;
Expand Down Expand Up @@ -18195,28 +18201,95 @@ struct llama_context * llama_new_context_with_model(
ctx->sampling.rng = std::mt19937(params.seed);

ctx->sampling.psirngclient_ptr = nullptr;
ctx->sampling.meterfeeder_serial_number = nullptr;
ctx->sampling.use_meterfeeder = false;

// Check for MeterFeeder configuration first
const char* meterfeeder_device = std::getenv("METERFEEDER_USE_DEVICE");
if (meterfeeder_device != nullptr) {
// Initialize MeterFeeder
char error_reason[256];
if (int result = MF_Initialize(error_reason); result != 1) {
LLAMA_LOG_ERROR("%s: failed to initialize MeterFeeder: %s\n", __func__, error_reason);
llama_free(ctx);
return nullptr;
}

const char* psirng_host = std::getenv("PSIRNG_HOST");
const char* psirng_grpc_port = std::getenv("PSIRNG_GRPC_PORT");
const char* psirng_cert_path = std::getenv("PSIRNG_CERT_PATH");
// Check if the specified device exists
int num_generators = MF_GetNumberGenerators();
if (num_generators <= 0) {
LLAMA_LOG_ERROR("%s: no MeterFeeder devices found\n", __func__);
llama_free(ctx);
return nullptr;
}

if (psirng_host != nullptr && psirng_grpc_port != nullptr && psirng_cert_path != nullptr) {
if (int result = psirngclient_init(&ctx->sampling.psirngclient_ptr, psirng_host, std::stoi(psirng_grpc_port), psirng_cert_path); result != PSIRNGCLIENT_RESULT_OK) {
LLAMA_LOG_ERROR("%s: failed to initialize psirng client: %d\n", __func__, result);
// Get list of generators and check if our device is in the list
char** generators = new char*[num_generators];
for (int i = 0; i < num_generators; i++) {
generators[i] = new char[256];
}

int result = MF_GetSerialListGeneratorsWithSize(generators, num_generators);
if (result != num_generators) {
LLAMA_LOG_ERROR("%s: failed to get MeterFeeder device list\n", __func__);
for (int i = 0; i < num_generators; i++) {
delete[] generators[i];
}
delete[] generators;
llama_free(ctx);
return nullptr;
}
if (!psirngclient_ishealthy(ctx->sampling.psirngclient_ptr)) {
LLAMA_LOG_ERROR("%s: psirng is not healthy\n", __func__);

bool device_found = false;
for (int i = 0; i < num_generators; i++) {
if (strcmp(generators[i], meterfeeder_device) == 0) {
device_found = true;
break;
}
}

// Clean up generators array
for (int i = 0; i < num_generators; i++) {
delete[] generators[i];
}
delete[] generators;

if (!device_found) {
LLAMA_LOG_ERROR("%s: MeterFeeder device '%s' not found\n", __func__, meterfeeder_device);
llama_free(ctx);
return nullptr;
} else {
LLAMA_LOG_INFO("%s: Using psirng running on %s:%s\n", __func__, psirng_host, psirng_grpc_port);
}

// Store the device serial number
ctx->sampling.meterfeeder_serial_number = new char[strlen(meterfeeder_device) + 1];
strcpy(ctx->sampling.meterfeeder_serial_number, meterfeeder_device);
ctx->sampling.use_meterfeeder = true;

LLAMA_LOG_INFO("%s: Using MeterFeeder device: %s\n", __func__, meterfeeder_device);
} else {
LLAMA_LOG_ERROR("%s: psirng is not configured\n", __func__);
llama_free(ctx);
return nullptr;
// Fall back to PsiRNGClient configuration
const char* psirng_host = std::getenv("PSIRNG_HOST");
const char* psirng_grpc_port = std::getenv("PSIRNG_GRPC_PORT");
const char* psirng_cert_path = std::getenv("PSIRNG_CERT_PATH");

if (psirng_host != nullptr && psirng_grpc_port != nullptr && psirng_cert_path != nullptr) {
if (int result = psirngclient_init(&ctx->sampling.psirngclient_ptr, psirng_host, std::stoi(psirng_grpc_port), psirng_cert_path); result != PSIRNGCLIENT_RESULT_OK) {
LLAMA_LOG_ERROR("%s: failed to initialize psirng client: %d\n", __func__, result);
llama_free(ctx);
return nullptr;
}
if (!psirngclient_ishealthy(ctx->sampling.psirngclient_ptr)) {
LLAMA_LOG_ERROR("%s: psirng is not healthy\n", __func__);
llama_free(ctx);
return nullptr;
} else {
LLAMA_LOG_INFO("%s: Using psirng running on %s:%s\n", __func__, psirng_host, psirng_grpc_port);
}
} else {
LLAMA_LOG_ERROR("%s: neither MeterFeeder nor psirng is configured\n", __func__);
llama_free(ctx);
return nullptr;
}
}

ctx->logits_all = params.logits_all;
Expand Down