Skip to main content

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

Metadata

Release files for adaptivegraph 0.1.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for adaptivegraph 0.1.2
File Size Uploaded Provenance
adaptivegraph-0.1.2.tar.gz 63.1 kB Without provenance Details

Built distribution (wheel)

Table of built distributions (wheels) for adaptivegraph 0.1.2
File Interpreter ABI Platform
adaptivegraph-0.1.2-py3-none-any.whl Python 3 none any Details

Total release size: 79.5 kB

Release files / adaptivegraph-0.1.2.tar.gz

Download URL adaptivegraph-0.1.2.tar.gz
Size 63.1 kB
Tags Source
SHA-256 checksum
How to use checksums
a1bd44e2daafeb145503e36e49b5a249e3a1f7be645979b7a8b2f22df28a6dc0
BLAKE2b-256 checksum
How to use checksums
408e1961e6e59ca9b365efec9a04c6657101829c7f8c71c95fcacd624f77376c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.11

Release files / adaptivegraph-0.1.2-py3-none-any.whl

Download URL adaptivegraph-0.1.2-py3-none-any.whl
Size 16.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
07b96c4258f8c9a258764665456457f3f6ae7d253c0fad79afcbc1cd0c1517fb
BLAKE2b-256 checksum
How to use checksums
dbfc9ea74b7676169026df2c34bb828c49980d5e69237c4523c7f123bedb0c84
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.11.11

Security for adaptivegraph 0.1.2

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

No provenance found

None of the files in this release were uploaded with provenance metadata.

A note on package security

PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page