Skip to main content

Operations Research Agentic Framework - A lightweight framework for creating AI agents with tool-calling capabilities

Project description

OR-AF (Operations Research Agentic Framework)

A lightweight, production-ready framework for creating AI agents with tool-calling capabilities, streaming support, comprehensive logging, and full observability. Designed for operations research and optimization tasks.

Python 3.8+ License: MIT

✨ Features

  • 🔧 Tool Support: Easy tool registration with automatic schema generation
  • 📊 Full Observability: Custom callbacks for monitoring every step
  • 🌊 Streaming Responses: Real-time streaming of agent responses
  • 📝 Comprehensive Logging: Colored console logging and file logging
  • ✅ Type Safety: Built with Pydantic for full type validation
  • ⚡ Lightweight: Minimal dependencies, maximum performance
  • 🎯 Simple API: Intuitive interface inspired by popular frameworks
  • 🔍 Error Handling: Robust error handling with custom exceptions
  • 📈 Metrics: Built-in execution metrics and performance tracking

🚀 Installation

From Source (Development)

From Source (Development)

git clone https://github.com/iaakashRoy/or-af.git
cd or-af
pip install -e .

Using pip (when published)

pip install or-af

📋 Requirements

  • Python 3.8+
  • openai >= 1.0.0
  • python-dotenv >= 1.0.0
  • pydantic >= 2.0.0

🎯 Quick Start

1. Configure Environment

Create a .env file with your Azure OpenAI credentials:

endpoint = "https://your-endpoint.openai.azure.com/"
deployment = "your-deployment-name"
subscription_key = "your-api-key"
api_version = "2024-12-01-preview"

2. Create Your First Agent

from or_af import Agent

# Initialize agent with a system prompt
agent = Agent(
    system_prompt="You are a helpful AI assistant.",
    max_iterations=10,
    stream=True,  # Enable streaming
    verbose=True  # Enable detailed logging
)

3. Add Tools

def calculator(operation: str, x: float, y: float) -> float:
    """Perform basic arithmetic operations."""
    if operation == "add":
        return x + y
    elif operation == "multiply":
        return x * y
    # ... more operations

# Register the tool
agent.add_tool("calculator", calculator, "Perform arithmetic calculations")

4. Run Tasks

# Run with streaming (default)
response = agent.run("What is 25 multiplied by 4?")

# Access detailed response
print(f"Success: {response.success}")
print(f"Response: {response.response}")
print(f"Iterations: {response.iteration_count}")
print(f"Tools called: {response.total_tool_calls}")
print(f"Duration: {response.total_duration:.2f}s")

🎨 Advanced Features

Custom Callbacks for Observability

from or_af import BaseCallback, Agent
from or_af.models import ToolCall, ToolResult

class MyCustomCallback(BaseCallback):
    """Track custom metrics"""
    
    def on_tool_call_start(self, tool_call: ToolCall):
        print(f"Tool starting: {tool_call.name}")
    
    def on_tool_call_end(self, tool_result: ToolResult):
        print(f"Tool completed in {tool_result.execution_time:.3f}s")
    
    def on_thinking(self, iteration: int, thinking: str):
        print(f"Agent is thinking: {thinking}")

# Use custom callback
agent = Agent(
    system_prompt="You are helpful",
    callbacks=[MyCustomCallback()]
)

Streaming vs Non-Streaming

# Streaming mode (real-time output)
response = agent.run("Calculate something", stream=True)

# Non-streaming mode
response = agent.run("Calculate something", stream=False)

Access Detailed Execution Info

response = agent.run("Complex task")

# Iterate through each iteration
for iteration in response.iterations:
    print(f"Iteration {iteration.iteration_number}:")
    print(f"  Duration: {iteration.duration:.2f}s")
    print(f"  Tools called: {len(iteration.tool_calls)}")
    
    for tool_call in iteration.tool_calls:
        print(f"    - {tool_call.name}({tool_call.arguments})")

Custom Logging

from or_af import setup_logger
from pathlib import Path
import logging

# Setup custom logger
logger = setup_logger(
    name="my_agent",
    level=logging.DEBUG,
    log_file=Path("agent.log"),
    use_colors=True
)

# Use with agent
from or_af.callbacks import LoggingCallback
agent = Agent(
    system_prompt="You are helpful",
    callbacks=[LoggingCallback(logger)]
)

📚 Examples

Example 1: Simple Calculator

from or_af import Agent

def add(x: float, y: float) -> float:
    """Add two numbers"""
    return x + y

def multiply(x: float, y: float) -> float:
    """Multiply two numbers"""
    return x * y

agent = Agent(system_prompt="You are a math assistant")
agent.add_tool("add", add)
agent.add_tool("multiply", multiply)

response = agent.run("What is (25 + 75) * 2?")
print(response.response)

Example 2: With Error Handling

from or_af import Agent, ToolExecutionError

def divide(x: float, y: float) -> float:
    """Divide two numbers"""
    if y == 0:
        raise ValueError("Cannot divide by zero")
    return x / y

agent = Agent(system_prompt="You are a calculator")
agent.add_tool("divide", divide)

try:
    response = agent.run("Divide 100 by 0")
    if not response.success:
        print(f"Error: {response.error_message}")
except Exception as e:
    print(f"Exception: {e}")

🏗️ Architecture

Core Components

  1. Agent: Main orchestrator that manages conversation flow
  2. Tool: Wraps Python functions with automatic schema generation
  3. CallbackManager: Handles observability callbacks
  4. Models: Pydantic models for type safety and validation
  5. Logger: Colored console and file logging

Execution Flow

User Task → Agent
    ↓
Agent analyzes task
    ↓
Decides which tools to use
    ↓
Executes tools (with callbacks)
    ↓
Synthesizes response
    ↓
Returns AgentResponse

📊 Models

AgentResponse

response = agent.run("task")

# Access properties
response.task              # Original task
response.response          # Final response
response.iterations        # List[IterationState]
response.total_tool_calls  # Number of tools called
response.success           # bool
response.error_message     # Optional error
response.total_duration    # Execution time in seconds

IterationState

for iteration in response.iterations:
    iteration.iteration_number  # int
    iteration.tool_calls        # List[ToolCall]
    iteration.tool_results      # List[ToolResult]
    iteration.thinking          # Agent's reasoning
    iteration.response          # Final response if last iteration
    iteration.duration          # Execution time

🔧 Configuration

AgentConfig

agent = Agent(
    system_prompt="Your prompt",      # Required
    model_name="gpt-4",               # Optional, defaults to env
    temperature=1.0,                   # 0.0 to 2.0
    max_iterations=10,                 # Max tool-call loops
    stream=True,                       # Enable streaming
    verbose=True                       # Enable console output
)

🧪 Running Examples

# Simple example
python examples/simple_example.py

# Advanced example with all features
python examples/advanced_example.py

# Jupyter notebook
jupyter notebook examples/advanced_example.ipynb

📝 Logging Levels

  • DEBUG: Detailed execution information
  • INFO: General information about operations
  • WARNING: Warning messages
  • ERROR: Error messages with stack traces

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Acknowledgments

  • Built with OpenAI for LLM capabilities
  • Uses Pydantic for data validation
  • Inspired by LangChain and other agent frameworks

📞 Support

For issues, questions, or contributions, please visit our GitHub repository.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

or_af-0.1.0.tar.gz (20.3 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

or_af-0.1.0-py3-none-any.whl (16.4 kB view details)

Uploaded Python 3

File details

Details for the file or_af-0.1.0.tar.gz.

File metadata

  • Download URL: or_af-0.1.0.tar.gz
  • Upload date:
  • Size: 20.3 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for or_af-0.1.0.tar.gz
Algorithm Hash digest
SHA256 9a3162364daae792c06a961b4cd1c01555d702584127ed6dff0730ed34c8789b
MD5 c2dd5f657bb4727f4bc2ff45829af804
BLAKE2b-256 be756a00a6182e4c296372f16956c6589f8a1813976743fb297c3097a0efddf1

See more details on using hashes here.

Provenance

The following attestation bundles were made for or_af-0.1.0.tar.gz:

Publisher: publish.yml on iaakashRoy/or-af

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file or_af-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: or_af-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 16.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for or_af-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f229ae5e725c2b8db882fded7d2e85bcf5b22e3b5ce7b480e197925760134b3c
MD5 52dcb071d5bca074724e9b2ac3fb1f25
BLAKE2b-256 7fed057c937fddb1fb52994fca095be23343aec03f59fd7e32aa72159198caf9

See more details on using hashes here.

Provenance

The following attestation bundles were made for or_af-0.1.0-py3-none-any.whl:

Publisher: publish.yml on iaakashRoy/or-af

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page