qac-l-cloud / src /llm.py
IHat0's picture
Upload folder using huggingface_hub
2db2be1 verified
Raw
History Blame Contribute Delete
6.66 kB
"""
llm.py — the LLM slot (Task 2 wiring point).
This is where the Qwen2.5-3B-Instruct GGUF model lives. The module is written
now so the rest of the pipeline has a clean, lazy single point of integration.
Until the model is wired in, `is_available()` returns False and the pipeline
falls back to the heuristic parser in `spec.interpret_query`.
"""
from __future__ import annotations
import os
import logging
from typing import Optional
from .spec import QuantumSpec, interpret_query, parse_dsl
log = logging.getLogger(__name__)
# ── Configuration ────────────────────────────────────────────────────────────
MODEL_REPO = os.environ.get(
"QAC_L_MODEL_REPO",
"YOUR_USERNAME/qwen3b-quantum-compiler", # Replace with your repo
)
MODEL_FILE = os.environ.get(
"QAC_L_MODEL_FILE",
"qwen3b_quantum.gguf",
)
N_CTX = int(os.environ.get("QAC_L_N_CTX", "4096"))
N_THREADS = int(os.environ.get("QAC_L_N_THREADS", "2"))
_LLM = None
_LOAD_ATTEMPTED = False
# ── Loading ──────────────────────────────────────────────────────────────────
def _load():
"""Lazy-load the GGUF model. Returns the llama-cpp instance or None."""
global _LLM, _LOAD_ATTEMPTED
if _LOAD_ATTEMPTED:
return _LLM
_LOAD_ATTEMPTED = True
try:
from huggingface_hub import hf_hub_download
from llama_cpp import Llama
path = hf_hub_download(repo_id=MODEL_REPO, filename=MODEL_FILE)
log.info("Loading LLM %s/%s (ctx=%d, threads=%d)",
MODEL_REPO, MODEL_FILE, N_CTX, N_THREADS)
_LLM = Llama(
model_path=path,
n_ctx=N_CTX,
n_threads=N_THREADS,
verbose=False,
)
log.info("LLM loaded.")
except Exception as exc:
log.warning("LLM unavailable, falling back to heuristic parser: %s", exc)
_LLM = None
return _LLM
def is_available() -> bool:
"""True iff the GGUF model can be loaded in this environment."""
return _load() is not None
# ── Generation ───────────────────────────────────────────────────────────────
_COMPILE_SYS = (
"You are a quantum compiler. Translate the user's natural-language request "
"into exactly one strict DSL line. Valid formats:\n"
" [ACTION: RANDOM] [QUBITS: n] # n in 1..5\n"
" [ACTION: VQE] [DISTANCE: r] # r in 0.5..2.5 (Å)\n"
" [ACTION: BELL] [PAIRS: k] # k in 1..4\n"
" [ACTION: GROVER] [ITEMS: m] # m in 2..16\n"
" [ACTION: QAOA] [NODES: v] [DEPTH: p]# v in 2..8, p in 1..3\n"
"Output ONLY the DSL line, nothing else."
)
_REPORT_SYS = (
"You are a senior quantum physicist. Given raw measurement counts and "
"computed statistics, explain the result in clear, scientifically accurate "
"English. Treat probabilities below 5% as expected quantum noise. Be concise."
)
def _chat(llm, system: str, user: str, *, max_tokens: int, temperature: float) -> str:
resp = llm.create_chat_completion(
messages=[{"role": "system", "content": system},
{"role": "user", "content": user}],
max_tokens=max_tokens,
temperature=temperature,
)
return resp["choices"][0]["message"]["content"].strip()
# ── Public API ───────────────────────────────────────────────────────────────
def compile_query(query: str) -> Optional[QuantumSpec]:
"""English → QuantumSpec via the LLM, or heuristic fallback."""
llm = _load()
if llm is not None:
raw = _chat(llm, _COMPILE_SYS, query, max_tokens=64, temperature=0.1)
spec = parse_dsl(raw)
if spec is not None:
return spec
log.warning("LLM produced unparseable DSL (%r); trying heuristic.", raw)
return interpret_query(query)
def explain_results(query: str, receipt_text: str, receipt_data: dict) -> str:
"""Results → natural-language explanation via the LLM or template fallback."""
llm = _load()
if llm is None:
return _template_explanation(query, receipt_data)
user = f"Original query: {query}\n\nReceipt:\n{receipt_text}"
return _chat(llm, _REPORT_SYS, user, max_tokens=256, temperature=0.7)
def _template_explanation(query: str, data: dict) -> str:
"""Plain-English summary derived from statistics — no LLM needed."""
action = data.get("action", "?")
s = data.get("statistics", {})
if action == "RANDOM":
return (f"Measured {data['qubits']} qubits in superposition across "
f"{data['shots']} shots. The distribution had "
f"{s.get('entropy_bits', 0):.2f} bits of entropy "
f"(max {s.get('max_entropy_bits', 0):.2f}), i.e. "
f"{s.get('uniformity', 0):.0%} uniform — these are genuinely "
f"random bits from quantum measurement.")
if action == "BELL":
return (f"Created {s.get('entangled_pairs', 1)} Bell pair(s). "
f"{s.get('correlation', 0):.2%} of shots produced perfectly "
f"correlated outcomes between paired qubits "
f"(ideal: 100%), confirming entanglement.")
if action == "GROVER":
return (f"Grover search found the marked state |{s.get('target_state')}⟩ "
f"with {s.get('success_probability', 0):.0%} probability after "
f"{data['extra'].get('iterations', '?')} iterations — a "
f"quadratic speedup over the {s.get('classical_baseline', 0):.0%} "
f"classical baseline.")
if action == "QAOA":
return (f"QAOA (p={s.get('depth_p', 1)}) found a MaxCut of "
f"{s.get('best_cut', 0)}/{s.get('max_possible_cut', 0)} on the "
f"ring graph, approximation ratio "
f"{s.get('approximation_ratio', 0):.2f}.")
if action == "VQE":
return (f"VQE converged to a ground-state energy of "
f"{s.get('vqe_converged_energy_ha', 0)} Ha for H₂ at "
f"{data['extra'].get('bond_distance_angstrom', '?')} Å "
f"(analytical reference {s.get('analytical_energy_ha', 0)} Ha).")
return "No explanation available for this action."