Metadata-Version: 2.4
Name: ingenious
Version: 0.2.3
Summary: An enterprise-grade Python library for quickly setting up APIs to interact with AI Agents
Project-URL: Homepage, https://github.com/Insight-Services-APAC/ingenious
Project-URL: Documentation, https://insight-services-apac.github.io/ingenious/
Project-URL: Repository, https://github.com/Insight-Services-APAC/ingenious
Project-URL: Issues, https://github.com/Insight-Services-APAC/ingenious/issues
Author-email: John Rampono <john.rampono@insight.com>, Kokko Ng <kokko.ng@insight.com>, Elliot Zhu <elliot.zhu@insight.com>
License: MIT
License-File: LICENSE
Keywords: agent,autogen,azure,fastapi
Classifier: Development Status :: 3 - Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.13
Requires-Dist: aiofiles>=24.1.0
Requires-Dist: autogen-agentchat>=0.5.7
Requires-Dist: autogen-ext>=0.5.7
Requires-Dist: azure-identity>=1.17.1
Requires-Dist: azure-keyvault-secrets>=4.10.0
Requires-Dist: azure-search-documents>=11.5.2
Requires-Dist: azure-storage-blob>=12.25.1
Requires-Dist: chromadb>=1.0.11
Requires-Dist: dependency-injector==4.48.1
Requires-Dist: fastapi==0.115.9
Requires-Dist: flask>=3.1.1
Requires-Dist: jsonpickle==4.1.1
Requires-Dist: markdown>=3.8.2
Requires-Dist: openai>=1.82.0
Requires-Dist: pandas>=2.3.1
Requires-Dist: passlib>=1.7.4
Requires-Dist: psutil>=7.0.0
Requires-Dist: pydantic-settings>=2.10.1
Requires-Dist: pydantic==2.11.5
Requires-Dist: pyodbc>=5.2.0
Requires-Dist: python-dotenv>=1.0.1
Requires-Dist: python-jose>=3.5.0
Requires-Dist: structlog==25.4.0
Requires-Dist: tiktoken>=0.9.0
Requires-Dist: typer==0.16.0
Requires-Dist: uvicorn>=0.35.0
Provides-Extra: ai
Requires-Dist: autogen-agentchat==0.5.7; extra == 'ai'
Requires-Dist: autogen-ext[openai]==0.5.7; extra == 'ai'
Requires-Dist: openai==1.82.0; extra == 'ai'
Provides-Extra: auth
Requires-Dist: bcrypt==4.3.0; extra == 'auth'
Requires-Dist: passlib==1.7.4; extra == 'auth'
Requires-Dist: python-jose[cryptography]==3.5.0; extra == 'auth'
Provides-Extra: azure
Requires-Dist: azure-core==1.34.0; extra == 'azure'
Requires-Dist: azure-cosmos==4.9.0; extra == 'azure'
Requires-Dist: azure-identity==1.17.1; extra == 'azure'
Requires-Dist: azure-keyvault==4.2.0; extra == 'azure'
Requires-Dist: azure-search-documents==11.5.2; extra == 'azure'
Requires-Dist: azure-storage-blob==12.25.1; extra == 'azure'
Provides-Extra: azure-full
Requires-Dist: aiosqlite==0.21.0; extra == 'azure-full'
Requires-Dist: autogen-agentchat==0.5.7; extra == 'azure-full'
Requires-Dist: autogen-ext[openai]==0.5.7; extra == 'azure-full'
Requires-Dist: azure-core==1.34.0; extra == 'azure-full'
Requires-Dist: azure-cosmos==4.9.0; extra == 'azure-full'
Requires-Dist: azure-identity==1.17.1; extra == 'azure-full'
Requires-Dist: azure-keyvault==4.2.0; extra == 'azure-full'
Requires-Dist: azure-search-documents==11.5.2; extra == 'azure-full'
Requires-Dist: azure-storage-blob==12.25.1; extra == 'azure-full'
Requires-Dist: bcrypt==4.3.0; extra == 'azure-full'
Requires-Dist: fastapi-cli==0.0.7; extra == 'azure-full'
Requires-Dist: flask==3.1.1; extra == 'azure-full'
Requires-Dist: jinja2==3.1.6; extra == 'azure-full'
Requires-Dist: openai==1.82.0; extra == 'azure-full'
Requires-Dist: passlib==1.7.4; extra == 'azure-full'
Requires-Dist: psutil==7.0.0; extra == 'azure-full'
Requires-Dist: pyodbc==5.2.0; extra == 'azure-full'
Requires-Dist: python-dotenv==1.0.1; extra == 'azure-full'
Requires-Dist: python-jose[cryptography]==3.5.0; extra == 'azure-full'
Provides-Extra: chunk
Requires-Dist: ijson==3.2.3; extra == 'chunk'
Requires-Dist: jsonlines==3.1.0; extra == 'chunk'
Requires-Dist: langchain-experimental==0.3.4; extra == 'chunk'
Requires-Dist: langchain-openai==0.3.0; extra == 'chunk'
Requires-Dist: langchain-text-splitters==0.3.0; extra == 'chunk'
Requires-Dist: regex==2024.11.6; extra == 'chunk'
Requires-Dist: xxhash==3.5.0; extra == 'chunk'
Provides-Extra: core
Requires-Dist: aiosqlite==0.21.0; extra == 'core'
Requires-Dist: fastapi-cli==0.0.7; extra == 'core'
Requires-Dist: jinja2==3.1.6; extra == 'core'
Requires-Dist: python-dotenv==1.0.1; extra == 'core'
Provides-Extra: database
Requires-Dist: psutil==7.0.0; extra == 'database'
Requires-Dist: pyodbc==5.2.0; extra == 'database'
Provides-Extra: dataprep
Requires-Dist: backoff==2.2.0; extra == 'dataprep'
Requires-Dist: python-dotenv==1.0.1; extra == 'dataprep'
Requires-Dist: scrapfly-sdk==0.8.23; extra == 'dataprep'
Provides-Extra: development
Requires-Dist: ipython==9.2.0; extra == 'development'
Provides-Extra: document-advanced
Requires-Dist: pdfminer-six==20250506; extra == 'document-advanced'
Requires-Dist: unstructured[all-docs]==0.17.2; extra == 'document-advanced'
Provides-Extra: document-processing
Requires-Dist: azure-ai-documentintelligence==1.0.2; extra == 'document-processing'
Requires-Dist: psutil==7.0.0; extra == 'document-processing'
Requires-Dist: pymupdf==1.26.1; extra == 'document-processing'
Provides-Extra: full
Requires-Dist: aiosqlite==0.21.0; extra == 'full'
Requires-Dist: autogen-agentchat==0.5.7; extra == 'full'
Requires-Dist: autogen-ext[openai]==0.5.7; extra == 'full'
Requires-Dist: azure-ai-documentintelligence==1.0.2; extra == 'full'
Requires-Dist: azure-core==1.34.0; extra == 'full'
Requires-Dist: azure-cosmos==4.9.0; extra == 'full'
Requires-Dist: azure-identity==1.17.1; extra == 'full'
Requires-Dist: azure-keyvault==4.2.0; extra == 'full'
Requires-Dist: azure-search-documents==11.5.2; extra == 'full'
Requires-Dist: azure-storage-blob==12.25.1; extra == 'full'
Requires-Dist: backoff==2.2.0; extra == 'full'
Requires-Dist: bcrypt==4.3.0; extra == 'full'
Requires-Dist: chromadb==1.0.11; extra == 'full'
Requires-Dist: fastapi-cli==0.0.7; extra == 'full'
Requires-Dist: flask==3.1.1; extra == 'full'
Requires-Dist: jinja2==3.1.6; extra == 'full'
Requires-Dist: matplotlib==3.10.3; extra == 'full'
Requires-Dist: openai==1.82.0; extra == 'full'
Requires-Dist: passlib==1.7.4; extra == 'full'
Requires-Dist: psutil==7.0.0; extra == 'full'
Requires-Dist: pymupdf==1.26.1; extra == 'full'
Requires-Dist: pyodbc==5.2.0; extra == 'full'
Requires-Dist: python-dotenv==1.0.1; extra == 'full'
Requires-Dist: python-jose[cryptography]==3.5.0; extra == 'full'
Requires-Dist: scrapfly-sdk==0.8.23; extra == 'full'
Requires-Dist: seaborn==0.13.2; extra == 'full'
Requires-Dist: sentence-transformers==5.0.0; extra == 'full'
Provides-Extra: knowledge-base
Requires-Dist: aiosqlite==0.21.0; extra == 'knowledge-base'
Requires-Dist: autogen-agentchat==0.5.7; extra == 'knowledge-base'
Requires-Dist: autogen-ext[openai]==0.5.7; extra == 'knowledge-base'
Requires-Dist: chromadb==1.0.11; extra == 'knowledge-base'
Requires-Dist: fastapi-cli==0.0.7; extra == 'knowledge-base'
Requires-Dist: jinja2==3.1.6; extra == 'knowledge-base'
Requires-Dist: openai==1.82.0; extra == 'knowledge-base'
Requires-Dist: python-dotenv==1.0.1; extra == 'knowledge-base'
Requires-Dist: sentence-transformers==5.0.0; extra == 'knowledge-base'
Provides-Extra: minimal
Provides-Extra: ml
Requires-Dist: chromadb==1.0.11; extra == 'ml'
Requires-Dist: sentence-transformers==5.0.0; extra == 'ml'
Provides-Extra: standard
Requires-Dist: aiosqlite==0.21.0; extra == 'standard'
Requires-Dist: autogen-agentchat==0.5.7; extra == 'standard'
Requires-Dist: autogen-ext[openai]==0.5.7; extra == 'standard'
Requires-Dist: bcrypt==4.3.0; extra == 'standard'
Requires-Dist: fastapi-cli==0.0.7; extra == 'standard'
Requires-Dist: jinja2==3.1.6; extra == 'standard'
Requires-Dist: openai==1.82.0; extra == 'standard'
Requires-Dist: passlib==1.7.4; extra == 'standard'
Requires-Dist: psutil==7.0.0; extra == 'standard'
Requires-Dist: pyodbc==5.2.0; extra == 'standard'
Requires-Dist: python-dotenv==1.0.1; extra == 'standard'
Requires-Dist: python-jose[cryptography]==3.5.0; extra == 'standard'
Provides-Extra: test
Requires-Dist: httpx==0.28.1; extra == 'test'
Requires-Dist: hypothesis==6.136.2; extra == 'test'
Requires-Dist: jsonpickle==4.1.1; extra == 'test'
Requires-Dist: mypy==1.16.1; extra == 'test'
Requires-Dist: pip-audit==2.9.0; extra == 'test'
Requires-Dist: pre-commit==4.2.0; extra == 'test'
Requires-Dist: pytest-asyncio==0.26.0; extra == 'test'
Requires-Dist: pytest-cov==6.1.1; extra == 'test'
Requires-Dist: pytest-mock==3.14.0; extra == 'test'
Requires-Dist: pytest-timeout==2.4.0; extra == 'test'
Requires-Dist: pytest==8.3.5; extra == 'test'
Requires-Dist: reportlab==4.4.2; extra == 'test'
Requires-Dist: ruff==0.11.10; extra == 'test'
Requires-Dist: twine==6.0.0; extra == 'test'
Requires-Dist: types-markdown==3.8.0.20250708; extra == 'test'
Requires-Dist: types-psutil==7.0.0.20250601; extra == 'test'
Requires-Dist: types-pyyaml==6.0.12.20250516; extra == 'test'
Requires-Dist: types-requests==2.32.4.20250611; extra == 'test'
Requires-Dist: vulture==2.14; extra == 'test'
Provides-Extra: ui
Requires-Dist: flask==3.1.1; extra == 'ui'
Provides-Extra: visualization
Requires-Dist: matplotlib==3.10.3; extra == 'visualization'
Requires-Dist: seaborn==0.13.2; extra == 'visualization'
Description-Content-Type: text/markdown

# Insight Ingenious

[![Version](https://img.shields.io/badge/version-0.2.2-blue.svg)](https://github.com/Insight-Services-APAC/ingenious)
[![Python](https://img.shields.io/badge/python-3.13+-green.svg)](https://www.python.org/downloads/)
[![Ask DeepWiki](https://deepwiki.com/badge.svg)](https://deepwiki.com/Insight-Services-APAC/ingenious)
[![License](https://img.shields.io/badge/license-MIT-purple.svg)](LICENSE)

Ingenious is a tool for quickly setting up APIs to interact with AI Agents. It features multi-agent conversation flows using Microsoft's AutoGen, JWT authentication, and comprehensive Azure service integrations.

## Quick Start

Get up and running in 5 minutes with Azure OpenAI!

### Prerequisites
- Python 3.13 or higher (required - earlier versions are not supported)
- Azure OpenAI API credentials
- [uv package manager](https://docs.astral.sh/uv/)

### 5-Minute Setup

1. **Install and Initialize**:
    ```bash
    # Navigate to your desired project directory first
    cd /path/to/your/project

    # Set up the uv project
    uv init

    # Choose installation based on features needed
    uv add "ingenious[azure-full]" # Recommended: Full Azure integration (core, auth, azure, ai, database, ui)
    # OR
    uv add "ingenious[standard]" # for local testing: includes SQL agent support (core, auth, ai, database)

    # Initialize project in the current directory
    uv run ingen init
    ```

2. **Configure Credentials**:
    Create a `.env` file with your Azure OpenAI credentials:
    ```bash
    # Create .env file in current directory
    touch .env

    # Edit .env file with your actual credentials
    ```

    **Required configuration (add to .env file)**:
    ```bash
    # Model Configuration (only INGENIOUS_* variables are used by the system)
    INGENIOUS_MODELS__0__MODEL=gpt-4.1-nano
    INGENIOUS_MODELS__0__API_TYPE=rest
    INGENIOUS_MODELS__0__API_VERSION=2024-12-01-preview
    INGENIOUS_MODELS__0__DEPLOYMENT=your-gpt4.1-nano-deployment-name
    INGENIOUS_MODELS__0__API_KEY=your-actual-api-key-here
    INGENIOUS_MODELS__0__BASE_URL=https://your-resource.openai.azure.com/

    # Basic required settings
    INGENIOUS_CHAT_SERVICE__TYPE=multi_agent
    INGENIOUS_CHAT_HISTORY__DATABASE_TYPE=sqlite
    INGENIOUS_CHAT_HISTORY__DATABASE_PATH=./.tmp/chat_history.db
    INGENIOUS_CHAT_HISTORY__MEMORY_PATH=./.tmp

    # Optional: Authentication settings (enabled by default)
    # INGENIOUS_WEB_CONFIGURATION__ENABLE_AUTHENTICATION=false  # To disable auth
    ```

3. **Validate Configuration**:
    ```bash
    uv run ingen validate  # Check configuration before starting
    ```

    **If validation fails with port conflicts**:
    ```bash
    # Check if validation passes with different port
    INGENIOUS_WEB_CONFIGURATION__PORT=8001 uv run ingen validate

    # Or update your .env file before validating:
    echo "INGENIOUS_WEB_CONFIGURATION__PORT=8001" >> .env
    uv run ingen validate
    ```

    > **⚠️ BREAKING CHANGE**: Ingenious now uses **pydantic-settings** for configuration via environment variables. Legacy YAML configuration files (`config.yml`, `profiles.yml`) are **no longer supported** and must be migrated to environment variables with `INGENIOUS_` prefixes. Use the migration script:
    > ```bash
    > uv run python scripts/migrate_config.py --yaml-file config.yml --output .env
    > uv run python scripts/migrate_config.py --yaml-file profiles.yml --output .env.profiles
    > ```

4. **Start the Server**:
    ```bash
    # Start server on port 8000 (recommended for development)
    uv run ingen serve --port 8000

    # Additional options:
    # --host 0.0.0.0         # Bind host (default: 0.0.0.0)
    # --port                 # Port to bind (default: 80 or $WEB_PORT env var)
    # --config config.yml    # Legacy config file (deprecated - use environment variables)
    # --profile production   # Legacy profile (deprecated - use environment variables)
    ```

5. **Verify Health**:
    ```bash
    # Check server health
    curl http://localhost:8000/api/v1/health
    ```

6. **Test with Core Workflows**:

    Create test files to avoid JSON escaping issues:
    ```bash
    # Create test files for each workflow
    echo '{"user_prompt": "Analyze this customer feedback: Great product", "conversation_flow": "classification-agent"}' > test_classification.json
    echo '{"user_prompt": "Search for documentation about setup", "conversation_flow": "knowledge-base-agent"}' > test_knowledge.json
    echo '{"user_prompt": "Show me all tables in the database", "conversation_flow": "sql-manipulation-agent"}' > test_sql.json

    # Test each workflow
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_classification.json
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_knowledge.json
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_sql.json
    ```

**Expected Responses**:
- **Successful classification-agent response**: JSON with message analysis and categories
- **Successful knowledge-base-agent response**: JSON with relevant information retrieved (may indicate empty knowledge base initially)
- **Successful sql-manipulation-agent response**: JSON with query results or confirmation

**If you see error responses**, check the troubleshooting section above or the detailed [troubleshooting guide](docs/getting-started/troubleshooting.md).

That's it! You should see a JSON response with AI analysis of the input.

**Next Steps - Test Additional Workflows**:

7. **Test bike-insights Workflow (Requires `ingen init` first)**:

    The `bike-insights` workflow is part of the project template and must be initialized first:
    ```bash
    # First initialize project to get bike-insights workflow
    uv run ingen init

    # Create bike-insights test data file
    # IMPORTANT: bike-insights requires JSON data in the user_prompt field (double-encoded JSON)
    # Method 1: Use printf for precise formatting (recommended)
    printf '%s\n' '{
      "user_prompt": "{\"revision_id\": \"test-v1\", \"identifier\": \"test-001\", \"stores\": [{\"name\": \"Test Store\", \"location\": \"NSW\", \"bike_sales\": [{\"product_code\": \"MB-TREK-2021-XC\", \"quantity_sold\": 2, \"sale_date\": \"2023-04-01\", \"year\": 2023, \"month\": \"April\", \"customer_review\": {\"rating\": 4.5, \"comment\": \"Great bike\"}}], \"bike_stock\": []}]}",
      "conversation_flow": "bike-insights"
    }' > test_bike_insights.json

    # Method 2: Alternative using echo (simpler but watch for shell differences)
    echo '{
      "user_prompt": "{\"revision_id\": \"test-v1\", \"identifier\": \"test-001\", \"stores\": [{\"name\": \"Test Store\", \"location\": \"NSW\", \"bike_sales\": [{\"product_code\": \"MB-TREK-2021-XC\", \"quantity_sold\": 2, \"sale_date\": \"2023-04-01\", \"year\": 2023, \"month\": \"April\", \"customer_review\": {\"rating\": 4.5, \"comment\": \"Great bike\"}}], \"bike_stock\": []}]}",
      "conversation_flow": "bike-insights"
    }' > test_bike_insights.json

    # Method 3: If heredoc is preferred, ensure proper EOF placement
    cat > test_bike_insights.json << 'EOF'
    {
    "user_prompt": "{\"revision_id\": \"test-v1\", \"identifier\": \"test-001\", \"stores\": [{\"name\": \"Test Store\", \"location\": \"NSW\", \"bike_sales\": [{\"product_code\": \"MB-TREK-2021-XC\", \"quantity_sold\": 2, \"sale_date\": \"2023-04-01\", \"year\": 2023, \"month\": \"April\", \"customer_review\": {\"rating\": 4.5, \"comment\": \"Great bike\"}}], \"bike_stock\": []}]}",
    "conversation_flow": "bike-insights"
    }
    EOF

    # Test bike-insights workflow
    curl -X POST http://localhost:8000/api/v1/chat -H "Content-Type: application/json" -d @test_bike_insights.json
    ```

    **Expected bike-insights response**: JSON with comprehensive bike sales analysis from multiple agents (fiscal analysis, customer sentiment, summary, and bike lookup).

**Important Notes**:
- **Core Library Workflows** (`classification-agent`, `knowledge-base-agent`, `sql-manipulation-agent`) are always available and accept simple text prompts
- **Template Workflows** like `bike-insights` require JSON-formatted data with specific fields and are only available after running `ingen init`
- The `bike-insights` workflow is the recommended "Hello World" example for new users

## Workflow Categories

Insight Ingenious provides multiple conversation workflows with different configuration requirements:

### Core Library Workflows (Always Available)
These workflows are built into the Ingenious library and available immediately:

- `classification-agent` - Simple text classification and routing to categories (minimal config required)
- `knowledge-base-agent` - Search and retrieve information from knowledge bases (requires Azure Search or uses local ChromaDB by default)
- `sql-manipulation-agent` - Execute SQL queries based on natural language (requires Azure SQL or uses local SQLite by default)

> **Note**: Core workflows support both hyphenated (`classification-agent`) and underscored (`classification_agent`) naming formats for backward compatibility.

### Template Workflows (Created by `ingen init`)
These workflows are provided as examples in the project template when you run `ingen init`:

- `bike-insights` - Comprehensive bike sales analysis showcasing multi-agent coordination (**ONLY available after `ingen init`** - not included in the core library)

> **Important**: The `bike-insights` workflow is NOT part of the core library. It's a template example that's created when you initialize a new project with `ingen init`. This is the recommended "Hello World" example for learning how to build custom workflows.

## Troubleshooting

For common issues like port conflicts, configuration errors, or workflow problems, see the [detailed troubleshooting guide](docs/getting-started/troubleshooting.md).

## Documentation

For detailed documentation, see the [docs](https://insight-services-apac.github.io/ingenious/).

## Contributing

Contributions are welcome! Please see [CONTRIBUTING.md](https://github.com/Insight-Services-APAC/ingenious/blob/main/CONTRIBUTING.md) for guidelines.

## License

This project is licensed under the terms specified in the [LICENSE](https://github.com/Insight-Services-APAC/ingenious/blob/main/LICENSE) file.
