Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
137 changes: 137 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
name: CI

on:
push:
branches: [main]
tags:
- 'v*'
pull_request:
branches: [main]
release:
types: [published]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: uv sync --dev
- name: Ruff
run: uv run ruff check .
- name: Black
run: uv run black --check .
- name: mypy
run: uv run mypy intent_kit tests

test:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: uv sync --dev
- name: Tests with coverage
run: |
uv run pytest --cov=intent_kit --cov-report=xml
- name: Upload coverage to Codecov
uses: codecov/codecov-action@v4
with:
files: ./coverage.xml
token: ${{ secrets.CODECOV_TOKEN }}

eval:
runs-on: ubuntu-latest
needs: lint
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: uv sync --dev
- name: Evaluations (Mock Mode)
run: uv run python -m intent_kit.evals.run_all_evals --quiet --mock

build:
runs-on: ubuntu-latest
needs: [test, eval]
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build dependencies
run: |
pip install build
- name: Build package
run: python -m build --sdist --wheel --outdir dist
- name: Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: python-distributions
path: dist

docs:
runs-on: ubuntu-latest
needs: [test, eval]
if: startsWith(github.ref, 'refs/tags/')
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install uv
run: |
curl -LsSf https://astral.sh/uv/install.sh | sh
echo "$HOME/.cargo/bin" >> $GITHUB_PATH
- name: Install dependencies
run: uv sync --dev
- name: Build documentation
run: uv run mkdocs build
- name: Deploy to Cloudflare Pages
uses: cloudflare/pages-action@v1
with:
apiToken: ${{ secrets.CLOUDFLARE_API_TOKEN }}
accountId: ${{ secrets.CLOUDFLARE_ACCOUNT_ID }}
projectName: intentkit-docs
directory: site
gitHubToken: ${{ secrets.GITHUB_TOKEN }}

publish:
runs-on: ubuntu-latest
needs: build
if: startsWith(github.ref, 'refs/tags/')
permissions:
contents: write
id-token: write
steps:
- uses: actions/checkout@v3
- uses: actions/setup-python@v4
with:
python-version: '3.11'
- name: Install build and publish dependencies
run: |
pip install build twine
- name: Build package
run: python -m build --sdist --wheel --outdir dist
- name: Publish package to PyPI
uses: pypa/gh-action-pypi-publish@release/v1
31 changes: 0 additions & 31 deletions .github/workflows/test-and-eval.yml

This file was deleted.

3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@ htmlcov/
.tox/
reports/

# Documentation
site/

# Evaluation Results
intent_kit/evals/results/
intent_kit/evals/reports/
Expand Down
19 changes: 19 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.7
hooks:
- id: ruff
args: [--fix]
- repo: https://github.com/psf/black
rev: 24.4.2
hooks:
- id: black
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.10.0
hooks:
- id: mypy
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
hooks:
- id: end-of-file-fixer
- id: trailing-whitespace
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
# Changelog

All notable changes to this project will be documented in this file.

## [0.1.0] - 2025-07-07

### Added
- Experimental CI/CD pipeline with linting, type checking, test coverage reporting via Codecov, and trusted publishing.
- MkDocs documentation site using the Material theme with live search and API reference.
- Binder environment for interactive notebooks and examples.
- Pre-commit configuration powered by Ruff, Black, and mypy.
- Documentation badges for CI, coverage, docs, and PyPI.

### Changed
- Updated development dependencies and tooling for modern Python 3.11 ecosystem.

### Removed
- N/A
8 changes: 8 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,13 @@
# intent-kit

<!-- Badges -->

[![CI](https://github.com/Stephen-Collins-tech/intent-kit/actions/workflows/ci.yml/badge.svg)](https://github.com/Stephen-Collins-tech/intent-kit/actions/workflows/ci.yml)
[![Coverage Status](https://codecov.io/gh/Stephen-Collins-tech/intent-kit/branch/main/graph/badge.svg)](https://codecov.io/gh/Stephen-Collins-tech/intent-kit)
[![Documentation](https://img.shields.io/badge/docs-online-blue)](https://docs.intentkit.io)
[![PyPI](https://img.shields.io/pypi/v/intent-kit)](https://pypi.org/project/intent-kit)
[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/Stephen-Collins-tech/intent-kit/HEAD?filepath=examples%2Fsimple_demo.ipynb)

A Python library for building hierarchical intent classification and execution systems with support for multiple AI service backends.

## Features
Expand Down
3 changes: 3 additions & 0 deletions binder/requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-e .
jupyterlab
ipykernel
3 changes: 3 additions & 0 deletions docs/api_reference.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
# API Reference

::: intent_kit
36 changes: 36 additions & 0 deletions docs/examples/calculator-bot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Calculator Bot Example

This example shows how to build a simple calculator bot that can add and subtract numbers using intent-kit.

```python
from intent_kit import IntentGraphBuilder, handler

def add(a: int, b: int) -> str:
return str(a + b)

def subtract(a: int, b: int) -> str:
return str(a - b)

add_handler = handler(
name="add",
description="Add two numbers",
handler_func=add,
param_schema={"a": int, "b": int},
)

subtract_handler = handler(
name="subtract",
description="Subtract two numbers",
handler_func=subtract,
param_schema={"a": int, "b": int},
)

graph = (
IntentGraphBuilder()
.root(add_handler)
.root(subtract_handler)
.build()
)

print(graph.route("add 2 3").output) # -> 5
```
39 changes: 39 additions & 0 deletions docs/examples/context-aware-chatbot.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
# Context-Aware Chatbot Example

This example is adapted from `examples/context_demo.py`. It demonstrates how `IntentContext` can persist conversation state across multiple turns.

```python
from intent_kit import IntentGraphBuilder, handler
from intent_kit.context import IntentContext

# Handler remembers how many times we greeted the user

def greet(name: str, context: IntentContext) -> str:
count = context.get("greet_count", 0) + 1
context.set("greet_count", count, modified_by="greet")
return f"Hello {name}! (greeting #{count})"

hello_handler = handler(
name="greet",
description="Greet the user and track greeting count",
handler_func=greet,
param_schema={"name": str},
)

graph = IntentGraphBuilder().root(hello_handler).build()

ctx = IntentContext(session_id="abc123")
print(graph.route("hello alice", context=ctx).output)
print(graph.route("hello bob", context=ctx).output) # Greeting count increments
```

Running the above prints:

```
Hello alice! (greeting #1)
Hello bob! (greeting #2)
```

Key take-aways:
* `IntentContext` persists between calls so you can build multi-turn experiences.
* Each handler can declare which context keys it reads/writes for explicit dependency tracking.
51 changes: 51 additions & 0 deletions docs/examples/multi-intent-routing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
# Multi-Intent Routing Example

The following shows how intent-kit can handle _multiple_ intents in a single user utterance using a splitter node.

```python
from intent_kit import IntentGraphBuilder, handler, rule_splitter_node

# Handlers for individual intents

def greet(name: str) -> str:
return f"Hello {name}!"

def weather(city: str) -> str:
return f"The weather in {city} is sunny."

hello = handler(
name="greet",
description="Greet the user",
handler_func=greet,
param_schema={"name": str},
)

weather_h = handler(
name="weather",
description="Get weather information",
handler_func=weather,
param_schema={"city": str},
)

# Splitter routes parts of the sentence to different handlers
splitter = rule_splitter_node(
name="multi_split",
children=[hello, weather_h],
)

graph = IntentGraphBuilder().root(splitter).build()

result = graph.route("Hello Alice and what's the weather in Paris?")
print(result.output)
```

The `rule_splitter_node` looks for keywords ("hello", "weather", etc.) and breaks the user input into sub-phrases routed to the appropriate handlers. The final `result.output` aggregates the outputs from each intent, e.g.:

```
{
"greet": "Hello Alice!",
"weather": "The weather in Paris is sunny."
}
```

For a more robust version that uses LLM-based splitting, see `examples/multi_intent_demo.py`.
5 changes: 5 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Welcome to intent-kit

intent-kit is a universal Python framework for building hierarchical intent graphs with deterministic, fully-auditable execution models.

Explore the Quickstart to get running in minutes, or dive into the full API reference.
Loading