Metadata-Version: 2.4
Name: modaic
Version: 0.4.1
Summary: Modular Agent Infrastructure Collection, a python framework for managing and sharing DSPy agents
Author-email: Tyrin <tytodd@mit.edu>, Farouk <farouk@modaic.dev>
License: MIT License
        
        Copyright (c) 2025 Modaic Inc
        
        Permission is hereby granted, free of charge, to any person obtaining a copy
        of this software and associated documentation files (the "Software"), to deal
        in the Software without restriction, including without limitation the rights
        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
        copies of the Software, and to permit persons to whom the Software is
        furnished to do so, subject to the following conditions:
        
        The above copyright notice and this permission notice shall be included in all
        copies or substantial portions of the Software.
        
        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
        SOFTWARE.
        
        ---
        
        Additional Terms:
        
        1. You may not modify this Software in any way that changes the default hub
           endpoint, nor distribute derivative works that route agents or models to
           a hub other than modaic.dev.
        
        2. All other rights are granted as per the MIT License.
        
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: aenum>=3.1.16
Requires-Dist: dspy>=2.6.27
Requires-Dist: duckdb>=1.3.2
Requires-Dist: filetype>=1.2.0
Requires-Dist: gitpython>=3.1.45
Requires-Dist: immutables>=0.21
Requires-Dist: langchain-community>=0.3.29
Requires-Dist: langchain-core>=0.3.72
Requires-Dist: langchain-text-splitters>=0.3.9
Requires-Dist: more-itertools>=10.8.0
Requires-Dist: openpyxl>=3.1.5
Requires-Dist: opik==1.8.42
Requires-Dist: pillow>=11.3.0
Requires-Dist: pymilvus>=2.5.14
Requires-Dist: sqlalchemy>=2.0.42
Requires-Dist: tomlkit>=0.13.3
Provides-Extra: pinecone
Requires-Dist: pinecone>=7.3.0; extra == "pinecone"
Dynamic: license-file

[![Docs](https://img.shields.io/badge/docs-available-brightgreen.svg)](https://docs.modaic.dev)
[![PyPI](https://img.shields.io/pypi/v/modaic)](https://pypi.org/project/modaic/)


# Modaic 🐙
**Mod**ular **A**gent **I**nfrastructure **C**ollection, a Python framework for building AI agents with structured context management, database integration, and retrieval-augmented generation (RAG) capabilities.

## Overview

Modaic provides a comprehensive toolkit for creating intelligent agents that can work with diverse data sources including tables, documents, and databases. Built on top of DSPy, it offers a way to share and manage declarative agent architectures with integrated vector, SQL, and graph database support.

## Key Features

- **Hub Support**: Load and share precompiled agents from Modaic Hub
- **Context Management**: Structured handling of molecular and atomic context types
- **Database Integration**: Support for Vector (Milvus, Pinecone, Qdrant), SQL (SQLite, MySQL, PostgreSQL), and Graph (Memgraph, Neo4j)
- **Agent Framework**: Precompiled and auto-loading agent architectures
- **Table Processing**: Advanced Excel/CSV processing with SQL querying capabilities


## Installation

### Using uv (recommended)

```bash
uv add modaic
```

Optional (for hub operations):

```bash
export MODAIC_TOKEN="<your-token>"
```

### Using pip
Please note that you will not be able to push agents to the Modaic Hub with pip.
```bash
pip install modaic
```
## Quick Start

### Creating a Simple Agent

```python
from modaic import PrecompiledAgent, PrecompiledConfig

class WeatherConfig(PrecompiledConfig):
    weather: str = "sunny"

class WeatherAgent(PrecompiledAgent):
    config: WeatherConfig

    def __init__(self, config: WeatherConfig, **kwargs):
        super().__init__(config, **kwargs)

    def forward(self, query: str) -> str:
        return f"The weather in {query} is {self.config.weather}."

agent = WeatherAgent(WeatherConfig())
print(agent(query="Tokyo"))
```

Save and load locally:

```python
agent.save_precompiled("./my-weather")

from modaic import AutoAgent, AutoConfig

cfg = AutoConfig.from_precompiled("./my-weather", local=True)
loaded = AutoAgent.from_precompiled("./my-weather", local=True)
print(loaded(query="Kyoto"))
```

### Working with Tables

```python
from pathlib import Path
from modaic.context import Table, TableFile
import pandas as pd

# Load from Excel/CSV
excel = TableFile.from_file(
    file_ref="employees.xlsx",
    file=Path("employees.xlsx"),
    file_type="xlsx",
)
csv = TableFile.from_file(
    file_ref="data.csv",
    file=Path("data.csv"),
    file_type="csv",
)

# Create from DataFrame
df = pd.DataFrame({"col1": [1, 2, 3], "col2": [4, 5, 6]})
table = Table(df=df, name="my_table")

# Query with SQL (refer to in-memory table as `this`)
result = table.query("SELECT * FROM this WHERE col1 > 1")

# Convert to markdown
markdown = table.markdown()
```

### Database Integration

#### SQL Database
```python
from modaic.databases import SQLDatabase, SQLiteBackend

# Configure and connect
backend = SQLiteBackend(db_path="my_database.db")
db = SQLDatabase(backend)

# Add table
db.add_table(table)

# Query
rows = db.fetchall("SELECT * FROM my_table")
```

#### Vector Database
#### Graph Database
```python
from modaic.context import Context, Relation
from modaic.databases import GraphDatabase, MemgraphConfig, Neo4jConfig

# Configure backend (choose one)
mg = GraphDatabase(MemgraphConfig())
# or
neo = GraphDatabase(Neo4jConfig())

# Define nodes
class Person(Context):
    name: str
    age: int

class KNOWS(Relation):
    since: int

alice = Person(name="Alice", age=30)
bob = Person(name="Bob", age=28)

# Save nodes
alice.save(mg)
bob.save(mg)

# Create relationship (Alice)-[KNOWS]->(Bob)
rel = (alice >> KNOWS(since=2020) >> bob)
rel.save(mg)

# Query
rows = mg.execute_and_fetch("MATCH (a:Person)-[r:KNOWS]->(b:Person) RETURN a, r, b LIMIT 5")
```
```python
from modaic import Embedder
from modaic.context import Text
from modaic.databases import VectorDatabase, MilvusBackend

# Setup embedder and backend
embedder = Embedder("openai/text-embedding-3-small")
backend = MilvusBackend.from_local("vector.db")  # milvus lite

# Initialize database
vdb = VectorDatabase(backend=backend, embedder=embedder, payload_class=Text)

# Create collection and add records
vdb.create_collection("my_collection", payload_class=Text)
vdb.add_records("my_collection", [Text(text="hello world"), Text(text="modaic makes sharing agents easy")])

# Search
results = vdb.search("my_collection", query="hello", k=3)
top_hit_text = results[0][0].context.text
```

## Architecture
### Agent Types

1. **PrecompiledAgent**: Statically defined agents with explicit configuration
2. **AutoAgent**: Dynamically loaded agents from Modaic Hub or local repositories

### Database Support

| Database Type | Providers | Use Case |
|---------------|-----------|----------|
| **Vector** | Milvus | Semantic search, RAG |
| **SQL** | SQLite, MySQL, PostgreSQL | Structured queries, table storage |

## Examples

### TableRAG Example

The TableRAG example demonstrates a complete RAG pipeline for table-based question answering:

```python
from modaic.precompiled_agent import PrecompiledConfig, PrecompiledAgent
from modaic.context import Table
from modaic.databases import VectorDatabase, SQLDatabase
from modaic.types import Indexer

class TableRAGConfig(PrecompiledConfig):
    k_recall: int = 50
    k_rerank: int = 5

class TableRAGAgent(PrecompiledAgent):
    config: TableRAGConfig # ! Important: config must be annotated with the config class
    
    def __init__(self, config: TableRAGConfig, indexer: Indexer, **kwargs):
        super().__init__(config, **kwargs)
        self.indexer = indexer
        # Initialize DSPy modules for reasoning
    
    def forward(self, user_query: str) -> str:
        # Retrieve relevant tables
        # Generate SQL queries
        # Combine results and provide answer
        pass
```

## Support

For issues and questions:
- GitHub Issues: `https://github.com/modaic-ai/modaic/issues`
- Docs: `https://docs.modaic.dev`
