Metadata-Version: 2.4
Name: pyflowforge
Version: 0.1.0
Summary: Declarative YAML-first chatbot framework with pluggable intent detection
Project-URL: Homepage, https://github.com/ivanVgusev/FlowForge
Project-URL: Documentation, https://github.com/ivanVgusev/FlowForge/blob/main/docs/dsl.md
Project-URL: Repository, https://github.com/ivanVgusev/FlowForge
Project-URL: Issues, https://github.com/ivanVgusev/FlowForge/issues
Author-email: Ivan Gusev <ivan.v.gusev@gmail.com>
License-Expression: MIT
License-File: LICENSE
Keywords: bot-framework,chatbot,conversational-ai,dialogue,dsl,yaml
Classifier: Development Status :: 4 - Beta
Classifier: Framework :: Robot Framework :: Library
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.9
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Communications :: Chat
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Typing :: Typed
Requires-Python: >=3.9
Requires-Dist: pyyaml>=6.0
Provides-Extra: dev
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest>=7.0; extra == 'dev'
Provides-Extra: llm
Requires-Dist: anthropic>=0.20; extra == 'llm'
Requires-Dist: openai>=1.0; extra == 'llm'
Description-Content-Type: text/markdown

# FlowForge

**Object-oriented dialogue framework for Python.**

FlowForge lets you build conversational bots using a declarative YAML DSL where each state is a **business object** — not an abstract node in a state machine, but a real concept from your domain: `pricing`, `support`, `checkout`, `booking`.

YAML defines the dialogue structure. Python handles the logic. The engine connects them.

## Philosophy

Traditional chatbot frameworks think in terms of **states and transitions** — abstract nodes connected by arrows. FlowForge thinks in terms of **objects and signals**:

| Traditional | FlowForge |
|---|---|
| State node | Business object (`pricing`, `support`, `order`) |
| Responses | What the object **says about itself** |
| `run:` actions | What the object **does** when activated |
| `auto_transitions` | **Signals** this object listens for |
| `response_transitions` | **Follow-up actions** after the object has spoken |

This means your bot's structure mirrors your business domain. Adding a new topic = adding a new object. Each object is self-contained: it knows what to say, what to do, and where to go next.

## Quick Start

```bash
pip install flowforge
```

Create `scenario.yaml`:

```yaml
scenario:
  name: shop_bot
  initial_state: greeting
  fallback: llm

intents:
  ask_price:
    - "how much does it cost"
    - "what is the price"
  greeting:
    - "hello"
    - "hi"

states:
  # Object: Greeting — entry point, knows how to welcome
  greeting:
    responses:
      - "Hello! Ask about prices or say help."
    auto_transitions:
      - target: pricing
        when:
          - type: intent
            value: ask_price
      - target: help
        when:
          - type: regex
            value: 'help|support'

  # Object: Pricing — knows everything about prices
  pricing:
    run:
      - action: get_price
    responses:
      - "Price: {price} USD."
    response_transitions:
      - target: checkout
        when:
          - type: regex
            value: 'yes|sure|buy'

  # Object: Help — knows how to assist
  help:
    responses:
      - "I can help with pricing and orders."
    auto_transitions:
      - target: greeting
        when:
          - type: intent
            value: '*'

  # Object: Checkout — handles purchases
  checkout:
    responses:
      - "Order confirmed!"
```

Run:

```python
from flowforge import Bot

bot = Bot.from_yaml("scenario.yaml")

@bot.action("get_price")
def get_price(ctx):
    return {"price": 100}

bot.run()  # interactive console REPL
```

Or use programmatically:

```python
response = bot.send("how much does it cost?")
print(response.text)   # "Price: 100 USD."
print(response.state)  # "pricing"
```

## Connect to any channel

FlowForge is the brain. The channel (Telegram, Discord, web) is just ears and mouth:

```python
from telegram.ext import ApplicationBuilder, MessageHandler, filters
from flowforge import Bot

bot = Bot.from_yaml("scenario.yaml")

async def handle_message(update, context):
    user_id = str(update.effective_user.id)
    response = bot.send(update.message.text, session_id=user_id)
    await update.message.reply_text(response.text)

app = ApplicationBuilder().token("TOKEN").build()
app.add_handler(MessageHandler(filters.TEXT, handle_message))
app.run_polling()
```

## Features

- **Object-oriented DSL** — states are business objects, not abstract nodes
- **Hybrid API** — YAML for dialogue structure, Python for business logic
- **Pluggable intent detection** — TF-IDF out of the box, bring your own classifier
- **LLM fallback** — rule-based for known paths, LLM for everything else
- **Knowledge base** — attach a `knowledge.md` file for LLM-powered Q&A
- **Persistent sessions** — SQLite store included, plug in Redis/Postgres/anything
- **Trigger types** — regex, pattern matching, intent classification
- **Session management** — multiple independent conversations by session_id
- **Actions** — Python functions via `@bot.action()`, Node.js via subprocess
- **Debugging** — `verbose=True` for step-by-step engine trace
- **Channel-agnostic** — `bot.send(text) -> response`, connect to anything
- **Zero heavy dependencies** — only `pyyaml`

## Documentation

Full DSL reference, Python API, and examples: **[docs/dsl.md](docs/dsl.md)**

## License

MIT
