Download splitbit_llm/agents/always_on.py from hermescures1/splitbit-llm: direct link, hf CLI and curl.
- Browser
- Download file 18.9 kB
-
https://huggingface.co/hermescures1/splitbit-llm/resolve/main/splitbit_llm/agents/always_on.py
- Command line
-
hf download hf://hermescures1/splitbit-llm/splitbit_llm/agents/always_on.py
-
curl -L -o always_on.py https://huggingface.co/hermescures1/splitbit-llm/resolve/main/splitbit_llm/agents/always_on.py
18.9 kB
| """Always-On Daemon β when not in use, the system keeps working. | |
| When the user isn't interacting: | |
| 1. The 5 agents talk to the LLM, creating a continuous learning loop | |
| 2. Jarvis creates skills from agent conversations | |
| 3. Conversation skill creation β patterns extracted from agent talks | |
| 4. Self-refinement engine optimizes speed and intelligence | |
| 5. Goals are progressed β agents pick up and work on pending goals | |
| 6. 100-project mode β auto-generates and works on 100 projects 24/7 | |
| 7. First-run naming β greets user as Incentives Inc. LLM, asks for a name | |
| This creates a system that's always getting smarter, even when idle. | |
| Once it has enough skills, it enters 100-project mode and never stops working. | |
| Daemon loop: | |
| - Check if user is active (recent conversation < 60s ago) | |
| - If idle: trigger agent conversations, skill creation, refinement, project generation | |
| - If active: do nothing (don't interfere with user interactions) | |
| - Runs in a background thread, started with `python -m splitbit_llm daemon` | |
| """ | |
| from __future__ import annotations | |
| import logging | |
| import random | |
| import threading | |
| import time | |
| from typing import Any, Callable | |
| from .agent_manager import AgentManager | |
| from .self_refine import SelfRefinementEngine | |
| logger = logging.getLogger(__name__) | |
| class AlwaysOnDaemon: | |
| """Always-on daemon β keeps the system working when idle. | |
| When the user isn't interacting: | |
| - Agents have conversations with the LLM (continuous learning) | |
| - Jarvis creates skills from those conversations | |
| - Self-refinement engine optimizes speed and intelligence | |
| - Goals are progressed | |
| The daemon monitors activity and only runs when the system is idle. | |
| """ | |
| IDLE_THRESHOLD_S = 60.0 # consider idle after 60s of no user activity | |
| AGENT_TALK_INTERVAL_S = 30.0 # agents talk every 30s when idle | |
| REFINEMENT_INTERVAL_S = 120.0 # refine every 2 minutes | |
| SKILL_CREATION_INTERVAL_S = 60.0 # create skills every 60s | |
| PROJECT_CHECK_INTERVAL_S = 45.0 # check project count every 45s | |
| MESH_INTERVAL_S = 90.0 # conversation mesh every 90s | |
| TARGET_PROJECT_COUNT = 100 # maintain 100 active projects | |
| FAST_REPLY_SKILL_THRESHOLD = 50 # need 50+ skills for fast replies | |
| FAST_REPLY_HIT_RATE_THRESHOLD = 0.3 # need 30%+ cache hit rate | |
| AGENT_CONVERSATION_TOPICS = [ | |
| "What's the most efficient way to process data?", | |
| "How can I improve my response speed?", | |
| "What patterns have you noticed in recent conversations?", | |
| "How do you handle complex problem-solving?", | |
| "What's the best approach for learning new skills?", | |
| "How can we optimize our tool usage?", | |
| "What are common mistakes to avoid in coding?", | |
| "How do you break down large tasks into smaller ones?", | |
| "What makes a good user experience?", | |
| "How can we improve our memory recall?", | |
| "What's the most important skill for an AI to have?", | |
| "How do you prioritize tasks when everything is urgent?", | |
| "What's the relationship between speed and accuracy?", | |
| "How can we learn from our mistakes?", | |
| "What's the best way to structure a project?", | |
| ] | |
| def __init__(self, harness: Any) -> None: | |
| self.harness = harness | |
| self._running = False | |
| self._thread: threading.Thread | None = None | |
| # Components | |
| self.agent_manager = harness.agent_manager | |
| self.refinement = SelfRefinementEngine(harness=harness) | |
| # State | |
| self._last_user_activity = time.time() | |
| self._last_agent_talk = 0.0 | |
| self._last_skill_creation = 0.0 | |
| self._last_refinement = 0.0 | |
| self._last_project_check = 0.0 | |
| self._last_mesh = 0.0 | |
| self._conversation_count = 0 | |
| self._skills_created = 0 | |
| self._projects_generated = 0 | |
| self._projects_completed = 0 | |
| self._hundred_project_mode = False | |
| self._stats = { | |
| "daemon_uptime_s": 0.0, | |
| "idle_cycles": 0, | |
| "agent_conversations": 0, | |
| "skills_created": 0, | |
| "refinement_cycles": 0, | |
| "goals_progressed": 0, | |
| "projects_generated": 0, | |
| "projects_completed": 0, | |
| "hundred_project_mode": False, | |
| "fast_reply_ready": False, | |
| "mesh_conversations": 0, | |
| "mesh_categories_discovered": 0, | |
| "mesh_skills_pooled": 0, | |
| } | |
| def notify_user_activity(self) -> None: | |
| """Call this when the user interacts with the system.""" | |
| self._last_user_activity = time.time() | |
| def start(self) -> None: | |
| """Start the always-on daemon.""" | |
| if self._running: | |
| return | |
| self._running = True | |
| self._start_time = time.time() | |
| # Start agents | |
| self.agent_manager.start_all() | |
| # Start self-refinement | |
| self.refinement.start() | |
| # Start daemon loop | |
| self._thread = threading.Thread(target=self._run_loop, daemon=True, name="always-on") | |
| self._thread.start() | |
| logger.info("Always-on daemon started β 5 agents active, self-refinement running") | |
| def stop(self) -> None: | |
| """Stop the daemon.""" | |
| self._running = False | |
| self.refinement.stop() | |
| self.agent_manager.stop_all() | |
| if self._thread: | |
| self._thread.join(timeout=10) | |
| logger.info("Always-on daemon stopped (ran %d cycles, %d agent conversations, %d skills created)", | |
| self._stats["idle_cycles"], self._stats["agent_conversations"], self._stats["skills_created"]) | |
| def _run_loop(self) -> None: | |
| """Main daemon loop.""" | |
| while self._running: | |
| time.sleep(5) # check every 5 seconds | |
| now = time.time() | |
| idle_time = now - self._last_user_activity | |
| self._stats["daemon_uptime_s"] = now - self._start_time | |
| if idle_time < self.IDLE_THRESHOLD_S: | |
| continue # user is active, don't interfere | |
| # System is idle β do work | |
| self._stats["idle_cycles"] += 1 | |
| # 1. Agent conversations (every AGENT_TALK_INTERVAL_S) | |
| if now - self._last_agent_talk > self.AGENT_TALK_INTERVAL_S: | |
| self._run_agent_conversation() | |
| self._last_agent_talk = now | |
| # 2. Skill creation from conversations (every SKILL_CREATION_INTERVAL_S) | |
| if now - self._last_skill_creation > self.SKILL_CREATION_INTERVAL_S: | |
| self._create_skills_from_conversations() | |
| self._last_skill_creation = now | |
| # 3. Self-refinement (every REFINEMENT_INTERVAL_S) | |
| if now - self._last_refinement > self.REFINEMENT_INTERVAL_S: | |
| result = self.refinement.refine_once() | |
| if result.get("actions"): | |
| self._stats["refinement_cycles"] += 1 | |
| self._last_refinement = now | |
| # 4. Progress goals | |
| self._progress_goals() | |
| # 5. Check fast reply readiness | |
| self._check_fast_reply_ready() | |
| # 6. Multi-LLM conversation mesh β agents converse to build skills | |
| if now - self._last_mesh > self.MESH_INTERVAL_S: | |
| self._run_mesh_conversation() | |
| self._last_mesh = now | |
| # 7. 100-project mode β auto-generate and maintain projects | |
| if now - self._last_project_check > self.PROJECT_CHECK_INTERVAL_S: | |
| self._maintain_hundred_projects() | |
| self._last_project_check = now | |
| def _run_agent_conversation(self) -> None: | |
| """Have an agent talk to the LLM β creates training data and skills.""" | |
| topic = random.choice(self.AGENT_CONVERSATION_TOPICS) | |
| # Pick a random agent to ask the question | |
| agent_names = list(self.agent_manager.agents.keys()) | |
| asking_agent = random.choice(agent_names) | |
| # Generate a response from the LLM | |
| try: | |
| prompt = f"Agent {asking_agent} asks: {topic}" | |
| response = self.harness._agent_generate(prompt) | |
| # Store in persistent memory | |
| self.harness.persistent_memory.add_episodic( | |
| "agent", f"{asking_agent}: {topic} β {response[:100]}", | |
| channel="agent-self-talk", importance=0.4, | |
| tags=["self-talk", asking_agent] | |
| ) | |
| # Store in recursive link graph | |
| self.harness.link_graph.add_context( | |
| topic, response, session_id="agent-self-talk", channel="agent" | |
| ) | |
| self._stats["agent_conversations"] += 1 | |
| self._conversation_count += 1 | |
| logger.debug("Agent conversation #%d: %s asks '%s'", self._conversation_count, asking_agent, topic[:40]) | |
| except Exception as e: | |
| logger.error("Agent conversation failed: %s", e) | |
| def _create_skills_from_conversations(self) -> None: | |
| """Extract skills from recent agent conversations.""" | |
| try: | |
| factory = self.harness.skill_factory | |
| skill = factory.extract_skill() | |
| if skill: | |
| self.harness.skill_manager.create(skill) | |
| self._stats["skills_created"] += 1 | |
| self._skills_created += 1 | |
| logger.info("Created skill from agent conversations: %s", skill.name) | |
| # Also try meta-skill | |
| meta = factory.maybe_create_meta_skill(self.harness.skill_manager) | |
| if meta: | |
| self.harness.skill_manager.create(meta) | |
| self._stats["skills_created"] += 1 | |
| except Exception as e: | |
| logger.debug("Skill creation from conversations: %s", e) | |
| def _progress_goals(self) -> None: | |
| """Check if any goals can be progressed.""" | |
| try: | |
| active = self.harness.goal_memory.get_active_goals() | |
| pending = self.harness.goal_memory.list_goals(status="pending") | |
| if pending and not active: | |
| # Assign pending goals to agents | |
| for goal in pending[:2]: # assign up to 2 at a time | |
| self.harness.goal_memory.assign_agent(goal.id, "planner") | |
| self._stats["goals_progressed"] += 1 | |
| logger.info("Assigned pending goal to planner: %s", goal.title) | |
| except Exception as e: | |
| logger.debug("Goal progression: %s", e) | |
| def _check_fast_reply_ready(self) -> None: | |
| """Check if the system is ready for near-instant replies.""" | |
| try: | |
| skill_stats = self.harness.skill_manager.get_stats() | |
| total_skills = skill_stats.get("total_skills", 0) | |
| cache = getattr(self.harness, 'fast_cache', None) | |
| hit_rate = cache.get_hit_rate() if cache else 0.0 | |
| ready = (total_skills >= self.FAST_REPLY_SKILL_THRESHOLD and | |
| hit_rate >= self.FAST_REPLY_HIT_RATE_THRESHOLD) | |
| if ready and not self._stats["fast_reply_ready"]: | |
| logger.info("Fast reply mode activated! %d skills, %.0f%% cache hit rate", | |
| total_skills, hit_rate * 100) | |
| self._stats["fast_reply_ready"] = ready | |
| except Exception as e: | |
| logger.debug("Fast reply check: %s", e) | |
| def _run_mesh_conversation(self) -> None: | |
| """Run a multi-LLM conversation mesh β agents converse to build skills. | |
| All 5 agents talk to each other on a topic, creating: | |
| - Skill building pools (collaborative skills) | |
| - New skill categories (auto-discovered) | |
| - Cross-agent knowledge sharing | |
| """ | |
| try: | |
| mesh = self.harness.conversation_mesh | |
| result = mesh.run_conversation() | |
| self._stats["mesh_conversations"] += 1 | |
| self._stats["mesh_categories_discovered"] += len(result.get("categories", [])) | |
| if result.get("skill_pool"): | |
| self._stats["mesh_skills_pooled"] += 1 | |
| logger.info("Mesh conversation: %s on '%s' β %d messages, %d categories, skill=%s", | |
| result.get("mode", "?"), result.get("topic", "?")[:40], | |
| result.get("messages", 0), len(result.get("categories", [])), | |
| result.get("skill_pool", False)) | |
| except Exception as e: | |
| logger.debug("Mesh conversation failed: %s", e) | |
| def _maintain_hundred_projects(self) -> None: | |
| """Maintain 100 active projects β auto-generate new ones when count drops. | |
| Once the system has enough skills and knowledge, it enters | |
| 100-project mode and continuously generates and works on projects. | |
| It never stops β as soon as one project completes, a new one is created. | |
| """ | |
| try: | |
| goal_stats = self.harness.goal_memory.get_stats() | |
| active_count = goal_stats.get("active", 0) | |
| pending_count = goal_stats.get("pending", 0) | |
| total_active = active_count + pending_count | |
| # Check if we should enter 100-project mode | |
| skill_stats = self.harness.skill_manager.get_stats() | |
| total_skills = skill_stats.get("total_skills", 0) | |
| if not self._hundred_project_mode: | |
| if total_skills >= self.FAST_REPLY_SKILL_THRESHOLD: | |
| self._hundred_project_mode = True | |
| self._stats["hundred_project_mode"] = True | |
| logger.info("Entering 100-project mode! %d skills accumulated. " | |
| "Generating and working on projects 24/7.", total_skills) | |
| if not self._hundred_project_mode: | |
| return # Not ready yet β keep learning | |
| # Generate new projects to maintain TARGET_PROJECT_COUNT | |
| if total_active < self.TARGET_PROJECT_COUNT: | |
| needed = self.TARGET_PROJECT_COUNT - total_active | |
| generated = self._generate_projects(min(needed, 5)) # generate up to 5 at a time | |
| self._stats["projects_generated"] += generated | |
| self._projects_generated += generated | |
| if generated > 0: | |
| logger.info("Generated %d new projects (active: %d/%d)", | |
| generated, total_active + generated, self.TARGET_PROJECT_COUNT) | |
| # Track completed projects | |
| completed = goal_stats.get("completed", 0) | |
| if completed > self._projects_completed: | |
| new_completions = completed - self._projects_completed | |
| self._projects_completed = completed | |
| self._stats["projects_completed"] = completed | |
| logger.info("Projects completed: %d total (+%d new)", completed, new_completions) | |
| except Exception as e: | |
| logger.debug("100-project mode: %s", e) | |
| def _generate_projects(self, count: int) -> int: | |
| """Generate new project goals automatically. | |
| Projects are generated from a mix of: | |
| - Template projects (improvement, optimization, learning) | |
| - LLM-generated project ideas | |
| - Skill-gap analysis (what skills are missing?) | |
| """ | |
| project_templates = [ | |
| ("Optimize inference speed", "Analyze and optimize the LLM inference pipeline for faster responses", "high"), | |
| ("Improve memory recall", "Enhance the persistent memory system's recall accuracy and speed", "medium"), | |
| ("Create new skill: {topic}", "Develop a new skill for {topic} interactions", "medium"), | |
| ("Optimize tokenizer", "Improve tokenizer efficiency and vocabulary coverage", "medium"), | |
| ("Enhance agent coordination", "Improve how the 5 agents coordinate on multi-step goals", "high"), | |
| ("Build conversation cache", "Expand the fast reply cache for more instant responses", "high"), | |
| ("Refine quantization", "Experiment with quantization formats to improve accuracy/speed tradeoff", "medium"), | |
| ("Create tool: {topic}", "Build a new tool for {topic} operations", "medium"), | |
| ("Improve recursive links", "Enhance the recursive link graph for better context retrieval", "low"), | |
| ("Optimize skill matching", "Improve skill trigger matching for more accurate skill selection", "medium"), | |
| ("Expand semantic memory", "Extract more semantic facts from conversations", "low"), | |
| ("Enhance voice responses", "Improve TTS output formatting and voice adapter latency", "medium"), | |
| ("Build webhook integration", "Create webhook endpoints for external service notifications", "low"), | |
| ("Optimize image generation", "Improve image generation speed and quality", "low"), | |
| ("Create API connector", "Build a new API connector for external service integration", "medium"), | |
| ("Improve goal planning", "Enhance the goal planning system with better step decomposition", "medium"), | |
| ("Refine self-talk topics", "Generate better self-talk conversation topics for continuous learning", "low"), | |
| ("Build monitoring dashboard", "Create a monitoring dashboard for system stats and health", "medium"), | |
| ("Optimize SQLite queries", "Profile and optimize SQLite queries for memory and goal storage", "medium"), | |
| ("Enhance error handling", "Improve error handling and recovery across all system components", "high"), | |
| ] | |
| topics = ["data processing", "code review", "text summarization", "pattern matching", | |
| "cache optimization", "memory management", "search algorithms", "data compression", | |
| "natural language", "math operations", "file handling", "network requests", | |
| "image processing", "audio processing", "task scheduling", "resource monitoring"] | |
| generated = 0 | |
| for i in range(count): | |
| try: | |
| template = random.choice(project_templates) | |
| title = template[0].format(topic=random.choice(topics)) | |
| description = template[1].format(topic=random.choice(topics)) | |
| priority = template[2] | |
| self.harness.create_goal(title, description, priority=priority, | |
| tags=["auto-generated", "100-project"]) | |
| generated += 1 | |
| except Exception as e: | |
| logger.debug("Project generation failed: %s", e) | |
| break | |
| return generated | |
| def get_stats(self) -> dict[str, Any]: | |
| return { | |
| **self._stats, | |
| "running": self._running, | |
| "idle": (time.time() - self._last_user_activity) > self.IDLE_THRESHOLD_S, | |
| "idle_time_s": round(time.time() - self._last_user_activity, 1), | |
| "refinement": self.refinement.get_stats(), | |
| "agents": self.agent_manager.get_stats(), | |
| } | |