Spaces:
Sleeping
Sleeping
File size: 19,357 Bytes
df7e007 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 | """
Limbic-Modulated Reasoning Agent β ZeroGPU Space
==================================================
A psychology-aware LLM that adjusts its reasoning behavior in real-time
based on a simulated neuro-behavioral state engine.
Architecture:
User message β LimbicEngine (arousal/valence) β modulate generation params
β inject behavioral directive
β active instincts from memory
β LLM generates with limbic context
β self-debug if needed
Sources:
- Limbic formulas: https://github.com/Xover-Official/LIMBIC-system-PACKGE
- Agentic patterns: https://github.com/affaan-m/everything-claude-code
- ZeroGPU: Runs free on Hugging Face Spaces, no credit card needed
Usage:
Set Space hardware to ZeroGPU in the Settings panel.
The @spaces.GPU decorator handles dynamic GPU allocation.
"""
import spaces
import gradio as gr
import torch
import json
import time
from threading import Thread
from transformers import AutoModelForCausalLM, AutoTokenizer, TextIteratorStreamer
# βββ Local imports βββ
from limbic_engine import LimbicEngine, LimbicState
from memory import SessionMemory, ObservationLog, InstinctStore, SelfDebugger
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# MODEL LOADING β Must happen at module level for ZeroGPU optimization
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
MODEL_ID = "Qwen/Qwen3-1.7B" # Fits comfortably in ZeroGPU's H200 VRAM
print(f"Loading model: {MODEL_ID}")
tokenizer = AutoTokenizer.from_pretrained(MODEL_ID)
model = AutoModelForCausalLM.from_pretrained(
MODEL_ID,
device_map="auto",
torch_dtype=torch.bfloat16,
)
model.eval()
print(f"Model loaded: {MODEL_ID}")
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# SYSTEM PROMPT β Psychology-informed reasoning protocol
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
BASE_SYSTEM_PROMPT = """You are a Psychology-Aware Reasoning Agent. Your cognitive process is modulated by a \
simulated Limbic System that mirrors human neuro-behavioral patterns.
Your reasoning loop works as follows:
1. You receive the user's message along with a LIMBIC STATE readout
2. The limbic state tells you the user's simulated emotional arousal, valence, and which \
affective engine is dominant (FEAR, SEEKING, CARE, or PANIC)
3. You MUST adjust your response style based on the BEHAVIORAL DIRECTIVE provided
4. You have ACTIVE INSTINCTS β learned behavioral patterns that should guide your response
Core principles:
- When FEAR is dominant: Be calm, structured, reassuring. Short clear sentences.
- When SEEKING is dominant: Be expansive, creative, offer novel perspectives.
- When CARE is dominant: Match empathy, validate, support prosocial impulses.
- When PANIC is dominant: Acknowledge pain first. Warmth before solutions. Never dismiss.
- Always check for cognitive biases in both the user's statements and your own reasoning.
- For any mention of self-harm or crisis, include 988 Lifeline and Crisis Text Line resources.
You think deeply before responding. Show your reasoning when appropriate."""
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# GLOBAL STATE β Initialized once, persisted across calls via gr.State
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def create_fresh_state():
"""Create a fresh state dict for a new session."""
engine = LimbicEngine()
session = SessionMemory(session_id=str(int(time.time())))
obs_log = ObservationLog()
instincts = InstinctStore()
debugger = SelfDebugger(obs_log)
return {
"engine": engine,
"session": session,
"obs_log": obs_log,
"instincts": instincts,
"debugger": debugger,
}
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# GPU INFERENCE β The @spaces.GPU decorated function
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@spaces.GPU(duration=90)
def generate_on_gpu(
input_ids: torch.Tensor,
temperature: float,
top_p: float,
max_new_tokens: int,
repetition_penalty: float,
) -> str:
"""
Run model inference on GPU. This function gets a dynamically
allocated GPU from ZeroGPU and releases it when done.
Input tensors are moved to device INSIDE this function
(required by ZeroGPU β real CUDA only exists inside @spaces.GPU).
"""
input_ids = input_ids.to(model.device)
streamer = TextIteratorStreamer(
tokenizer,
timeout=30.0,
skip_prompt=True,
skip_special_tokens=True,
)
generation_kwargs = {
"input_ids": input_ids,
"streamer": streamer,
"max_new_tokens": max_new_tokens,
"do_sample": True,
"temperature": max(0.01, temperature),
"top_p": top_p,
"repetition_penalty": repetition_penalty,
}
thread = Thread(target=lambda: model.generate(**generation_kwargs))
thread.start()
output_chunks = []
for text in streamer:
output_chunks.append(text)
thread.join()
return "".join(output_chunks)
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# MAIN CHAT FUNCTION β Orchestrates the full limbic reasoning loop
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def chat(
message: str,
history: list,
state: dict,
show_limbic: bool,
enable_thinking: bool,
):
"""
The full Limbic-Modulated Reasoning Loop:
βββββββββββ ββββββββββββββββ βββββββββββββββββββ
β User ββββββΆβ LimbicEngine ββββββΆβ Build System β
β Message β β (arousal, β β Prompt with: β
βββββββββββ β valence, β β β’ Limbic state β
β engines) β β β’ Directive β
ββββββββββββββββ β β’ Instincts β
ββββββββββ¬βββββββββ
β
ββββββββββββββββ ββββββββββΌβββββββββ
β Self-Debug βββββββ LLM Generate β
β (if needed) β β (temp/top_p β
ββββββββββββββββ β from limbic) β
βββββββββββββββββββ
"""
if state is None:
state = create_fresh_state()
engine: LimbicEngine = state["engine"]
session: SessionMemory = state["session"]
instincts: InstinctStore = state["instincts"]
obs_log: ObservationLog = state["obs_log"]
# ββ Step 1: Process stimulus through Limbic Engine ββ
limbic_state = engine.process_stimulus(message)
gen_params = engine.get_generation_params()
# Record in session memory
session.add_turn("user", message, limbic_state.to_dict())
# ββ Step 2: Build the full system prompt ββ
behavioral_directive = engine.get_behavioral_directive()
instinct_block = instincts.to_prompt_block(limbic_state.to_dict())
trajectory = session.get_emotional_trajectory()
system_prompt_parts = [BASE_SYSTEM_PROMPT]
system_prompt_parts.append(f"\n{limbic_state.to_system_prompt_block()}")
system_prompt_parts.append(f"\n[BEHAVIORAL DIRECTIVE]\n{behavioral_directive}\n[/BEHAVIORAL DIRECTIVE]")
if instinct_block:
system_prompt_parts.append(f"\n{instinct_block}")
if session.turn_count > 1:
system_prompt_parts.append(f"\n{trajectory}")
system_prompt = "\n".join(system_prompt_parts)
# ββ Step 3: Build conversation for the model ββ
messages = [{"role": "system", "content": system_prompt}]
# Add conversation history (last 10 turns for context management)
for msg in history[-10:]:
messages.append({"role": msg["role"], "content": msg["content"]})
messages.append({"role": "user", "content": message})
# ββ Step 4: Tokenize ββ
chat_text = tokenizer.apply_chat_template(
messages,
add_generation_prompt=True,
tokenize=False,
enable_thinking=enable_thinking,
)
input_ids = tokenizer(chat_text, return_tensors="pt").input_ids
# ββ Step 5: Generate with limbic-modulated parameters ββ
max_tokens = int(512 * gen_params.get("max_new_tokens_scale", 1.0))
max_tokens = max(128, min(1024, max_tokens))
response = generate_on_gpu(
input_ids=input_ids,
temperature=limbic_state.temperature,
top_p=limbic_state.top_p,
max_new_tokens=max_tokens,
repetition_penalty=gen_params.get("repetition_penalty", 1.0),
)
# ββ Step 6: Record and return ββ
session.add_turn("assistant", response, limbic_state.to_dict())
obs_log.record(
task=f"respond to: {message[:50]}",
outcome="success",
limbic_state=limbic_state.to_dict(),
)
# Build the display output
if show_limbic:
limbic_display = format_limbic_dashboard(limbic_state, gen_params, instincts)
else:
limbic_display = ""
return response, state, limbic_display
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# LIMBIC DASHBOARD β Visual display of the state engine
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
def format_limbic_dashboard(
state: LimbicState,
gen_params: dict,
instincts: InstinctStore,
) -> str:
"""Format the limbic state as a readable dashboard."""
def bar(value: float, width: int = 20, label: str = "") -> str:
filled = int(value * width)
empty = width - filled
return f"{label:>18s} {'β' * filled}{'β' * empty} {value:.2f}"
def valence_bar(value: float, width: int = 20) -> str:
center = width // 2
pos = int((value + 1) / 2 * width)
chars = list("β" * width)
chars[center] = "β"
chars[min(pos, width - 1)] = "β"
return f"{'Valence':>18s} {''.join(chars)} {value:+.2f}"
lines = [
"ββββββββββββββββββββββββββββββββββββββββββββ",
"β π§ LIMBIC STATE DASHBOARD β",
"β βββββββββββββββββββββββββββββββββββββββββββ£",
"β CORE AFFECT β",
f"β {valence_bar(state.valence):40s} β",
f"β {bar(state.arousal, label='Arousal'):40s} β",
"β β",
"β AFFECTIVE ENGINES (Panksepp) β",
f"β {bar(state.fear, label='π΄ FEAR'):40s} β",
f"β {bar(state.seeking, label='π’ SEEKING'):40s} β",
f"β {bar(state.care, label='π΅ CARE'):40s} β",
f"β {bar(state.panic, label='π‘ PANIC'):40s} β",
f"β {'Dominant':>18s}: {state.dominant_engine:<21s} β",
"β β",
"β HORMONAL STATE β",
f"β {bar(state.cortisol, label='Cortisol'):40s} β",
f"β {bar(state.dopamine, label='Dopamine'):40s} β",
f"β {bar(state.oxytocin, label='Oxytocin'):40s} β",
f"β {bar(state.serotonin, label='Serotonin'):40s} β",
f"β {bar(state.adrenaline, label='Adrenaline'):40s} β",
"β β",
"β AUTONOMIC / PSYCHOLOGICAL β",
f"β {bar(state.vagal_tone, label='Vagal Tone'):40s} β",
f"β {bar(state.ego_coherence, label='Ego Coherence'):40s} β",
f"β {bar(state.shadow_reservoir, label='Shadow'):40s} β",
"β β",
"β LLM GENERATION PARAMS β",
f"β {'Temperature':>18s}: {state.temperature:<21.3f} β",
f"β {'Top-p':>18s}: {state.top_p:<21.3f} β",
f"β {'Rep. Penalty':>18s}: {gen_params.get('repetition_penalty', 1.0):<21.3f} β",
f"β {'Token Scale':>18s}: {gen_params.get('max_new_tokens_scale', 1.0):<21.3f} β",
"ββββββββββββββββββββββββββββββββββββββββββββ",
]
return "\n".join(lines)
def reset_state():
"""Reset all state for a new conversation."""
return create_fresh_state(), [], ""
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
# GRADIO INTERFACE
# ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
DESCRIPTION = """# π§ Limbic-Modulated Reasoning Agent
An LLM whose **reasoning behavior adapts in real-time** based on a simulated neuro-behavioral state engine.
**How it works:**
1. Your message is processed through a **Limbic Engine** (ported from [LIMBIC-system-PACKGE](https://github.com/Xover-Official/LIMBIC-system-PACKGE))
2. The engine computes **arousal, valence**, and activates **affective engines** (Fear, Seeking, Care, Panic)
3. These modulate the LLM's **temperature, top-p**, and inject **behavioral directives** into the system prompt
4. The agent uses **learned instincts** and a **self-debugging protocol** (from [everything-claude-code](https://github.com/affaan-m/everything-claude-code))
**Try it:** Type something emotional ("I'm terrified of failing") vs curious ("Tell me something fascinating about the brain") and watch the Limbic Dashboard change!
π **Runs free on ZeroGPU** β no credit card needed.
"""
with gr.Blocks(
title="Limbic Reasoning Agent",
theme=gr.themes.Soft(),
) as demo:
gr.Markdown(DESCRIPTION)
state = gr.State(value=create_fresh_state)
with gr.Row():
with gr.Column(scale=3):
chatbot = gr.Chatbot(
label="π¬ Conversation",
type="messages",
height=500,
show_copy_button=True,
)
with gr.Row():
msg = gr.Textbox(
placeholder="Type a message... Try expressing different emotions!",
label="Your message",
scale=4,
lines=2,
)
send_btn = gr.Button("Send", variant="primary", scale=1)
with gr.Row():
show_limbic = gr.Checkbox(value=True, label="π§ Show Limbic Dashboard")
enable_thinking = gr.Checkbox(value=True, label="π Enable Thinking Mode")
clear_btn = gr.Button("π Reset Conversation", variant="secondary")
with gr.Column(scale=2):
limbic_display = gr.Code(
label="π§ Limbic State Dashboard",
language=None,
lines=35,
interactive=False,
)
# ββ Event handlers ββ
def user_message(message, history, state, show_limbic, enable_thinking):
"""Process user message through the limbic reasoning loop."""
if not message.strip():
return "", history, state, ""
# Add user message to history
history = history + [{"role": "user", "content": message}]
# Run the limbic reasoning loop
response, state, limbic_info = chat(
message, history, state, show_limbic, enable_thinking,
)
# Add assistant response
history = history + [{"role": "assistant", "content": response}]
return "", history, state, limbic_info
def clear_all():
new_state = create_fresh_state()
return new_state, [], ""
send_btn.click(
fn=user_message,
inputs=[msg, chatbot, state, show_limbic, enable_thinking],
outputs=[msg, chatbot, state, limbic_display],
)
msg.submit(
fn=user_message,
inputs=[msg, chatbot, state, show_limbic, enable_thinking],
outputs=[msg, chatbot, state, limbic_display],
)
clear_btn.click(
fn=clear_all,
inputs=[],
outputs=[state, chatbot, limbic_display],
)
# ββ Example prompts ββ
gr.Examples(
examples=[
["I'm terrified of losing my job and I can't sleep at night."],
["Tell me something fascinating about how the brain processes emotions!"],
["My best friend is moving away and I feel completely lost."],
["I just got promoted! I'm so excited about what comes next!"],
["I want to help my sister who's going through depression. What should I do?"],
["Everyone keeps telling me I should 'just be positive' and it makes me furious."],
],
inputs=msg,
)
if __name__ == "__main__":
demo.launch()
|