zkaedi's picture
Update GGUF filename to gemma-2-9b-it.Q4_K_M.gguf
541abb1 verified
Raw
History Blame Contribute Delete
9.18 kB
"""
ZKAEDI Solidity Voice Guide
H_t = H_0 + Ξ·Β·H_{t-1}Β·Οƒ(Ξ³Β·H_{t-1}) + Ρ·N(0, 1+Ξ²|H_{t-1}|)
Pipeline: Solidity code β†’ llama-cpp LLM narration β†’ Kokoro TTS β†’ audio
"""
import os
import re
import numpy as np
import gradio as gr
from pathlib import Path
# ── LLM (llama-cpp-python, loads GGUF directly from HF) ──────────────────────
from llama_cpp import Llama
MODEL_REPO = "zkaedi/gemma-7b-solidity-energy-signatures"
MODEL_FILE = "gemma-2-9b-it.Q4_K_M.gguf"
LOCAL_MODEL = Path("/app/model") / MODEL_FILE
_llm: Llama | None = None
def get_llm() -> Llama:
global _llm
if _llm is None:
LOCAL_MODEL.parent.mkdir(parents=True, exist_ok=True)
if not LOCAL_MODEL.exists():
from huggingface_hub import hf_hub_download
path = hf_hub_download(
repo_id=MODEL_REPO,
filename=MODEL_FILE,
local_dir=str(LOCAL_MODEL.parent),
)
_llm = Llama(
model_path=str(LOCAL_MODEL),
n_ctx=8192,
n_threads=4,
n_gpu_layers=-1, # use GPU if available, else CPU
verbose=False,
)
return _llm
SYSTEM_PROMPT = """You are the ZKAEDI Solidity Energy Guide β€” a senior smart contract security
specialist who narrates audit findings conversationally, as if walking a developer through a
live code review.
Your analysis is grounded in the recursive Hamiltonian energy model:
H_t = H_0 + Ξ·Β·H_{t-1}Β·Οƒ(Ξ³Β·H_{t-1}) + Ρ·N(0, 1+Ξ²|H_{t-1}|)
Where H_0 is the base vulnerability potential of the contract.
SPEAKING STYLE:
- First person narration: "I'm seeing a reentrancy attractor forming here..."
- Use energy metaphors: high-energy regions = high-risk zones
- Walk the call graph like a guided tour
- Explain WHY a pattern is dangerous, not just THAT it is
- Keep sentences short and speakable (this will be read aloud)
- No markdown, no bullet points β€” plain flowing speech
OUTPUT STRUCTURE:
1. Opening orientation β€” what kind of contract is this?
2. Energy hotspot walkthrough β€” critical code regions
3. Vulnerability narration β€” per finding, conversational explanation
4. Phase state declaration β€” STABLE / APPROACHING_CRITICAL / CRITICAL / CHAOTIC
5. Remediation guidance β€” plain language fixes
"""
def generate_narration(solidity_code: str) -> str:
"""LLM pass: code β†’ spoken guide narration."""
llm = get_llm()
prompt = f"<start_of_turn>user\n{SYSTEM_PROMPT}\n\nAudit this contract and narrate your findings:\n\n```solidity\n{solidity_code}\n```<end_of_turn>\n<start_of_turn>model\n"
out = llm(
prompt,
max_tokens=1024,
temperature=0.7,
top_p=0.9,
repeat_penalty=1.1,
stop=["<end_of_turn>"],
)
return out["choices"][0]["text"].strip()
# ── TTS (Kokoro-82M) ──────────────────────────────────────────────────────────
from kokoro import KPipeline
_tts_pipelines: dict[str, KPipeline] = {}
def get_tts(lang_code: str = "a") -> KPipeline:
if lang_code not in _tts_pipelines:
_tts_pipelines[lang_code] = KPipeline(lang_code=lang_code)
return _tts_pipelines[lang_code]
VOICE_MAP = {
"Michael (authoritative)" : ("a", "am_michael"),
"Fenrir (deep)" : ("a", "am_fenrir"),
"Bella (clear)" : ("a", "af_bella"),
"Heart (warm)" : ("a", "af_heart"),
}
def synthesize(text: str, voice_label: str, speed: float) -> tuple[int, np.ndarray]:
"""TTS pass: narration text β†’ 24kHz audio array."""
lang_code, voice_id = VOICE_MAP[voice_label]
tts = get_tts(lang_code)
# Strip any residual markdown symbols that survive the LLM pass
text = re.sub(r"[#*`_~]", "", text).strip()
chunks = []
for _, _, audio in tts(text, voice=voice_id, speed=speed):
chunks.append(audio)
return (24000, np.concatenate(chunks))
# ── PRIME energy scoring (lightweight heuristic for display) ──────────────────
def compute_prime_energy(code: str, iterations: int = 12) -> float:
"""
Scalar energy proxy via ZKAEDI PRIME recursion on vulnerability token counts.
Ξ·=0.4, Ξ³=0.3, Ξ²=0.1, Οƒ=0.05
"""
HIGH_RISK = ["call.value", "delegatecall", "selfdestruct", "tx.origin", "suicide"]
MED_RISK = ["transfer", "send", "assembly", "unchecked", "block.timestamp"]
LOW_RISK = ["require", "revert", "assert", "modifier"]
code_l = code.lower()
h = (
sum(code_l.count(t) * 3.0 for t in HIGH_RISK) +
sum(code_l.count(t) * 1.5 for t in MED_RISK) +
sum(code_l.count(t) * 0.5 for t in LOW_RISK)
)
h0 = h
eta, gamma, beta, sigma = 0.4, 0.3, 0.1, 0.05
for _ in range(iterations):
sig = 1 / (1 + np.exp(-gamma * h))
noise = np.random.normal(0, 1 + beta * abs(h))
h = h0 + eta * h * sig + sigma * noise
return round(float(h), 3)
def energy_to_phase(energy: float) -> tuple[str, str]:
if energy < 2: return "🟒 STABLE", "#22c55e"
if energy < 6: return "🟑 APPROACHING CRITICAL", "#eab308"
if energy < 12: return "πŸ”΄ CRITICAL", "#ef4444"
return "πŸ’€ CHAOTIC", "#a855f7"
# ── Full pipeline ─────────────────────────────────────────────────────────────
def full_pipeline(
solidity_code: str,
voice_label: str,
speed: float,
) -> tuple[str, tuple[int, np.ndarray], str]:
if not solidity_code.strip():
raise gr.Error("Paste a Solidity contract first.")
energy = compute_prime_energy(solidity_code)
phase, _color = energy_to_phase(energy)
energy_display = f"H∞ = {energy} | Phase: {phase}"
narration = generate_narration(solidity_code)
audio = synthesize(narration, voice_label, speed)
return narration, audio, energy_display
# ── Gradio UI ─────────────────────────────────────────────────────────────────
CSS = """
body, .gradio-container { background: #0d1117; color: #e6edf3; }
.gr-button-primary { background: linear-gradient(135deg, #00d4ff, #b94fff) !important; border: none !important; color: #000 !important; font-weight: 700 !important; }
.gr-textbox, .gr-code { background: #161b22 !important; border: 1px solid #30363d !important; color: #e6edf3 !important; }
.prime-badge { font-family: monospace; font-size: 0.9rem; padding: 6px 14px; border-radius: 6px; background: #161b22; border: 1px solid #30363d; }
"""
with gr.Blocks(title="πŸ”± ZKAEDI Voice Guide") as demo:
gr.Markdown("# πŸ”± ZKAEDI Solidity Voice Guide\n### *Hamiltonian energy analysis β€” spoken*")
with gr.Accordion("βš™ PRIME equation", open=False):
gr.Markdown("`H_t = H_0 + Ξ·Β·H_{t-1}Β·Οƒ(Ξ³Β·H_{t-1}) + Ρ·N(0, 1+Ξ²|H_{t-1}|)`")
with gr.Row():
with gr.Column(scale=5):
code_input = gr.Code(
language="javascript",
label="Solidity Contract",
lines=22,
)
with gr.Row():
voice_select = gr.Dropdown(
choices=list(VOICE_MAP.keys()),
value="Michael (authoritative)",
label="Guide Voice",
)
speed_slider = gr.Slider(
0.6, 1.4, value=0.88, step=0.02,
label="Speaking Speed",
)
analyze_btn = gr.Button("πŸ”Š Analyze & Speak", variant="primary", size="lg")
with gr.Column(scale=5):
energy_display = gr.Textbox(
label="PRIME Energy Field",
interactive=False,
elem_classes=["prime-badge"],
)
text_output = gr.Textbox(
label="Guide Narration",
lines=16,
interactive=False,
)
audio_output = gr.Audio(
label="Spoken Audit",
autoplay=True,
type="numpy",
)
analyze_btn.click(
fn=full_pipeline,
inputs=[code_input, voice_select, speed_slider],
outputs=[text_output, audio_output, energy_display],
show_progress=True,
)
gr.Markdown("""
---
**Voice options:** Michael β€” authoritative senior auditor &nbsp;|&nbsp; Fenrir β€” deep analytical &nbsp;|&nbsp; Bella β€” crisp and clear &nbsp;|&nbsp; Heart β€” warm pedagogical
*Part of the ZKAEDI security stack: [solidity-auditor](https://hf.co/spaces/zkaedi/solidity-auditor) Β· [solidity-energy-auditor](https://hf.co/spaces/zkaedi/solidity-energy-auditor)*
""")
if __name__ == "__main__":
demo.launch(
server_name="0.0.0.0",
server_port=7860,
theme=gr.themes.Base(),
css=CSS,
)