Skip to content
Draft
Show file tree
Hide file tree
Changes from 9 commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
9779303
docs(hivemind): add comprehensive HiveMind orchestration plan and tas…
Mirrowel Nov 19, 2025
20e0cb1
feat(ensemble): add HiveMind ensemble manager, config loader, and def…
Mirrowel Nov 19, 2025
e80c3e0
feat(ensemble): delegate HiveMind ensemble requests to ensemble manager
Mirrowel Nov 19, 2025
2c99326
feat(ensemble): ✨ add _prepare_drones to prepare drone configs for pa…
Mirrowel Nov 19, 2025
d13eb95
feat(ensemble): add parallel drone execution and response formatter
Mirrowel Nov 19, 2025
eccbea4
feat(ensemble): add arbiter prompt builder, arbiter caller, and swarm…
Mirrowel Nov 19, 2025
0ab51aa
fix(ensemble): use litellm.acompletion for drone API calls
Mirrowel Nov 19, 2025
eb5d7a1
feat(ensemble): add streaming arbiter and swarm handlers
Mirrowel Nov 19, 2025
8af4919
fix(client): prefetch model mapping to avoid repeated lookups during …
Mirrowel Nov 19, 2025
4d83427
feat(ensemble): route swarm requests to streaming handler when stream…
Mirrowel Nov 19, 2025
b343bd4
feat(ensemble): ✨ add temperature jitter and adversarial drone mode
Mirrowel Nov 19, 2025
aa8a609
feat(ensemble): ✨ add blind-mode response anonymization and hoist imp…
Mirrowel Nov 19, 2025
bc2672a
feat(ensemble): prepare specialist model configurations for fusion
Mirrowel Nov 19, 2025
e86457a
feat(ensemble): add fusion phase 5 with specialist roles, arbiter rou…
Mirrowel Nov 19, 2025
08edb05
docs(hivemind): 📚 update HiveMind task checklist progress
Mirrowel Nov 19, 2025
d03d34d
feat(ensemble): ✨ add streaming fusion handler and consolidate fusion…
Mirrowel Nov 19, 2025
e41cfd2
feat(ensemble): add recursive arbiter mode and filter internal reasoning
Mirrowel Nov 19, 2025
0856dc0
fix(ensemble): 🐛 use deepcopy, load provider models, and robustly han…
Mirrowel Nov 19, 2025
5da1db4
feat(ensemble): dynamically aggregate usage and add cost/latency trac…
Mirrowel Nov 19, 2025
865f7cf
feat(ensemble): add specialist weight descriptions and embed expertis…
Mirrowel Nov 19, 2025
60243f5
feat(ensemble): extract specialist metadata for arbiter and return al…
Mirrowel Nov 19, 2025
55a94f8
fix(rotator): 🐛 include HiveMind fusion models in available models li…
Mirrowel Nov 19, 2025
4b0a0bf
docs(hivemind): 📚 add HiveMind API and user guide, update task checklist
Mirrowel Nov 19, 2025
6c9f278
feat(ensemble): add preset-based hivemind swarm model discovery and h…
Mirrowel Nov 19, 2025
d093b26
docs(hivemind): 📚 mark fusion features and documentation items comple…
Mirrowel Nov 19, 2025
2323dbc
feat(ensemble): support multi-fusion config format and fusion id suffix
Mirrowel Nov 19, 2025
d8c90b2
docs(hivemind): 📚 standardize "HiveMind Ensemble" naming across docum…
Mirrowel Nov 19, 2025
105d10a
feat(ensemble): switch swarm loader to preset-based format and add sa…
Mirrowel Nov 19, 2025
d8ed4a2
feat(ensemble): add role template support and sample role configs
Mirrowel Nov 19, 2025
6794096
fix(config): 🐛 report correct swarm preset count in loader log
Mirrowel Nov 19, 2025
f8de42b
refactor(ensemble): 🔨 standardize HiveMind ensemble initialization logs
Mirrowel Nov 19, 2025
e03d42c
feat(ensemble): ✨ enable implicit preset lookup for compact swarm IDs…
Mirrowel Nov 19, 2025
9e6cbc0
docs(ensemble): 📚 add HiveMind Ensemble documentation, presets, roles…
Mirrowel Nov 19, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,290 changes: 1,290 additions & 0 deletions docs/HiveMind Plan.md

Large diffs are not rendered by default.

93 changes: 93 additions & 0 deletions docs/HiveMind Task.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# HiveMind (Swarm/Fusion) Implementation

## Phase 1: Core Infrastructure
- [/] Design and Plan
- [x] Explore codebase
- [x] Create comprehensive implementation plan
- [ ] Create `src/rotator_library/ensemble_manager.py`
- [ ] Define `EnsembleManager` class skeleton
- [ ] Implement config loading and validation
- [ ] Implement `is_ensemble()` detection
- [ ] Implement conflict resolution for naming
- [ ] Modify `src/rotator_library/client.py`
- [ ] Initialize `EnsembleManager` in `__init__`
- [ ] Integrate into `acompletion()` dispatcher
- [ ] Add logging for HiveMind operations
- [ ] Create `ensemble_config.json`
- [ ] Define schema for Fusions
- [ ] Define schema for Swarm defaults
- [ ] Define arbitration strategies

## Phase 2: Basic Swarm Mode
- [ ] Implement Swarm Features
- [ ] `_prepare_drones()` - basic cloning
- [ ] `_execute_parallel()` - asyncio.gather
- [ ] `_format_for_arbiter()` - response aggregation
- [ ] `_build_arbiter_prompt()` - synthesis strategy
- [ ] `_call_arbiter()` - judge execution
- [ ] Testing
- [ ] Test basic 3-drone swarm
- [ ] Test arbiter synthesis
- [ ] Test partial failures

## Phase 3: Advanced Swarm Features
- [ ] Temperature Jitter
- [ ] Implement jitter logic
- [ ] Test randomness and clamping
- [ ] Adversarial Mode
- [ ] Implement adversarial prompt injection
- [ ] Test with configurable count
- [ ] Blind Switch
- [ ] Implement response anonymization
- [ ] Test with blind=true/false
- [ ] Confidence Scoring
- [ ] Implement score extraction
- [ ] Add logging for scores

## Phase 4: Fusion Mode
- [ ] Implement Fusion Features
- [ ] `_prepare_models()` - multi-model setup
- [ ] Role assignment and prompts
- [ ] Role context for Arbiter
- [ ] Weight system (future)
- [ ] Testing
- [ ] Test 2-model fusion
- [ ] Test role context injection
- [ ] Test specialist descriptions

## Phase 5: Recursive/Reflective Mode
- [ ] Implement Recursion
- [ ] Consensus check logic
- [ ] Conflict extraction
- [ ] `_trigger_round_2()` implementation
- [ ] Max rounds enforcement
- [ ] Testing
- [ ] Test low-confidence trigger
- [ ] Test Round 2 critique
- [ ] Test final re-synthesis

## Phase 6: Polish & Edge Cases
- [ ] Error Handling
- [ ] Partial failure handling
- [ ] Arbiter failure fallback
- [ ] Infinite recursion prevention
- [ ] Performance
- [ ] Latency logging
- [ ] Token usage tracking
- [ ] Rate limit mitigation
- [ ] Documentation
- [ ] User guide
- [ ] Example configs
- [ ] API reference

## Verification
- [ ] Automated Tests
- [ ] test_ensemble_manager.py (all 8 test cases)
- [ ] test_swarm_logic.py
- [ ] test_fusion_logic.py
- [ ] test_recursion.py
- [ ] Manual Tests
- [ ] Scenario 1: Simple Swarm
- [ ] Scenario 2: Adversarial Swarm
- [ ] Scenario 3: Fusion with Roles
- [ ] Scenario 4: Recursive Refinement
49 changes: 34 additions & 15 deletions src/rotator_library/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
from .credential_manager import CredentialManager
from .background_refresher import BackgroundRefresher
from .model_definitions import ModelDefinitions
from .ensemble import EnsembleManager


class StreamedAPIError(Exception):
Expand Down Expand Up @@ -128,6 +129,10 @@ def __init__(
if max_val < 1:
lib_logger.warning(f"Invalid max_concurrent for '{provider}': {max_val}. Setting to 1.")
self.max_concurrent_requests_per_key[provider] = 1

# Initialize HiveMind ensemble manager
self.ensemble_manager = EnsembleManager(rotating_client=self)
lib_logger.info("HiveMind ensemble manager initialized")

def _is_model_ignored(self, provider: str, model_id: str) -> bool:
"""
Expand Down Expand Up @@ -636,6 +641,15 @@ async def _execute_with_retry(
kwargs = self._convert_model_params(**kwargs)

# The main rotation loop. It continues as long as there are untried credentials and the global deadline has not been exceeded.

# Resolve model ID early, before any credential operations
# This ensures consistent model ID usage for acquisition, release, and tracking
resolved_model = self._resolve_model_id(model, provider)
if resolved_model != model:
lib_logger.info(f"Resolved model '{model}' to '{resolved_model}'")
model = resolved_model
kwargs["model"] = model # Ensure kwargs has the resolved model for litellm

while (
len(tried_creds) < len(credentials_for_provider) and time.time() < deadline
):
Expand Down Expand Up @@ -689,13 +703,8 @@ async def _execute_with_retry(

provider_plugin = self._get_provider_instance(provider)

# Convert model name to ID if custom mapping exists
resolved_model = self._resolve_model_id(model, provider)
if resolved_model != model:
lib_logger.info(f"Resolved model '{model}' to '{resolved_model}'")
litellm_kwargs["model"] = resolved_model
# Update the model variable for subsequent logging
model = resolved_model
# Model ID is already resolved before the loop, and kwargs['model'] is updated.
# No further resolution needed here.

# Apply model-specific options for custom providers
if provider_plugin and hasattr(provider_plugin, "get_model_options"):
Expand Down Expand Up @@ -996,6 +1005,14 @@ async def _streaming_acompletion_with_retry(

consecutive_quota_failures = 0

# Resolve model ID early, before any credential operations
# This ensures consistent model ID usage for acquisition, release, and tracking
resolved_model = self._resolve_model_id(model, provider)
if resolved_model != model:
lib_logger.info(f"Resolved model '{model}' to '{resolved_model}'")
model = resolved_model
kwargs["model"] = model # Ensure kwargs has the resolved model for litellm

try:
while (
len(tried_creds) < len(credentials_for_provider)
Expand Down Expand Up @@ -1071,13 +1088,8 @@ async def _streaming_acompletion_with_retry(

provider_plugin = self._get_provider_instance(provider)

# Convert model name to ID if custom mapping exists
resolved_model = self._resolve_model_id(model, provider)
if resolved_model != model:
lib_logger.info(f"Resolved model '{model}' to '{resolved_model}'")
litellm_kwargs["model"] = resolved_model
# Update the model variable for subsequent logging
model = resolved_model
# Model ID is already resolved before the loop, and kwargs['model'] is updated.
# No further resolution needed here.

# Apply model-specific options for custom providers
if provider_plugin and hasattr(
Expand Down Expand Up @@ -1606,8 +1618,15 @@ def acompletion(
Returns:
The completion response object, or an async generator for streaming responses, or None if all retries fail.
"""
# Handle iflow provider: remove stream_options to avoid HTTP 406
model = kwargs.get("model", "")

# Check if this is an ensemble request (HiveMind)
if model and self.ensemble_manager.is_ensemble(model):
lib_logger.debug(f"[HiveMind] Detected ensemble request: {model}")
# Delegate to ensemble manager
return self.ensemble_manager.handle_request(request=request, **kwargs)

# Handle iflow provider: remove stream_options to avoid HTTP 406
provider = model.split("/")[0] if "/" in model else ""

if provider == "iflow" and "stream_options" in kwargs:
Expand Down
9 changes: 9 additions & 0 deletions src/rotator_library/ensemble/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
"""
HiveMind Ensemble Module

This module provides parallel model execution (Swarm/Fusion) with intelligent arbitration.
"""

from .manager import EnsembleManager

__all__ = ['EnsembleManager']
Loading