Catalog PyPI
PACKAGE EXPLORERView in registry

adaptivegraph

PyPI

Learnable conditional edges for agentic workflows using contextual bandits

agenticbanditcontextual-banditlanggraphlinucbmachine-learningreinforcement-learningrouting
Versions collected1
Direct dependencies11From release 0.1.2
Last observed20 Oct, 19:06 UTC

README

Version 0.1.2 documentation

AdaptiveGraph

CI License: MIT Python 3.11+ Code style: black

from adaptivegraph import LearnableEdge

AdaptiveGraph provides LearnableEdge – a conditional edge that improves routing decisions over time through reinforcement learning.

What is LearnableEdge?

LearnableEdge replaces static routing logic with a learning-based approach. Instead of hard-coded if/else statements, it learns from feedback which routes work best for different inputs.

Key Features:

  • 🧠 Learning: Adapts routing decisions based on feedback (currently LinUCB, more policies coming)
  • ⚡ Lightweight: No training phase, no model files – learns online
  • 🎯 Balanced: Balances exploration (trying new routes) vs exploitation (using proven routes)
  • 🔧 Flexible: Works with strings, dicts, numpy arrays, or custom embeddings

Why LearnableEdge?

Traditional routing logic is static and brittle. LearnableEdge adds plasticity – it learns which routes work best through experience, automatically adapting as patterns change.

Installation

From PyPI:

pip install adaptivegraph

From source:

git clone https://github.com/BharathBillawa/adaptivegraph.git
cd adaptivegraph
pip install -e .

With optional dependencies:

# For semantic embeddings
pip install adaptivegraph[embed]

# For persistent storage
pip install adaptivegraph[faiss]

# For development
pip install adaptivegraph[dev]

# Everything
pip install adaptivegraph[all]

Quick Start

from adaptivegraph import LearnableEdge

# Create edge with routing options
edge = LearnableEdge(options=["expert_model", "fast_model", "cheap_model"])

# Make decisions
route = edge({"user": "premium", "query": "complex question"})

# Provide feedback so it learns
edge.record_feedback(result={}, reward=1.0)

See more examples:

How LearnableEdge Works

Think of LearnableEdge as a smart traffic router that learns which highway to recommend:

  1. Input State → You provide any state (string, dict, array)
  2. Encoding → Converts state into a fixed-size vector (32-dim by default)
  3. UCB Scoring → For each option, calculates:
    • Expected reward (what worked before)
    • Uncertainty bonus (exploration value)
    • UCB Score = expected_reward + α × uncertainty
  4. Selection → Picks option with highest UCB score
  5. Feedback → You call record_feedback(reward)
  6. Learning → Updates internal belief about which options work best

The algorithm balances:

  • Exploitation → Using routes with good historical performance
  • Exploration → Trying routes with high uncertainty

Features

- **Semantic Routing**: Use sentence transformers for similarity-based decisions (requires `adaptivegraph[embed]`)
- **Async Feedback**: Provide feedback hours later using event IDs
- **Trajectory Rewards**: Reward entire multi-step sessions with decay
- **Policy Persistence**: Save and restore learned routing policies

## Usage Examples

### Async Feedback
Pass `event_id` in the state to track decisions, then use it to record feedback later.
```python
# 1. Make decision with event_id
state = {"user": "premium", "query": "async test", "event_id": "req_123"}
route = edge(state)

# 2. Record feedback later using the same ID (no state needed)
edge.record_feedback(result={}, reward=1.0, event_id="req_123")
```

### Trajectory (Multi-step) Rewards
Pass `trace_id` in the state to group decisions into a session.
```python
# Step 1
edge({"step": 1, "intent": "greeting", "trace_id": "session_abc"})
# Step 2
edge({"step": 2, "intent": "params", "trace_id": "session_abc"})

# Reward the whole trace
edge.complete_trace(trace_id="session_abc", final_reward=1.0)
```

### Statistics
Inspect memory to see what the model has learned.
```python
stats = edge.memory.get_statistics()
print(f"Total decisions: {stats['total_decisions']}")
print(f"Average reward: {stats['average_reward']:.2f}")

# Access raw history
print(f"History size: {len(edge.memory.state_history)}")
```

## Notes & Gotchas
*   **Numpy Arrays**: Must match `feature_dim` (default 32). E.g., `np.random.randn(32)`.
*   **Factory Method**: `LearnableEdge.create()` defaults to `embedding="sentence-transformers"`, which requires the optional dependency.
    *   To use **without** optional dependencies, set `embedding=None` (uses hashing).
*   **Optional Dependencies**:
    *   `embedding="sentence-transformers"` requires `pip install adaptivegraph[embed]`
    *   `memory="faiss"` requires `pip install adaptivegraph[faiss]`

See [`examples/`](examples/) and [`notebooks/`](notebooks/) for detailed usage.

Comparison

LearnableEdge vs alternatives:

  • vs If/Else Rules: Learns from feedback instead of requiring manual updates
  • vs ML Classifiers: No training data needed, learns online from real usage
  • vs LLM Routers: Faster, cheaper, and adapts based on actual outcomes
  • vs Random/Epsilon-Greedy: Uses context to make smarter decisions, not just random exploration

Performance

On a typical customer support routing task (3 options, 1000 decisions):

  • Convergence: Achieves >95% accuracy within 50-100 iterations
  • Throughput: ~10,000 decisions/second on MacBook Pro M1
  • Memory: <50MB for 10,000 experiences

Roadmap

Completed ✅

  • Core LinUCB policy
  • Persistent storage (FAISS/Pickle)
  • Semantic state encoding (Sentence Transformers)
  • Async / ID-based feedback
  • Trajectory / trace rewards
  • Policy state persistence
  • Input validation and logging

Planned 🚧

  • Thompson Sampling policy
  • Epsilon-Greedy policy
  • Shared feature LinUCB (not disjoint)
  • Distributed training support
  • Visualization dashboard
  • Automated hyperparameter tuning
  • Integration examples (FastAPI, Streamlit)

Contributing

We welcome contributions! Please see CONTRIBUTING.md for guidelines.

Quick Start for Contributors

# Clone and setup
git clone https://github.com/BharathBillawa/adaptivegraph.git
cd adaptivegraph
pip install -e ".[dev]"

# Run tests
pytest tests/ -v

# Format code
black src/ tests/
isort src/ tests/

Citation

If you use AdaptiveGraph in your research, please cite:

@software{adaptivegraph2024,
  title = {AdaptiveGraph: Learnable Conditional Edges for Agentic Workflows},
  author = {BharathPoojary},
  year = {2024},
  url = {https://github.com/BharathBillawa/adaptivegraph}
}

License

MIT License - see LICENSE for details.

Acknowledgments

  • Built for LangGraph but framework-agnostic
  • LinUCB algorithm from Li et al. (2010)
  • Inspired by contextual bandit research in recommendation systems

Support


Made with ❤️ for the AI agent community

Downloads & popularity

Awaiting observations

No metric observations yet

Download counts and popularity will appear here as the collector receives them.

Versions 1

Collected releases
VersionPublishedDirect dependenciesOpen version
0.1.224 Dec 202511

Package advisories

0
No matching advisories collected

This describes our collected data; it is not a security assessment.

Repository

PENDING
bharathbillawa/adaptivegraph

Shared repository data · GitHub

License detected in repository
Not collected

Metadata history

Meaningful changes
Current collected state Current

Observed since 20 Oct, 19:06 UTC

No superseded metadata states collected. Unchanged observations do not create new revisions.

Record identity

package:cb88a3699af25e9c9949029a07ebbe1fb21f5625b16edaf49fbe6f9421a80844