Skip to main content

Install

uv add py-ai-toolkit

WHAT

A set of tools for easily interacting with LLMs.

WHY

Building AI-driven software leans upon a number of utilities, such as prompt building and LLM calling via HTTP requests. Additionally, writing agents and workflows can prove particularly challenging using conventional code structures.

HOW

This simple library offers a set of predefined functions for:

  • Easy prompting - you need only provide a path or a template string
  • Calling LLMs - instructor takes care of structured responses
  • Modifying response models - we use Pydantic

Additionally, we provide grafo out of the box for convenient workflow building.

Configuration

PyAIToolkit reads configuration from environment variables by default:

Variable Description
LLM_MODEL Model identifier (e.g. gpt-4o)
LLM_API_KEY API key
LLM_BASE_URL Base URL for the API
EMBEDDING_MODEL Embedding model identifier
LLM_REASONING_EFFORT Reasoning effort (e.g. low, medium, high)

You can also pass an LLMConfig directly:

from py_ai_toolkit import PyAIToolkit, LLMConfig

toolkit = PyAIToolkit(main_model_config=LLMConfig(model="gpt-4o", api_key="..."))

About Grafo

Grafo (see Recommended Docs below) is a library for building executable DAGs where each node contains a coroutine. Since the DAG abstraction fits particularly well into AI-driven building, we provide the BaseWorkflow class with:

  • task — for LLM calling (structured or plain text)
  • create_task_tree — builds a task + validation subtree
  • build_task_node — wraps a task tree in a single Node for use in larger graphs

Examples

Simple text:

from py_ai_toolkit import PyAIToolkit

toolkit = PyAIToolkit()
template = "./prompt.md"
response = await toolkit.chat(template)
print(response.content)

Structured response:

from py_ai_toolkit import PyAIToolkit
from pydantic import BaseModel


class Purchase(BaseModel):
    product: str
    quantity: int


toolkit = PyAIToolkit()
template = "./prompt.md"  # PROMPT: {{ message }}
response = await toolkit.asend(
    response_model=Purchase, template=template, message="I want to buy 5 apples"
)
print(response.content.product)  # "apple"
print(response.content.quantity)  # 5

Structured response with model type injection:

from py_ai_toolkit import PyAIToolkit
from pydantic import BaseModel
from typing import Literal


class Purchase(BaseModel):
    product: str
    quantity: int


toolkit = PyAIToolkit()
available_fruits = ["apple", "banana", "orange"]
FruitModel = toolkit.inject_types(
    Purchase, [("product", Literal[tuple(available_fruits)])]
)
response = await toolkit.asend(
    response_model=FruitModel, template="./prompt.md", message="I want to buy 5 apples"
)

Using run_task with validation:

from py_ai_toolkit import PyAIToolkit, LLMConfig
from py_ai_toolkit.core.domain.schemas import SingleShotValidationConfig
from pydantic import BaseModel


class Purchase(BaseModel):
    product: str
    quantity: int


toolkit = PyAIToolkit(main_model_config=LLMConfig())

result = await toolkit.run_task(
    template="""
        You will extract a purchase from the following message:
        {{ message }}
    """.strip(),
    response_model=Purchase,
    kwargs=dict(message="I want to buy 5 apples."),
    config=SingleShotValidationConfig(
        issues=["The identified purchase matches the user's request."],
    ),
)

print(result.product)  # "apple"
print(result.quantity)  # 5

Custom workflow with validation:

from py_ai_toolkit import PyAIToolkit, BaseWorkflow, Node, TreeExecutor
from py_ai_toolkit.core.domain.schemas import SingleShotValidationConfig
from pydantic import BaseModel
from typing import Literal


class Purchase(BaseModel):
    product: str
    quantity: int


toolkit = PyAIToolkit()
available_fruits = ["apple", "banana", "orange"]
FruitModel = toolkit.inject_types(
    Purchase, [("product", Literal[tuple(available_fruits)])]
)


class PurchaseWorkflow(BaseWorkflow):
    async def run(self, message: str) -> Purchase:
        executor = await self.create_task_tree(
            template="./purchase.md",
            response_model=FruitModel,
            kwargs=dict(message=message),
            config=SingleShotValidationConfig(
                issues=["The identified purchase matches the user's request."],
            ),
        )
        results = await executor.run()
        return results[0].output


workflow = PurchaseWorkflow(ai_toolkit=toolkit, error_class=ValueError)
result = await workflow.run("I want to buy 5 apples")

Validation Modes

The run_task method supports three validation modes that control how the LLM output is validated:

SingleShotValidationConfig

  • Count: 1 validation attempt
  • Required Ahead: 1 (needs 1 more success than failure)
  • Max Retries: 3
  • Use Case: Simple validation for straightforward tasks where a single validation check is sufficient
from py_ai_toolkit.core.domain.schemas import SingleShotValidationConfig

config = SingleShotValidationConfig(
    issues=["The identified purchase matches the user's request."],
)

ThresholdVotingValidationConfig

  • Count: 3 validation attempts (default)
  • Required Ahead: 1 (needs 1 more success than failure)
  • Use Case: Moderate confidence validation where multiple checks provide better reliability
from py_ai_toolkit.core.domain.schemas import ThresholdVotingValidationConfig

config = ThresholdVotingValidationConfig(
    issues=["The identified purchase matches the user's request."],
)

KAheadVotingValidationConfig

  • Count: 5 validation attempts (default)
  • Required Ahead: 3 (needs 3 more successes than failures)
  • Use Case: High-stakes validation where you need strong consensus across multiple validation checks
from py_ai_toolkit.core.domain.schemas import KAheadVotingValidationConfig

config = KAheadVotingValidationConfig(
    issues=["The identified purchase matches the user's request."],
)

All validation configs accept an issues parameter — a list of validation criteria checked against the task output. Each issue is evaluated independently, and the validation passes only if all issues pass according to the configured mode.

Metadata

Release files for py-ai-toolkit 0.8.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for py-ai-toolkit 0.8.0
File Size Uploaded
py_ai_toolkit-0.8.0.tar.gz 37.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for py-ai-toolkit 0.8.0
File Interpreter ABI Platform
py_ai_toolkit-0.8.0-py3-none-any.whl Python 3 none any Details

Total release size: 64.2 kB

Release files / py_ai_toolkit-0.8.0.tar.gz

Download URL py_ai_toolkit-0.8.0.tar.gz
Size 37.7 kB
Tags Source
SHA-256 checksum
How to use checksums
ce13ad8a7a704db344234ea183feae3c59819958c72f67068d458bc3712df48f
BLAKE2b-256 checksum
How to use checksums
55b43488388eb1336e35dd7080fa14498b0b4f41ab04b42db2b7ba75f68dabce
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release files / py_ai_toolkit-0.8.0-py3-none-any.whl

Download URL py_ai_toolkit-0.8.0-py3-none-any.whl
Size 26.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
28c6d3e20d0c3d10b2baa3617af75ab6c6b34d224f167aed8a2bf7f206e050b5
BLAKE2b-256 checksum
How to use checksums
92ae6485a92ab38d6b3fce40b4488d78018fc8ce411258abdb1c81159dac76b8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.9.25

Release history Release notifications | RSS feed

This release

0.8.0 This release

2 release files

0.7.0

2 release files

0.6.2

2 release files

0.6.1

2 release files

0.6.0

2 release files

0.5.10

2 release files

0.5.9

2 release files

0.5.8

2 release files

0.5.6

2 release files

0.5.5

2 release files

0.5.3

2 release files

0.5.1

2 release files

0.5.0

2 release files

0.4.7

2 release files

0.4.6

2 release files

0.4.5

2 release files

0.4.4

2 release files

0.4.3

2 release files

0.4.2

2 release files

0.4.1

2 release files

0.4.0

2 release files

0.3.8

2 release files

0.3.7

2 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.4

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page