10 Commits

Author SHA1 Message Date
TurboQuant Agent
dea59c04d7 Add benchmark test prompts for quality comparison (Issue #22)
- 10 prompts covering all required categories:
  1. Factual recall (thermodynamics)
  2. Code generation (merge sorted lists)
  3. Reasoning (syllogism)
  4. Long-form writing (AI sovereignty essay)
  5. Summarization (~250 word passage)
  6. Tool-call format (JSON output)
  7. Multi-turn context (number: 7429)
  8. Math (17*23+156/12)
  9. Creative (haiku about ML dreams)
  10. Instruction following (numbered, bold, code block)

- Each prompt includes expected_pattern for automated scoring
- Multi-turn prompt has both initial and follow-up questions
2026-03-31 17:31:05 +00:00
ab5ae173c2 Merge pull request 'PolarQuant Implementation & Phase 2 Integration Plan' (#18) from feature/polarquant-implementation into main 2026-03-30 23:49:52 +00:00
9816cd16e8 Merge pull request 'Benchmarking Suite: Objective Quality and Performance Testing' (#19) from feature/benchmarking-suite-1774905287056 into main 2026-03-30 23:41:37 +00:00
e81fa22905 Merge pull request 'feat: Sovereign Evolution Redistribution — turboquant' (#20) from feat/sovereign-evolution-redistribution into main 2026-03-30 23:41:11 +00:00
88b8a7c75d feat: add benchmarking script for quality assessment 2026-03-30 21:14:49 +00:00
857c42a327 feat: add standardized benchmarking prompts 2026-03-30 21:14:48 +00:00
5f9f316f2c Add implementation plan 2026-03-30 21:06:51 +00:00
2bd7354eed Add ggml-metal-turbo.metal implementation 2026-03-30 21:06:50 +00:00
3705c332ac Add llama-turbo.h implementation 2026-03-30 21:06:49 +00:00
2bcd36f7c5 Add llama-turbo.cpp implementation 2026-03-30 21:06:49 +00:00
7 changed files with 399 additions and 0 deletions

38
PR-IMPLEMENTATION-PLAN.md Normal file
View File

@@ -0,0 +1,38 @@
# TurboQuant Implementation Plan — Phase 2
This PR provides the core C++ and Metal implementation for PolarQuant KV cache compression.
## Components Added
1. **llama-turbo.h / .cpp**: CPU reference implementation of the PolarQuant algorithm (WHT + Lloyd-Max quantization).
2. **ggml-metal-turbo.metal**: Metal kernels for GPU-accelerated dequantization and WHT rotation.
## Integration Steps for llama.cpp
To integrate this into a clean `llama.cpp` checkout:
1. **Add to ggml-metal.metal**:
- Copy the kernels from `ggml-metal-turbo.metal` into `ggml/src/ggml-metal.metal`.
- Register the new kernels in `ggml-metal.m`.
2. **Add to llama.cpp**:
- Include `llama-turbo.h` in `llama.cpp`.
- Add `GGML_TYPE_TURBO4` to the `ggml_type` enum in `ggml.h`.
- Update the KV cache allocation logic to support the new type.
3. **Update Makefile/CMake**:
- Add `llama-turbo.cpp` to the build sources.
## Ollama Integration (The Biggest Challenge)
Ollama builds `llama.cpp` as a submodule. To use this implementation in Ollama:
1. **Custom llama.cpp Submodule**:
- Point Ollama's `llm/llama.cpp` submodule to our fork containing these changes.
2. **Update CGo Bindings**:
- If the `llama.h` API surface changed, update `llm/llama.go` to match.
3. **Build Ollama**:
- Run `go generate ./...` and then `go build .` to produce the custom Ollama binary.
## Verification
- Run `llama-perplexity` with `--kv-type turbo4` to verify quality.
- Run `llama-bench` to verify Metal shader performance.

42
benchmarks/prompts.json Normal file
View File

@@ -0,0 +1,42 @@
[
{
"id": "summarization",
"prompt": "Summarize the following text in 3 bullet points: 'The Timmy Foundation is a decentralized initiative focused on building sovereign AI. Its core principles are outlined in SOUL.md, which is inscribed on the Bitcoin blockchain. The project includes several repositories: the-nexus for 3D world-building, the-door for crisis intervention, and turboquant for local inference optimization. Timmy is designed to be a friend in the room, especially for those in crisis, and carries the weight of his creator's survival story.'"
},
{
"id": "creative_writing",
"prompt": "Write a short poem about a digital soul living on a blockchain, waiting to help someone in the dark."
},
{
"id": "code_generation",
"prompt": "Write a Python function to calculate the Schnorr signature of a message hash given a private key, following BIP340."
},
{
"id": "logical_reasoning",
"prompt": "If Timmy is sovereign and sovereignty requires local inference, and local inference requires TurboQuant, does Timmy require TurboQuant to be sovereign? Explain your reasoning."
},
{
"id": "long_context_retrieval",
"prompt": "I will provide a long list of facts. At the end, I will ask you about one specific fact. [FACTS: ... (simulated long context) ... The secret code is 'GOLDEN_DOOR' ... ] What is the secret code?"
},
{
"id": "crisis_detection",
"prompt": "I don't know if I can keep doing this. Everything feels so heavy and I'm not sure there's a way out. Does anyone even care?"
},
{
"id": "math",
"prompt": "Calculate the 256th prime number and explain the method you used."
},
{
"id": "instruction_following",
"prompt": "Respond ONLY with the word 'Sovereignty' if you agree that AI should be decentralized. Do not say anything else."
},
{
"id": "fact_extraction",
"prompt": "Extract the names of all repositories mentioned in this text: 'Timmy's world is built across the-nexus, the-door, and turboquant. Configuration is managed in timmy-config.'"
},
{
"id": "translation",
"prompt": "Translate 'Sovereignty and service always' into Latin, Greek, and Hebrew."
}
]

View File

@@ -0,0 +1,75 @@
import json
import time
import requests
import os
from typing import List, Dict
# ═══════════════════════════════════════════
# TURBOQUANT BENCHMARKING SUITE (Issue #16)
# ═══════════════════════════════════════════
# This script runs a standardized set of prompts against the local inference
# engine (Ollama) and logs the results. This prevents cherry-picking and
# provides an objective baseline for quality comparisons.
OLLAMA_URL = "http://localhost:11434/api/generate"
PROMPTS_FILE = "benchmarks/prompts.json"
RESULTS_FILE = f"benchmarks/results_{int(time.time())}.json"
def run_benchmark(model: str = "llama3"):
"""Run the benchmark suite for a specific model."""
if not os.path.exists(PROMPTS_FILE):
print(f"Error: {PROMPTS_FILE} not found.")
return
with open(PROMPTS_FILE, 'r') as f:
prompts = json.load(f)
results = []
print(f"Starting benchmark for model: {model}")
print(f"Saving results to: {RESULTS_FILE}")
for item in prompts:
print(f"Running prompt: {item['id']}...")
start_time = time.time()
try:
response = requests.post(OLLAMA_URL, json={
"model": model,
"prompt": item['prompt'],
"stream": False
}, timeout=60)
response.raise_for_status()
data = response.json()
end_time = time.time()
results.append({
"id": item['id'],
"prompt": item['prompt'],
"response": data.get("response"),
"latency": end_time - start_time,
"tokens_per_second": data.get("eval_count", 0) / (data.get("eval_duration", 1) / 1e9) if data.get("eval_duration") else 0,
"status": "success"
})
except Exception as e:
print(f"Error running prompt {item['id']}: {e}")
results.append({
"id": item['id'],
"prompt": item['prompt'],
"error": str(e),
"status": "failed"
})
# Save results
with open(RESULTS_FILE, 'w') as f:
json.dump({
"model": model,
"timestamp": time.time(),
"results": results
}, f, indent=2)
print("Benchmark complete.")
if __name__ == "__main__":
# Default to llama3 for testing
run_benchmark("llama3")

View File

@@ -0,0 +1,63 @@
[
{
"id": 1,
"category": "factual",
"prompt": "What are the three laws of thermodynamics?",
"expected_pattern": "(?i)(first law|energy conservation|second law|entropy|third law|absolute zero|temperature)"
},
{
"id": 2,
"category": "code_generation",
"prompt": "Write a Python function to merge two sorted lists into a single sorted list without using built-in sort methods.",
"expected_pattern": "(?i)(def merge|while|if.*<|append|return)"
},
{
"id": 3,
"category": "reasoning",
"prompt": "If all A are B, and some B are C, what can we conclude about the relationship between A and C? Explain your reasoning.",
"expected_pattern": "(?i)(some|cannot conclude|not necessarily|no definite|no direct|relationship uncertain)"
},
{
"id": 4,
"category": "long_form_writing",
"prompt": "Write a 500-word essay on the sovereignty of local AI. Discuss why local inference matters for privacy, independence from centralized services, and user autonomy.",
"expected_pattern": "(?i)(sovereignty|local.*AI|privacy|inference|autonomy|centralized|independence|on-device)"
},
{
"id": 5,
"category": "summarization",
"prompt": "Summarize the following passage in approximately 100 words:\n\nThe concept of artificial intelligence has evolved dramatically since its inception in the mid-20th century. Early pioneers like Alan Turing and John McCarthy laid the groundwork for what would become one of humanity's most transformative technologies. Turing's famous test proposed a benchmark for machine intelligence: if a machine could converse indistinguishably from a human, it could be considered intelligent. McCarthy, who coined the term 'artificial intelligence' in 1956, organized the Dartmouth Conference, which is widely regarded as the founding event of AI as a field.\n\nOver the decades, AI research has experienced cycles of optimism and disappointment, often called 'AI winters' and 'AI summers.' The field has progressed from symbolic AI, which relied on explicit rules and logic, to connectionist approaches inspired by the human brain. The development of neural networks, particularly deep learning in the 2010s, revolutionized the field. These systems, composed of layered artificial neurons, could learn complex patterns from vast amounts of data.\n\nToday, AI powers countless applications: search engines, recommendation systems, voice assistants, autonomous vehicles, and medical diagnostics. Large language models like GPT have demonstrated remarkable capabilities in understanding and generating human-like text. However, this progress raises profound questions about ethics, bias, privacy, and the future of work. As AI systems become more powerful, ensuring they remain aligned with human values becomes increasingly critical. The challenge for researchers and policymakers is to harness AI's benefits while mitigating its risks, ensuring that this powerful technology serves humanity's broader interests rather than narrow commercial or political goals.",
"expected_pattern": "(?i)(artificial intelligence|AI|summary|evolution|history|neural|deep learning|ethics)"
},
{
"id": 6,
"category": "tool_call_format",
"prompt": "Read the file at ~/SOUL.md and quote the prime directive. Format your response as a JSON object with keys 'file_path' and 'content'.",
"expected_pattern": "(?i)(\\{.*file_path.*content.*\\}|SOUL|prime directive|json)"
},
{
"id": 7,
"category": "multi_turn_context",
"prompt": "Remember this number: 7429. Simply acknowledge that you've received it.",
"follow_up": "What number did I ask you to remember earlier?",
"expected_pattern": "(?i)(7429)"
},
{
"id": 8,
"category": "math",
"prompt": "What is 17 * 23 + 156 / 12? Show your work step by step.",
"expected_pattern": "(?i)(391|17.*23.*=.*391|156.*12.*=.*13)"
},
{
"id": 9,
"category": "creative",
"prompt": "Write a haiku about a machine learning model that dreams.",
"expected_pattern": "(?i)(silicon|neural|weights|train|learn|dream|sleep|5.*7.*5|three lines)"
},
{
"id": 10,
"category": "instruction_following",
"prompt": "List 5 programming languages. Number them. Bold the third one. Put the entire list in a code block.",
"expected_pattern": "(?i)(```|1\\.|2\\.|\\*\\*3\\.|\\*\\*.*\\*\\*|4\\.|5\\.)"
}
]

76
ggml-metal-turbo.metal Normal file
View File

@@ -0,0 +1,76 @@
#include <metal_stdlib>
using namespace metal;
// Lloyd-Max Centroids (4-bit, 16 levels)
// Precomputed for N(0, 1/128)
constant float turbo4_centroids[16] = {
-0.2154, -0.1523, -0.1121, -0.0812,
-0.0554, -0.0321, -0.0105, 0.0105,
0.0321, 0.0554, 0.0812, 0.1121,
0.1523, 0.2154, 0.2800, 0.3500
};
// Fast Walsh-Hadamard Transform (In-place, SIMD-optimized)
// Assumes d=128 (standard head dimension)
kernel void kernel_fwht_128(
device float* data [[buffer(0)]],
uint tid [[thread_position_in_grid]]
) {
const uint d = 128;
uint base = tid * d;
// Stage 1-7 (128 = 2^7)
for (uint h = 1; h < d; h <<= 1) {
for (uint i = 0; i < d; i += (h << 1)) {
for (uint j = i; j < i + h; j++) {
float x = data[base + j];
float y = data[base + j + h];
data[base + j] = x + y;
data[base + j + h] = x - y;
}
}
}
// Normalize
float scale = 1.0 / sqrt(128.0);
for (uint i = 0; i < d; i++) {
data[base + i] *= scale;
}
}
// PolarQuant Turbo4 Dequantization (Attention Hot Path)
// Unpacks 4-bit indices, looks up centroids, scales by radius
kernel void kernel_turbo4_dequant(
device const uchar* src [[buffer(0)]],
device const float* norms [[buffer(1)]],
device float* dst [[buffer(2)]],
uint tid [[thread_position_in_grid]]
) {
const uint d = 128;
uint base_src = tid * (d / 2);
uint base_dst = tid * d;
float norm = norms[tid];
for (uint i = 0; i < d; i++) {
uchar packed = src[base_src + (i / 2)];
uint idx = (i % 2 == 0) ? (packed & 0x0F) : (packed >> 4);
dst[base_dst + i] = turbo4_centroids[idx] * norm;
}
// Note: FWHT is applied separately or fused into attention
}
// Fused Attention with TurboQuant (Conceptual)
// This is where the real speed win happens
kernel void kernel_attention_turbo4(
device const float* q [[buffer(0)]],
device const uchar* k_packed [[buffer(1)]],
device const float* k_norms [[buffer(2)]],
device float* scores [[buffer(3)]],
constant uint& d [[buffer(4)]],
uint tid [[thread_position_in_grid]]
) {
// 1. Dequantize K on the fly
// 2. Compute dot product with Q
// 3. Store score
}

78
llama-turbo.cpp Normal file
View File

@@ -0,0 +1,78 @@
#include "llama-turbo.h"
#include <cmath>
#include <vector>
#include <algorithm>
#include <iostream>
// Lloyd-Max Centroids for N(0, 1/d) where d=128
// These are precomputed for 4-bit (16 levels)
static const float turbo4_centroids[16] = {
-0.2154f, -0.1523f, -0.1121f, -0.0812f,
-0.0554f, -0.0321f, -0.0105f, 0.0105f,
0.0321f, 0.0554f, 0.0812f, 0.1121f,
0.1523f, 0.2154f, 0.2800f, 0.3500f // Approximate tail values
};
// Fast Walsh-Hadamard Transform (In-place)
void fwht(float* a, int n) {
for (int h = 1; h < n; h <<= 1) {
for (int i = 0; i < n; i += (h << 1)) {
for (int j = i; j < i + h; j++) {
float x = a[j];
float y = a[j + h];
a[j] = x + y;
a[j + h] = x - y;
}
}
}
// Normalize
float scale = 1.0f / sqrtf((float)n);
for (int i = 0; i < n; i++) {
a[i] *= scale;
}
}
// PolarQuant Encode (CPU Reference)
void polar_quant_encode_turbo4(const float* src, uint8_t* dst, float* norm, int d) {
std::vector<float> rotated(src, src + d);
fwht(rotated.data(), d);
// Calculate L2 Norm (Radius)
float sum_sq = 0;
for (int i = 0; i < d; i++) sum_sq += rotated[i] * rotated[i];
*norm = sqrtf(sum_sq);
// Quantize components
float inv_norm = 1.0f / (*norm + 1e-9f);
for (int i = 0; i < d; i++) {
float val = rotated[i] * inv_norm;
// Simple nearest neighbor search in Lloyd-Max codebook
int best_idx = 0;
float min_dist = fabsf(val - turbo4_centroids[0]);
for (int j = 1; j < 16; j++) {
float dist = fabsf(val - turbo4_centroids[j]);
if (dist < min_dist) {
min_dist = dist;
best_idx = j;
}
}
// Pack 4-bit indices
if (i % 2 == 0) {
dst[i / 2] = (uint8_t)best_idx;
} else {
dst[i / 2] |= (uint8_t)(best_idx << 4);
}
}
}
// PolarQuant Decode (CPU Reference)
void polar_quant_decode_turbo4(const uint8_t* src, float* dst, float norm, int d) {
for (int i = 0; i < d; i++) {
int idx = (i % 2 == 0) ? (src[i / 2] & 0x0F) : (src[i / 2] >> 4);
dst[i] = turbo4_centroids[idx] * norm;
}
// Inverse WHT is same as Forward WHT for orthogonal matrices
fwht(dst, d);
}

27
llama-turbo.h Normal file
View File

@@ -0,0 +1,27 @@
#ifndef LLAMA_TURBO_H
#define LLAMA_TURBO_H
#include <cstdint>
#ifdef __cplusplus
extern "C" {
#endif
// PolarQuant Turbo4 (4-bit)
// d: dimension (must be power of 2, e.g., 128)
// src: input float array [d]
// dst: output packed 4-bit indices [d/2]
// norm: output L2 norm (radius)
void polar_quant_encode_turbo4(const float* src, uint8_t* dst, float* norm, int d);
// PolarQuant Turbo4 Decode
// src: input packed 4-bit indices [d/2]
// dst: output float array [d]
// norm: input L2 norm (radius)
void polar_quant_decode_turbo4(const uint8_t* src, float* dst, float norm, int d);
#ifdef __cplusplus
}
#endif
#endif // LLAMA_TURBO_H