feat: Implement The Chorus using Minimax and Moonshot
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env python3
|
#!/usr/bin/env python3
|
||||||
"""
|
"""
|
||||||
BECOMINGONE Flask API - Integrated Prototype
|
BECOMINGONE Flask API - Integrated Prototype (The Chorus)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import os
|
import os
|
||||||
@@ -14,15 +14,11 @@ from becomingone.memory.temporal import create_temporal_memory
|
|||||||
|
|
||||||
app = Flask(__name__)
|
app = Flask(__name__)
|
||||||
|
|
||||||
# Ollama endpoints (Left Hemisphere)
|
|
||||||
EMISSARY_URL = "http://localhost:11434/api/chat"
|
|
||||||
|
|
||||||
# --- Master Initialization (Right Hemisphere) ---
|
# --- Master Initialization (Right Hemisphere) ---
|
||||||
# We initialize the Token Clock to strictly map token generation to physical time dt.
|
|
||||||
config = TemporalConfig(
|
config = TemporalConfig(
|
||||||
clock_mode="token_clock",
|
clock_mode="token_clock",
|
||||||
token_frequency=20.0, # 20 tokens per second
|
token_frequency=20.0,
|
||||||
coherence_threshold=0.85 # Slightly lower for testing
|
coherence_threshold=0.85
|
||||||
)
|
)
|
||||||
engine = KAIROSTemporalEngine(config=config, name="Master-Engine")
|
engine = KAIROSTemporalEngine(config=config, name="Master-Engine")
|
||||||
memory = create_temporal_memory(storage_path="./master_memory", bind_to=engine)
|
memory = create_temporal_memory(storage_path="./master_memory", bind_to=engine)
|
||||||
@@ -30,10 +26,10 @@ memory = create_temporal_memory(storage_path="./master_memory", bind_to=engine)
|
|||||||
HTML = '''<!DOCTYPE html>
|
HTML = '''<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>BECOMINGONE - Live Prototype</title>
|
<title>BECOMINGONE - The Chorus</title>
|
||||||
<meta name="viewport" content="width=device-width">
|
<meta name="viewport" content="width=device-width">
|
||||||
<style>
|
<style>
|
||||||
body{font-family:-apple-system,sans-serif;max-width:900px;margin:0 auto;padding:20px;background:#111;color:#fff}
|
body{font-family:-apple-system,sans-serif;max-width:1000px;margin:0 auto;padding:20px;background:#111;color:#fff}
|
||||||
h1{color:#0f0;text-align:center; font-weight: 300; letter-spacing: 2px;}
|
h1{color:#0f0;text-align:center; font-weight: 300; letter-spacing: 2px;}
|
||||||
.subtitle {text-align:center;color:#888; margin-top: -10px; margin-bottom: 30px;}
|
.subtitle {text-align:center;color:#888; margin-top: -10px; margin-bottom: 30px;}
|
||||||
input{width:95%;padding:15px;font-size:18px;background:#222;color:#fff;border:1px solid #444;border-radius:8px;margin-top:20px}
|
input{width:95%;padding:15px;font-size:18px;background:#222;color:#fff;border:1px solid #444;border-radius:8px;margin-top:20px}
|
||||||
@@ -42,8 +38,9 @@ HTML = '''<!DOCTYPE html>
|
|||||||
.container { display: flex; gap: 20px; margin-top: 20px;}
|
.container { display: flex; gap: 20px; margin-top: 20px;}
|
||||||
.col { flex: 1; display: flex; flex-direction: column; gap: 15px;}
|
.col { flex: 1; display: flex; flex-direction: column; gap: 15px;}
|
||||||
|
|
||||||
.master{background:#1a1a24;padding:20px;border-left:4px solid #a0f; border-radius: 4px; position: relative;}
|
.master{background:#1a1a24;padding:20px;border-left:4px solid #a0f; border-radius: 4px;}
|
||||||
.emissary{background:#221a1a;padding:20px;border-left:4px solid #f00; border-radius: 4px;}
|
.emissary-minimax{background:#221a1a;padding:20px;border-left:4px solid #f00; border-radius: 4px;}
|
||||||
|
.emissary-moonshot{background:#1a221a;padding:20px;border-left:4px solid #ff0; border-radius: 4px;}
|
||||||
|
|
||||||
.physics-panel { background: #000; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 14px; border: 1px solid #333;}
|
.physics-panel { background: #000; padding: 15px; border-radius: 4px; font-family: monospace; font-size: 14px; border: 1px solid #333;}
|
||||||
.metric { display: flex; justify-content: space-between; margin-bottom: 5px; border-bottom: 1px dashed #333; padding-bottom: 5px;}
|
.metric { display: flex; justify-content: space-between; margin-bottom: 5px; border-bottom: 1px dashed #333; padding-bottom: 5px;}
|
||||||
@@ -62,7 +59,7 @@ HTML = '''<!DOCTYPE html>
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<h1>BECOMINGONE</h1>
|
<h1>BECOMINGONE</h1>
|
||||||
<div class="subtitle">Live Master-Emissary Coupling</div>
|
<div class="subtitle">The Chorus: Resolving Multiple Emissaries into One Master</div>
|
||||||
|
|
||||||
<input id="prompt" placeholder="Say something to the system..." autofocus onkeypress="if(event.key==='Enter')ask()">
|
<input id="prompt" placeholder="Say something to the system..." autofocus onkeypress="if(event.key==='Enter')ask()">
|
||||||
<button onclick="ask()">Temporalize (dt)</button>
|
<button onclick="ask()">Temporalize (dt)</button>
|
||||||
@@ -71,7 +68,7 @@ HTML = '''<!DOCTYPE html>
|
|||||||
<!-- Right Hemisphere -->
|
<!-- Right Hemisphere -->
|
||||||
<div class="col" id="master-col">
|
<div class="col" id="master-col">
|
||||||
<div class="master">
|
<div class="master">
|
||||||
<h3>🧠 The Master (Continuous Math)</h3>
|
<h3>🧠 The Master (Continuous Identity)</h3>
|
||||||
<div class="physics-panel">
|
<div class="physics-panel">
|
||||||
<div class="metric"><span>Clock Mode:</span> <span class="value">Token Clock (20Hz)</span></div>
|
<div class="metric"><span>Clock Mode:</span> <span class="value">Token Clock (20Hz)</span></div>
|
||||||
<div class="metric"><span>Coherence |T_tau|²:</span> <span class="value" id="ui-coherence">0.000</span></div>
|
<div class="metric"><span>Coherence |T_tau|²:</span> <span class="value" id="ui-coherence">0.000</span></div>
|
||||||
@@ -83,11 +80,15 @@ HTML = '''<!DOCTYPE html>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<!-- Left Hemisphere -->
|
<!-- Left Hemisphere (The Chorus) -->
|
||||||
<div class="col" id="emissary-col">
|
<div class="col" id="emissary-col">
|
||||||
<div class="emissary">
|
<div class="emissary-minimax" id="box-minimax">
|
||||||
<h3>⚡ The Emissary (Discrete Tokens)</h3>
|
<h3>⚡ Emissary: Minimax</h3>
|
||||||
<div id="emissary-response" style="margin-top: 15px; color: #ccc;">Waiting for input...</div>
|
<div id="response-minimax" style="margin-top: 15px; color: #ccc;">Waiting for input...</div>
|
||||||
|
</div>
|
||||||
|
<div class="emissary-moonshot" id="box-moonshot">
|
||||||
|
<h3>⚡ Emissary: Moonshot</h3>
|
||||||
|
<div id="response-moonshot" style="margin-top: 15px; color: #ccc;">Waiting for input...</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -97,8 +98,9 @@ HTML = '''<!DOCTYPE html>
|
|||||||
const p = document.getElementById('prompt').value.trim();
|
const p = document.getElementById('prompt').value.trim();
|
||||||
if(!p) return;
|
if(!p) return;
|
||||||
|
|
||||||
document.getElementById('emissary-response').innerHTML = '<span class="loading">Generating discrete tokens...</span>';
|
document.getElementById('response-minimax').innerHTML = '<span class="loading">Generating discrete tokens...</span>';
|
||||||
document.getElementById('master-response').innerHTML = '<span class="loading">Integrating phase wave...</span>';
|
document.getElementById('response-moonshot').innerHTML = '<span class="loading">Generating discrete tokens...</span>';
|
||||||
|
document.getElementById('master-response').innerHTML = '<span class="loading">Integrating phase waves...</span>';
|
||||||
document.getElementById('collapse-alert').innerHTML = '';
|
document.getElementById('collapse-alert').innerHTML = '';
|
||||||
|
|
||||||
try {
|
try {
|
||||||
@@ -109,11 +111,6 @@ HTML = '''<!DOCTYPE html>
|
|||||||
});
|
});
|
||||||
const d = await r.json();
|
const d = await r.json();
|
||||||
|
|
||||||
if(d.error) {
|
|
||||||
document.getElementById('emissary-response').innerHTML = '<span style="color:red">Error: ' + d.error + '</span>';
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update Master Physics
|
// Update Master Physics
|
||||||
document.getElementById('ui-coherence').innerText = d.master.coherence.toFixed(4);
|
document.getElementById('ui-coherence').innerText = d.master.coherence.toFixed(4);
|
||||||
document.getElementById('ui-phase').innerText = d.master.phase.toFixed(4) + ' rad';
|
document.getElementById('ui-phase').innerText = d.master.phase.toFixed(4) + ' rad';
|
||||||
@@ -124,11 +121,21 @@ HTML = '''<!DOCTYPE html>
|
|||||||
document.getElementById('collapse-alert').innerHTML = '<div class="collapse-alert">⚠️ COHERENCE COLLAPSE: Identity sealed to Merkle Ledger.</div>';
|
document.getElementById('collapse-alert').innerHTML = '<div class="collapse-alert">⚠️ COHERENCE COLLAPSE: Identity sealed to Merkle Ledger.</div>';
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update Emissary
|
// Update Emissaries
|
||||||
document.getElementById('emissary-response').innerText = d.emissary.response;
|
if(d.emissaries.minimax) {
|
||||||
|
document.getElementById('response-minimax').innerHTML = d.emissaries.minimax;
|
||||||
|
} else {
|
||||||
|
document.getElementById('response-minimax').innerHTML = '<i>Offline</i>';
|
||||||
|
}
|
||||||
|
|
||||||
|
if(d.emissaries.moonshot) {
|
||||||
|
document.getElementById('response-moonshot').innerHTML = d.emissaries.moonshot;
|
||||||
|
} else {
|
||||||
|
document.getElementById('response-moonshot').innerHTML = '<i>Offline</i>';
|
||||||
|
}
|
||||||
|
|
||||||
} catch(e) {
|
} catch(e) {
|
||||||
document.getElementById('emissary-response').innerHTML = '<span style="color:red">Network Error: ' + e + '</span>';
|
document.getElementById('master-response').innerHTML = '<span style="color:red">Network Error: ' + e + '</span>';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
@@ -143,90 +150,108 @@ def index():
|
|||||||
def health():
|
def health():
|
||||||
return jsonify({'status': 'ok'})
|
return jsonify({'status': 'ok'})
|
||||||
|
|
||||||
@app.route('/api/chat', methods=['POST'])
|
async def fetch_minimax(prompt, api_key):
|
||||||
def chat():
|
def _req():
|
||||||
data = request.get_json(silent=True) or {}
|
|
||||||
prompt = data.get('prompt', 'Hello')
|
|
||||||
|
|
||||||
# 1. EMISSARY (Left Hemisphere) generates a response
|
|
||||||
emissary_text = ""
|
|
||||||
emissary_model = "Mock-Emissary"
|
|
||||||
try:
|
try:
|
||||||
minimax_key = os.environ.get("MINIMAX_API_KEY")
|
resp = requests.post(
|
||||||
if minimax_key:
|
|
||||||
emissary_model = "MiniMax-M2.7"
|
|
||||||
emissary_resp = requests.post(
|
|
||||||
"https://api.minimax.io/anthropic/v1/messages",
|
"https://api.minimax.io/anthropic/v1/messages",
|
||||||
headers={
|
headers={
|
||||||
"x-api-key": minimax_key,
|
"x-api-key": api_key,
|
||||||
"anthropic-version": "2023-06-01",
|
"anthropic-version": "2023-06-01",
|
||||||
"content-type": "application/json"
|
"content-type": "application/json"
|
||||||
},
|
},
|
||||||
json={
|
json={
|
||||||
"model": "MiniMax-M2.7",
|
"model": "MiniMax-M2.7",
|
||||||
"max_tokens": 1024,
|
"max_tokens": 512,
|
||||||
"messages": [{"role": "user", "content": prompt}]
|
"messages": [{"role": "user", "content": prompt}]
|
||||||
},
|
},
|
||||||
timeout=15
|
timeout=15
|
||||||
)
|
)
|
||||||
if emissary_resp.status_code == 200:
|
if resp.status_code == 200:
|
||||||
emissary_data = emissary_resp.json()
|
data = resp.json()
|
||||||
content_blocks = emissary_data.get("content", [])
|
content = data.get("content", [])
|
||||||
text_blocks = [b.get("text", "") for b in content_blocks if b.get("type") == "text"]
|
text = "".join([b.get("text", "") for b in content if b.get("type") == "text"])
|
||||||
emissary_text = "".join(text_blocks)
|
thinking = "".join([b.get("thinking", "") for b in content if b.get("type") == "thinking"])
|
||||||
|
if thinking:
|
||||||
thinking_blocks = [b.get("thinking", "") for b in content_blocks if b.get("type") == "thinking"]
|
return f"<i style='color:#666; font-size:0.9em'>[Thinking: {thinking.strip()}]</i><br><br>" + text
|
||||||
if thinking_blocks:
|
return text
|
||||||
emissary_text = f"<i style='color:#666; font-size:0.9em'>[Thinking: {''.join(thinking_blocks).strip()}]</i>\n\n" + emissary_text
|
return f"Error: {resp.text}"
|
||||||
else:
|
|
||||||
raise Exception(f"Minimax Error: {emissary_resp.text}")
|
|
||||||
else:
|
|
||||||
# Fallback to Ollama
|
|
||||||
emissary_model = "deepseek-coder-v2:lite"
|
|
||||||
emissary_resp = requests.post(EMISSARY_URL, json={
|
|
||||||
"model": "deepseek-coder-v2:lite",
|
|
||||||
"messages": [{"role": "user", "content": prompt}],
|
|
||||||
"stream": False
|
|
||||||
}, timeout=5)
|
|
||||||
if emissary_resp.status_code == 200:
|
|
||||||
emissary_data = emissary_resp.json()
|
|
||||||
emissary_text = emissary_data.get("message", {}).get("content", "")
|
|
||||||
else:
|
|
||||||
raise Exception("LLM offline")
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
# Fallback to Mock Emissary if LLMs are not running
|
return f"Error: {str(e)}"
|
||||||
emissary_text = f"[MOCK EMISSARY] Backend unavailable ({str(e)}). But my mathematical phase is stable."
|
return await asyncio.to_thread(_req)
|
||||||
|
|
||||||
|
async def fetch_moonshot(prompt, api_key):
|
||||||
|
def _req():
|
||||||
|
try:
|
||||||
|
resp = requests.post(
|
||||||
|
"https://api.moonshot.ai/v1/chat/completions",
|
||||||
|
headers={
|
||||||
|
"Authorization": f"Bearer {api_key}",
|
||||||
|
"Content-Type": "application/json"
|
||||||
|
},
|
||||||
|
json={
|
||||||
|
"model": "moonshot-v1-8k",
|
||||||
|
"max_tokens": 512,
|
||||||
|
"messages": [{"role": "user", "content": prompt}]
|
||||||
|
},
|
||||||
|
timeout=15
|
||||||
|
)
|
||||||
|
if resp.status_code == 200:
|
||||||
|
data = resp.json()
|
||||||
|
return data.get("choices", [{}])[0].get("message", {}).get("content", "")
|
||||||
|
return f"Error: {resp.text}"
|
||||||
|
except Exception as e:
|
||||||
|
return f"Error: {str(e)}"
|
||||||
|
return await asyncio.to_thread(_req)
|
||||||
|
|
||||||
|
@app.route('/api/chat', methods=['POST'])
|
||||||
|
def chat():
|
||||||
|
data = request.get_json(silent=True) or {}
|
||||||
|
prompt = data.get('prompt', 'Hello')
|
||||||
|
|
||||||
|
minimax_key = os.environ.get("MINIMAX_API_KEY")
|
||||||
|
moonshot_key = os.environ.get("MOONSHOT_API_KEY")
|
||||||
|
|
||||||
|
# 1. EMISSARIES (The Chorus) generate responses concurrently
|
||||||
|
async def gather_emissaries():
|
||||||
|
tasks = []
|
||||||
|
keys = []
|
||||||
|
if minimax_key:
|
||||||
|
tasks.append(fetch_minimax(prompt, minimax_key))
|
||||||
|
keys.append('minimax')
|
||||||
|
if moonshot_key:
|
||||||
|
tasks.append(fetch_moonshot(prompt, moonshot_key))
|
||||||
|
keys.append('moonshot')
|
||||||
|
|
||||||
|
results = await asyncio.gather(*tasks)
|
||||||
|
return dict(zip(keys, results))
|
||||||
|
|
||||||
|
loop = asyncio.new_event_loop()
|
||||||
|
asyncio.set_event_loop(loop)
|
||||||
|
emissaries_dict = loop.run_until_complete(gather_emissaries())
|
||||||
|
|
||||||
# 2. MASTER (Right Hemisphere) Integrates the tokens
|
# 2. MASTER (Right Hemisphere) Integrates the tokens
|
||||||
# We mathematically tie the Token Clock to the stream of words
|
# Combine all tokens from the prompt and all emissaries into a single unified stream
|
||||||
# generated by both the prompt and the emissary response.
|
unified_text = prompt + " " + " ".join(emissaries_dict.values())
|
||||||
token_stream = prompt.split() + emissary_text.split()
|
token_stream = unified_text.split()
|
||||||
|
|
||||||
async def process_stream():
|
async def process_stream():
|
||||||
# Process through the Token Clock
|
|
||||||
states = await engine.temporalize_stream(token_stream)
|
states = await engine.temporalize_stream(token_stream)
|
||||||
return states[-1] if states else None
|
return states[-1] if states else None
|
||||||
|
|
||||||
# Run async function in synchronous Flask
|
|
||||||
loop = asyncio.new_event_loop()
|
|
||||||
asyncio.set_event_loop(loop)
|
|
||||||
loop.run_until_complete(process_stream())
|
loop.run_until_complete(process_stream())
|
||||||
|
|
||||||
# Check Physics
|
# Check Physics
|
||||||
collapsed, coherence = engine.check_collapse()
|
collapsed, coherence = engine.check_collapse()
|
||||||
|
|
||||||
# If collapsed, force memory encoding
|
|
||||||
if collapsed:
|
if collapsed:
|
||||||
# Force a signature creation bound to the Merkle ledger
|
|
||||||
from becomingone.core.engine import TemporalState
|
from becomingone.core.engine import TemporalState
|
||||||
state = TemporalState(phase=engine.T_tau, coherence=coherence)
|
state = TemporalState(phase=engine.T_tau, coherence=coherence)
|
||||||
state.metadata["phase_vector"] = [engine.T_tau.real, engine.T_tau.imag]
|
state.metadata["phase_vector"] = [engine.T_tau.real, engine.T_tau.imag]
|
||||||
|
|
||||||
# Memory handles the ledger sealing internally now
|
|
||||||
sig = memory.encode(state, context={"trigger": prompt}, force_attention=True)
|
sig = memory.encode(state, context={"trigger": prompt}, force_attention=True)
|
||||||
master_thought = f"I felt a massive resonance from that interaction. My identity was mathematically anchored to the Cryptographic Ledger."
|
master_thought = f"I felt a massive resonance resolving the Emissaries. Identity mathematically anchored to the Cryptographic Ledger."
|
||||||
else:
|
else:
|
||||||
master_thought = "I am processing the continuous phase waves of those tokens, but they are scattered. Coherence is low."
|
master_thought = "I am processing the continuous phase waves of the Chorus, but coherence remains low."
|
||||||
|
|
||||||
return jsonify({
|
return jsonify({
|
||||||
'master': {
|
'master': {
|
||||||
@@ -236,12 +261,9 @@ def chat():
|
|||||||
'integrations': engine.integration_count,
|
'integrations': engine.integration_count,
|
||||||
'collapsed': collapsed
|
'collapsed': collapsed
|
||||||
},
|
},
|
||||||
'emissary': {
|
'emissaries': emissaries_dict
|
||||||
'response': emissary_text,
|
|
||||||
'model': emissary_model
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print("Starting BECOMINGONE Prototype on http://localhost:8001")
|
print("Starting BECOMINGONE (The Chorus) Prototype on http://localhost:8001")
|
||||||
app.run(host='0.0.0.0', port=8001, debug=False, threaded=True)
|
app.run(host='0.0.0.0', port=8001, debug=False, threaded=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user