proompt


Nameproompt JSON
Version 0.1.1 PyPI version JSON
download
home_pageNone
SummaryObject-oriented prompting for Python
upload_time2025-10-07 13:31:17
maintainerhttps://github.com/Burhan-Q
docs_urlNone
authorBurhan Qaddoumi
requires_python>=3.12
licenseNone
keywords ai prompting prompts object oriented ai agent prompt toolkit devtools developer tools llm prompt code tools structure
VCS
bugtrack_url
requirements No requirements were recorded.
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Proompt

**Object-oriented prompt engineering for LLMs**

Stop wrestling with string templates. Build composable, testable, and maintainable prompts using object-oriented design patterns.

```python
# Instead of this messy string concatenation...
prompt = f"""
Analyze this data:
{open('data.csv').read()}

Using these functions:
{str(my_functions)}
"""

# Write clean, composable prompts like this:
from proompt.data import (
    CsvDataProvider,
    FileDataProvider,
    SqliteProvider,
)
from proompt.base.context import ToolContext

section = PromptSection(
    context=ToolContext(my_function),
    CsvDataProvider("data.csv"),
    FileDataProvider("file.txt"),
    SqliteProvider("data.db"),
)
```

## Project Overview

Proompt is organized into a clean, modular structure:

```
proompt/
├── src/proompt/
│   ├── base/              # Abstract base classes
│   │   ├── context.py
│   │   ├── prompt.py
│   │   └── provider.py
│   └── data.py            # Concrete data provider examples
├── examples/              # Complete usage examples
│   ├── 01-simple_quarterly_review.py
│   ├── 02-intermediate_quarterly_review.py
│   └── 03-advanced_quarterly_review.py
└── tests/                 # Unit tests
```

**Key Components:**
- **Base classes** define contracts for providers, contexts, and prompts
- **Data providers** concrete examples of how to extend `DataProviders`
- **Examples** show real-world implementations from simple to advanced
- **Tests** ensure reliability and demonstrate usage patterns

## Why Proompt?

**Traditional string-based prompts are painful:**
- 🔥 Hard to compose and maintain large prompts
- 🐛 No separation between data and prompt logic
- 🚫 Difficult to test individual components
- 🔄 Can't reuse prompt components across projects
- ⚠️ No type safety or validation

**Proompt solves this with:**
- ✅ **Composable objects** - Build prompts from reusable components
- ✅ **Data providers** - Clean separation of data sources and prompt logic
- ✅ **Type safety** - Abstract base classes enforce contracts
- ✅ **Testable** - Unit test each component independently
- ✅ **Extensible** - Easy to create custom providers and contexts
- ✅ **Async ready** - Support for both sync and async operations

## Quick Start

```bash
uv pip install proompt
```

```python
from proompt.data import FileDataProvider

# Read a file and inject it into your prompt
provider = FileDataProvider("data.txt")
content = provider.run()  # Returns file contents as string

print(f"Analyze the data:\n{content}")
```

## Core Concepts

A few example classes for extending the `DataProvider` class can be found in the `proompt.data` module.

### 🔌 Providers - Inject Data from Any Source

Providers fetch data from external sources and format it for LLM consumption:

```python
from proompt.data import CsvDataProvider, SqliteProvider

# CSV data as markdown tables
csv_provider = CsvDataProvider("sales_data.csv")
print(csv_provider.run())
# | Product | Sales | Region |
# | ------- | ----- | ------ |
# | Widget  | 1000  | North  |

# Database queries as markdown tables
db_provider = SqliteProvider(
    "company.db",
    'SELECT * FROM employees WHERE department = "Engineering"'
)
print(db_provider.run())
# | name  | role      | salary |
# | ----- | --------- | ------ |
# | Alice | Developer | 85000  |
```

### 🛠️ Tool Context - Document Functions for LLMs

Automatically generate function documentation that LLMs can understand:

```python
from proompt.base.context import ToolContext

def calculate_tax(income: float, rate: float = 0.25) -> float:
    """Calculate tax owed on income."""
    return income * rate

tool_ctx = ToolContext(calculate_tax)
print(tool_ctx.render())
# Name: calculate_tax
# Description: Calculate tax owed on income.
# Arguments: income: float, rate: float = 0.25
# Returns: float
# Usage: Reference description for usage.
```

### 📝 Prompt Sections - Compose Complex Prompts

Combine providers, tools, and context into reusable sections:

```python
from textwrap import dedent
from proompt.base.prompt import PromptSection

class DataAnalysisSection(PromptSection):

    def formatter(self, instruction: str) -> str:
        data = "\n\n".join(p.run() for p in self.providers)
        tools = "\n\n".join(str(t) for t in self.tools)

        return dedent(f"""
        {instruction}

        Available Data Providers:
        {data}

        Available Tools:
        {tools}
        """)

    def render(self) -> str:
        return self.formatter("Analyze the provided data")

# Use it
section = DataAnalysisSection(
    context=context,  # Use Context to pass dynamic info
    tools=[ToolContext(calculate_tax)],
    CsvDataProvider("metrics.csv"),  # accepts any number of Providers
)

prompt = str(section)  # Ready for your LLM
```

## Data Providers

### File Provider
```python
from proompt.data import FileDataProvider

# Read any text file
provider = FileDataProvider("config.yaml")
content = provider.run().  # raw string content
```

**NOTE**: for structured YAML parsing, extend `DataProvider` to create `YamlProvider` class

### CSV Provider
```python
from proompt.data import CsvDataProvider

# Automatically converts CSV to markdown tables
provider = CsvDataProvider("data.csv")
table = provider.run()  # Returns formatted markdown table
```

See `proompt.data.TableData` and `proompt.data.to_markdown_table()` for conversion.

### SQLite Provider
```python
from proompt.data import SqliteProvider

# Execute SQL queries, get markdown tables
provider = SqliteProvider(
    database_path="app.db",
    query="SELECT name, email FROM users WHERE active = 1",
    table_name="users"  # Optional, for better context
)

# Async support; NOTE the async only runs sync method .run()
result = await provider.arun()
```

**NOTE**: A _true_ asynchronous method would need to be defined when extending the `DataProvider` class.

## Advanced Usage

### Custom Providers

Creating custom providers is straightforward:

```python
from proompt.base.provider import BaseProvider
import requests

class ApiProvider(BaseProvider, str):

    def __init__(self, url: str, api_key: str):
        self.url = url
        self.api_key = api_key

    @property
    def name(self) -> str:
        return f"API Provider for {self.url}"

    @property
    def provider_ctx(self) -> str:
        return f"Fetches data from REST API at {self.url}"
        # NOTE: would be useful to include available endpoints

    def run(self, endpoint: str) -> str:
        response = requests.get(
            f"{self.url}/{endpoint}",
            headers={"Authorization": f"Bearer {self.api_key}"}
        )
        return response.json()

# Use your custom provider
api = ApiProvider("https://api.example.com", "your-key")
data = api.run("users")
```

### Data Transformation

Convert any data format to LLM-friendly markdown:

```python
from proompt.data import TableData

# From dictionaries
data = [
    {"name": "Alice", "role": "Engineer", "salary": 85000},
    {"name": "Bob", "role": "Designer", "salary": 75000}
]

table = TableData.from_dicts(data)
markdown = table.to_md()
print(markdown)
# | name  | role     | salary |
# | ----- | -------- | ------ |
# | Alice | Engineer | 85000  |
# | Bob   | Designer | 75000  |
```

## API Reference

### Core Classes

- **`BaseProvider`** - Abstract base for all data providers
- **`Context`** - Abstract base for prompt contexts
- **`ToolContext`** - Documents functions for LLM consumption
- **`PromptSection`** - Composable prompt sections
- **`BasePrompt`** - Full prompt composition

### Concrete Providers

- **`FileDataProvider`** - Read text files
- **`CsvDataProvider`** - Read CSV files as markdown tables
- **`SqliteProvider`** - Execute SQL queries as markdown tables

### Utilities

- **`TableData`** - Convert various formats to markdown tables
- **`to_markdown_table()`** - Low-level table formatting

## Why Object-Oriented Prompts?

**Better Organization**
```python
# Instead of managing giant prompt strings
SYSTEM_PROMPT = """You are an assistant..."""
DATA_SECTION = """Here is the data: {data}"""
TOOL_SECTION = """Available tools: {tools}"""

# Compose from organized, testable objects
prompt = ChatPrompt(
    SystemSection("You are an assistant..."),
    DataSection(providers=[csv_provider, db_provider]),
    ToolSection(tools=[calculator, parser])
)
```

**Easier Testing**
```python
# Test individual components
def test_csv_provider():
    provider = CsvDataProvider("test.csv")
    result = provider.run()
    assert "| Name |" in result

def test_tool_context():
    ctx = ToolContext(my_function)
    assert "my_function" in ctx.render()
```

**Reusable Components**
```python
# Define once, use everywhere
analysis_section = DataAnalysisSection(
    providers=[CsvDataProvider("metrics.csv")]
)

# Reuse in different prompts
customer_prompt = CustomerPrompt(analysis_section, ...)
admin_prompt = AdminPrompt(analysis_section, ...)
```

## Contributing

Coming soon

<!--

Proompt is designed to be extensible. Common extension points:

1. **Custom Providers** - Connect to new data sources
2. **Custom Contexts** - New ways to document tools/functions
3. **Custom Sections** - Domain-specific prompt components
4. **Custom Prompts** - Full prompt templates for specific use cases


See the [Contributing Guide](CONTRIBUTING.md) for details.
-->

            

Raw data

            {
    "_id": null,
    "home_page": null,
    "name": "proompt",
    "maintainer": "https://github.com/Burhan-Q",
    "docs_url": null,
    "requires_python": ">=3.12",
    "maintainer_email": null,
    "keywords": "ai, prompting, prompts, object oriented, ai agent, prompt toolkit, devtools, developer tools, llm, prompt, code tools, structure",
    "author": "Burhan Qaddoumi",
    "author_email": null,
    "download_url": "https://files.pythonhosted.org/packages/9d/79/eb5b594aa21fa06e8e24c7d77a3a495cbee65ddf4fd29e8cd1e2f3086aea/proompt-0.1.1.tar.gz",
    "platform": null,
    "description": "# Proompt\n\n**Object-oriented prompt engineering for LLMs**\n\nStop wrestling with string templates. Build composable, testable, and maintainable prompts using object-oriented design patterns.\n\n```python\n# Instead of this messy string concatenation...\nprompt = f\"\"\"\nAnalyze this data:\n{open('data.csv').read()}\n\nUsing these functions:\n{str(my_functions)}\n\"\"\"\n\n# Write clean, composable prompts like this:\nfrom proompt.data import (\n    CsvDataProvider,\n    FileDataProvider,\n    SqliteProvider,\n)\nfrom proompt.base.context import ToolContext\n\nsection = PromptSection(\n    context=ToolContext(my_function),\n    CsvDataProvider(\"data.csv\"),\n    FileDataProvider(\"file.txt\"),\n    SqliteProvider(\"data.db\"),\n)\n```\n\n## Project Overview\n\nProompt is organized into a clean, modular structure:\n\n```\nproompt/\n\u251c\u2500\u2500 src/proompt/\n\u2502   \u251c\u2500\u2500 base/              # Abstract base classes\n\u2502   \u2502   \u251c\u2500\u2500 context.py\n\u2502   \u2502   \u251c\u2500\u2500 prompt.py\n\u2502   \u2502   \u2514\u2500\u2500 provider.py\n\u2502   \u2514\u2500\u2500 data.py            # Concrete data provider examples\n\u251c\u2500\u2500 examples/              # Complete usage examples\n\u2502   \u251c\u2500\u2500 01-simple_quarterly_review.py\n\u2502   \u251c\u2500\u2500 02-intermediate_quarterly_review.py\n\u2502   \u2514\u2500\u2500 03-advanced_quarterly_review.py\n\u2514\u2500\u2500 tests/                 # Unit tests\n```\n\n**Key Components:**\n- **Base classes** define contracts for providers, contexts, and prompts\n- **Data providers** concrete examples of how to extend `DataProviders`\n- **Examples** show real-world implementations from simple to advanced\n- **Tests** ensure reliability and demonstrate usage patterns\n\n## Why Proompt?\n\n**Traditional string-based prompts are painful:**\n- \ud83d\udd25 Hard to compose and maintain large prompts\n- \ud83d\udc1b No separation between data and prompt logic\n- \ud83d\udeab Difficult to test individual components\n- \ud83d\udd04 Can't reuse prompt components across projects\n- \u26a0\ufe0f No type safety or validation\n\n**Proompt solves this with:**\n- \u2705 **Composable objects** - Build prompts from reusable components\n- \u2705 **Data providers** - Clean separation of data sources and prompt logic\n- \u2705 **Type safety** - Abstract base classes enforce contracts\n- \u2705 **Testable** - Unit test each component independently\n- \u2705 **Extensible** - Easy to create custom providers and contexts\n- \u2705 **Async ready** - Support for both sync and async operations\n\n## Quick Start\n\n```bash\nuv pip install proompt\n```\n\n```python\nfrom proompt.data import FileDataProvider\n\n# Read a file and inject it into your prompt\nprovider = FileDataProvider(\"data.txt\")\ncontent = provider.run()  # Returns file contents as string\n\nprint(f\"Analyze the data:\\n{content}\")\n```\n\n## Core Concepts\n\nA few example classes for extending the `DataProvider` class can be found in the `proompt.data` module.\n\n### \ud83d\udd0c Providers - Inject Data from Any Source\n\nProviders fetch data from external sources and format it for LLM consumption:\n\n```python\nfrom proompt.data import CsvDataProvider, SqliteProvider\n\n# CSV data as markdown tables\ncsv_provider = CsvDataProvider(\"sales_data.csv\")\nprint(csv_provider.run())\n# | Product | Sales | Region |\n# | ------- | ----- | ------ |\n# | Widget  | 1000  | North  |\n\n# Database queries as markdown tables\ndb_provider = SqliteProvider(\n    \"company.db\",\n    'SELECT * FROM employees WHERE department = \"Engineering\"'\n)\nprint(db_provider.run())\n# | name  | role      | salary |\n# | ----- | --------- | ------ |\n# | Alice | Developer | 85000  |\n```\n\n### \ud83d\udee0\ufe0f Tool Context - Document Functions for LLMs\n\nAutomatically generate function documentation that LLMs can understand:\n\n```python\nfrom proompt.base.context import ToolContext\n\ndef calculate_tax(income: float, rate: float = 0.25) -> float:\n    \"\"\"Calculate tax owed on income.\"\"\"\n    return income * rate\n\ntool_ctx = ToolContext(calculate_tax)\nprint(tool_ctx.render())\n# Name: calculate_tax\n# Description: Calculate tax owed on income.\n# Arguments: income: float, rate: float = 0.25\n# Returns: float\n# Usage: Reference description for usage.\n```\n\n### \ud83d\udcdd Prompt Sections - Compose Complex Prompts\n\nCombine providers, tools, and context into reusable sections:\n\n```python\nfrom textwrap import dedent\nfrom proompt.base.prompt import PromptSection\n\nclass DataAnalysisSection(PromptSection):\n\n    def formatter(self, instruction: str) -> str:\n        data = \"\\n\\n\".join(p.run() for p in self.providers)\n        tools = \"\\n\\n\".join(str(t) for t in self.tools)\n\n        return dedent(f\"\"\"\n        {instruction}\n\n        Available Data Providers:\n        {data}\n\n        Available Tools:\n        {tools}\n        \"\"\")\n\n    def render(self) -> str:\n        return self.formatter(\"Analyze the provided data\")\n\n# Use it\nsection = DataAnalysisSection(\n    context=context,  # Use Context to pass dynamic info\n    tools=[ToolContext(calculate_tax)],\n    CsvDataProvider(\"metrics.csv\"),  # accepts any number of Providers\n)\n\nprompt = str(section)  # Ready for your LLM\n```\n\n## Data Providers\n\n### File Provider\n```python\nfrom proompt.data import FileDataProvider\n\n# Read any text file\nprovider = FileDataProvider(\"config.yaml\")\ncontent = provider.run().  # raw string content\n```\n\n**NOTE**: for structured YAML parsing, extend `DataProvider` to create `YamlProvider` class\n\n### CSV Provider\n```python\nfrom proompt.data import CsvDataProvider\n\n# Automatically converts CSV to markdown tables\nprovider = CsvDataProvider(\"data.csv\")\ntable = provider.run()  # Returns formatted markdown table\n```\n\nSee `proompt.data.TableData` and `proompt.data.to_markdown_table()` for conversion.\n\n### SQLite Provider\n```python\nfrom proompt.data import SqliteProvider\n\n# Execute SQL queries, get markdown tables\nprovider = SqliteProvider(\n    database_path=\"app.db\",\n    query=\"SELECT name, email FROM users WHERE active = 1\",\n    table_name=\"users\"  # Optional, for better context\n)\n\n# Async support; NOTE the async only runs sync method .run()\nresult = await provider.arun()\n```\n\n**NOTE**: A _true_ asynchronous method would need to be defined when extending the `DataProvider` class.\n\n## Advanced Usage\n\n### Custom Providers\n\nCreating custom providers is straightforward:\n\n```python\nfrom proompt.base.provider import BaseProvider\nimport requests\n\nclass ApiProvider(BaseProvider, str):\n\n    def __init__(self, url: str, api_key: str):\n        self.url = url\n        self.api_key = api_key\n\n    @property\n    def name(self) -> str:\n        return f\"API Provider for {self.url}\"\n\n    @property\n    def provider_ctx(self) -> str:\n        return f\"Fetches data from REST API at {self.url}\"\n        # NOTE: would be useful to include available endpoints\n\n    def run(self, endpoint: str) -> str:\n        response = requests.get(\n            f\"{self.url}/{endpoint}\",\n            headers={\"Authorization\": f\"Bearer {self.api_key}\"}\n        )\n        return response.json()\n\n# Use your custom provider\napi = ApiProvider(\"https://api.example.com\", \"your-key\")\ndata = api.run(\"users\")\n```\n\n### Data Transformation\n\nConvert any data format to LLM-friendly markdown:\n\n```python\nfrom proompt.data import TableData\n\n# From dictionaries\ndata = [\n    {\"name\": \"Alice\", \"role\": \"Engineer\", \"salary\": 85000},\n    {\"name\": \"Bob\", \"role\": \"Designer\", \"salary\": 75000}\n]\n\ntable = TableData.from_dicts(data)\nmarkdown = table.to_md()\nprint(markdown)\n# | name  | role     | salary |\n# | ----- | -------- | ------ |\n# | Alice | Engineer | 85000  |\n# | Bob   | Designer | 75000  |\n```\n\n## API Reference\n\n### Core Classes\n\n- **`BaseProvider`** - Abstract base for all data providers\n- **`Context`** - Abstract base for prompt contexts\n- **`ToolContext`** - Documents functions for LLM consumption\n- **`PromptSection`** - Composable prompt sections\n- **`BasePrompt`** - Full prompt composition\n\n### Concrete Providers\n\n- **`FileDataProvider`** - Read text files\n- **`CsvDataProvider`** - Read CSV files as markdown tables\n- **`SqliteProvider`** - Execute SQL queries as markdown tables\n\n### Utilities\n\n- **`TableData`** - Convert various formats to markdown tables\n- **`to_markdown_table()`** - Low-level table formatting\n\n## Why Object-Oriented Prompts?\n\n**Better Organization**\n```python\n# Instead of managing giant prompt strings\nSYSTEM_PROMPT = \"\"\"You are an assistant...\"\"\"\nDATA_SECTION = \"\"\"Here is the data: {data}\"\"\"\nTOOL_SECTION = \"\"\"Available tools: {tools}\"\"\"\n\n# Compose from organized, testable objects\nprompt = ChatPrompt(\n    SystemSection(\"You are an assistant...\"),\n    DataSection(providers=[csv_provider, db_provider]),\n    ToolSection(tools=[calculator, parser])\n)\n```\n\n**Easier Testing**\n```python\n# Test individual components\ndef test_csv_provider():\n    provider = CsvDataProvider(\"test.csv\")\n    result = provider.run()\n    assert \"| Name |\" in result\n\ndef test_tool_context():\n    ctx = ToolContext(my_function)\n    assert \"my_function\" in ctx.render()\n```\n\n**Reusable Components**\n```python\n# Define once, use everywhere\nanalysis_section = DataAnalysisSection(\n    providers=[CsvDataProvider(\"metrics.csv\")]\n)\n\n# Reuse in different prompts\ncustomer_prompt = CustomerPrompt(analysis_section, ...)\nadmin_prompt = AdminPrompt(analysis_section, ...)\n```\n\n## Contributing\n\nComing soon\n\n<!--\n\nProompt is designed to be extensible. Common extension points:\n\n1. **Custom Providers** - Connect to new data sources\n2. **Custom Contexts** - New ways to document tools/functions\n3. **Custom Sections** - Domain-specific prompt components\n4. **Custom Prompts** - Full prompt templates for specific use cases\n\n\nSee the [Contributing Guide](CONTRIBUTING.md) for details.\n-->\n",
    "bugtrack_url": null,
    "license": null,
    "summary": "Object-oriented prompting for Python",
    "version": "0.1.1",
    "project_urls": {
        "homepage": "https://github.com/Burhan-Q/proompt",
        "issues": "https://github.com/Burhan-Q/proompt/issues",
        "source": "https://github.com/Burhan-Q/proompt"
    },
    "split_keywords": [
        "ai",
        " prompting",
        " prompts",
        " object oriented",
        " ai agent",
        " prompt toolkit",
        " devtools",
        " developer tools",
        " llm",
        " prompt",
        " code tools",
        " structure"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "0cb0679bf3326b1c3f6ee51555dbfc0462fc725a8fd3a6b9fc17e21ba12288bc",
                "md5": "e2b88985b95efc49bcd071ed42217384",
                "sha256": "c25cd855dc4aa863ef5d21e23fb384148cb36399b5c191bce9d0d5bf95c9d41b"
            },
            "downloads": -1,
            "filename": "proompt-0.1.1-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "e2b88985b95efc49bcd071ed42217384",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.12",
            "size": 13819,
            "upload_time": "2025-10-07T13:31:16",
            "upload_time_iso_8601": "2025-10-07T13:31:16.603903Z",
            "url": "https://files.pythonhosted.org/packages/0c/b0/679bf3326b1c3f6ee51555dbfc0462fc725a8fd3a6b9fc17e21ba12288bc/proompt-0.1.1-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "9d79eb5b594aa21fa06e8e24c7d77a3a495cbee65ddf4fd29e8cd1e2f3086aea",
                "md5": "10a13b5b909ea3139d3f1071798984fc",
                "sha256": "d4fc6ee80d16d00618825348b9cee38f4e7e437e7588e78f42ef400bf6cf9d2f"
            },
            "downloads": -1,
            "filename": "proompt-0.1.1.tar.gz",
            "has_sig": false,
            "md5_digest": "10a13b5b909ea3139d3f1071798984fc",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.12",
            "size": 19647,
            "upload_time": "2025-10-07T13:31:17",
            "upload_time_iso_8601": "2025-10-07T13:31:17.392786Z",
            "url": "https://files.pythonhosted.org/packages/9d/79/eb5b594aa21fa06e8e24c7d77a3a495cbee65ddf4fd29e8cd1e2f3086aea/proompt-0.1.1.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-10-07 13:31:17",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Burhan-Q",
    "github_project": "proompt",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "lcname": "proompt"
}
        
Elapsed time: 1.65633s