Skip to main content

A Python library for structured LLM development with schema validation

Project description

LangTask

License: MIT Python Version Status

LangTask is a lightweight Python library for rapidly setting up and managing LLM prompts with structured input/output validation. It provides a clean, type-safe interface for working with language models while enforcing schema validation and proper error handling.

⚠️ Development Status Note: This is a work-in-progress personal project. The API will change significantly.

📝 Documentation Note: This project intentionally includes extensive documentation and inline examples to facilitate better understanding by LLMs. The API.md file can be used as a reference document in LLM chats to enable quick comprehension of the framework's usage patterns.

Features

  • 🔍 Schema Validation: Type-safe input and output validation using Pydantic models with dot notation access
  • 🔄 Provider Flexibility: Support for multiple LLM providers (currently OpenAI and Anthropic)
  • 📝 Prompt Management: Simple directory-based prompt organization and discovery
  • Easy Integration: Clean API for registering and running prompts
  • 🛠️ Error Handling: Comprehensive error hierarchy with detailed feedback
  • 📊 Logging: Structured logging with request tracing and performance monitoring

Installation

pip install langtask

Quick Start

First, import the library (we'll use this import in all following examples):

import langtask as lt
  1. Create a prompt directory structure:
prompts/
└── greeting/
    ├── config.yaml           # LLM configuration
    ├── instructions.md       # Prompt template
    ├── input_schema.yaml     # Input validation schema
    └── output_schema.yaml    # Output validation schema (optional)
  1. Configure your prompt:
# config.yaml
id: greeting
display_name: Greeting Generator
description: Generates personalized greetings
llm:
  provider: anthropic
  model: claude-3-5-sonnet-20241022
  temperature: 0.7
  1. Define input schema:
# input_schema.yaml
name:
  type: string
  description: Name of the person to greet
style:
  type: string
  description: Style of greeting
  options: ["formal", "casual"]
  required: false  # This field is optional
  1. Create prompt instructions:
# Note: Variable names are case-insensitive
Generate a {{STYLE}} greeting for {{Name}}.
# Will work the same as:
Generate a {{style}} greeting for {{name}}.
  1. Use in your code:
# Register prompt directory
lt.register("prompts")

# For simple text responses (no output schema)
response = lt.run("greeting", {
    "NAME": "Alice",  # Will work
    "style": "casual" # Will also work
})
print(response)  # "Hey Alice! How's it going?"

# For structured responses (with output schema)
response = lt.run("analyze-sentiment", {
    "text": "Great product!"
})
print(response.sentiment)      # "positive"
print(response.confidence)     # 0.95
print(response.word_count)     # 2

Variable Naming

LangTask handles variable names case-insensitively throughout the system:

  • Template variables like {{NAME}}, {{name}}, or {{Name}} are treated as identical
  • Input parameters can use any case (e.g., "NAME", "name", "Name")
  • Schema definitions use lowercase internally
  • All comparisons and validations are case-insensitive

Type names in schemas should use JSON Schema conventions:

  • Use string instead of str
  • Use integer instead of int
  • Use number instead of float
  • Use boolean instead of bool
  • Use object instead of dict

Arrays are defined using the list attribute on any field (e.g., list: true, list: 3, list: "2-5", list: "3+")

Example Prompt Structure

LangTask uses a directory-based approach for organizing prompts:

prompts/
├── greeting/
│   ├── config.yaml
│   ├── instructions.md
│   └── input_schema.yaml
└── sentiment/
    ├── config.yaml
    ├── instructions.md
    ├── input_schema.yaml
    └── output_schema.yaml

Each prompt requires:

  • config.yaml: LLM provider settings and prompt metadata
  • instructions.md: The actual prompt template with variable placeholders
  • input_schema.yaml: Schema defining expected input parameters
  • output_schema.yaml: Schema for structured output validation (required for dot notation access)

Configuration

Set global defaults for all prompts:

lt.set_global_config({
    "provider": "anthropic",
    "model": "claude-3-5-haiku-20241022",
    "temperature": 0.1
})

Or use provider-specific settings per prompt in config.yaml:

llm:
  - provider: anthropic
    model: claude-3-5-haiku-20241022
    temperature: 0.7
  - provider: openai
    model: gpt-4
    temperature: 0.5
    max_tokens: 1000

Structured Responses

When using output schemas, responses are returned as Pydantic models with dot notation access:

# Define output schema (output_schema.yaml):
sentiment:
  type: string
  description: Detected sentiment
  options: ["positive", "negative", "neutral"]
confidence:
  type: number
  description: Confidence score
  required: false  # Optional field
word_count:
  type: integer
  description: Number of words analyzed

Note: The options field can be used with string, integer, and number types as long as all values are of the same type. For example:

priority:
  type: integer
  options: [1, 2, 3]
  
confidence_intervals:
  type: number
  options: [0.25, 0.5, 0.75, 1.0]
# Access in code:
result = lt.run("analyze-sentiment", {"text": "Great product!"})

# Access fields with dot notation
print(result.sentiment)    # "positive"
print(result.confidence)   # 0.95
print(f"Analysis based on {result.word_count} words")

# Convert to dictionary if needed
data = result.model_dump()

Key benefits:

  • Type-safe field access
  • IDE autocompletion support
  • Immutable response objects
  • Automatic type conversion
  • Clear error messages for invalid access

Logging

LangTask provides comprehensive logging with configurable settings for both console and file output:

Features

  • Colored console output with configurable level
  • File logging with automatic rotation
  • Request ID tracking for operation tracing
  • Performance metrics for monitoring
  • Structured formatting for easy parsing

Configuration

Use set_logs() to configure logging behavior:

# Basic usage - just set log directory
lt.set_logs("./my_logs")

# Detailed configuration
lt.set_logs(
    path="./app/logs",              # Custom log directory
    console_level="WARNING",        # Less console output
    file_level="DEBUG",            # Detailed file logs
    rotation="100 MB",             # Larger log files
    retention="1 month"            # Keep logs longer
)

# Reset to defaults (logs/ directory with standard settings)
lt.set_logs()

Configuration Options

  • path: Directory for log files (default: './logs')
  • console_level: Console logging level (default: 'INFO')
    • Options: 'DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'
  • file_level: File logging level (default: 'DEBUG')
    • Options: Same as console_level
  • rotation: When to rotate log files (default: '10 MB')
    • Size-based: '10 MB', '1 GB', etc.
    • Time-based: '1 day', '1 week', etc.
  • retention: How long to keep old logs (default: '1 week')
    • '1 week', '1 month', '90 days', etc.

Default Behavior

  • Console: INFO level with color-coded output
  • File: DEBUG level for detailed troubleshooting
  • Location: ./logs/langtask.log
  • Rotation: 10 MB file size
  • Retention: 1 week

Fallback Behavior

If the specified log directory cannot be created or accessed:

  • Custom path: Raises FileSystemError
  • Default path: Falls back to console-only logging with warning

Example Log Output

2024-03-22 10:15:30 | req-123 | INFO    | prompt_loader  | Loading prompt | prompt_id=greeting
2024-03-22 10:15:30 | req-123 | WARNING | schema_loader  | Unknown field detected | field=custom_param
2024-03-22 10:15:31 | req-123 | SUCCESS | llm_processor  | Request processed | duration_ms=523.45

Environment Setup

LangTask supports multiple ways to configure your API keys:

  1. Direct environment variables:
# For Anthropic
export ANTHROPIC_API_KEY=sk-ant-...

# For OpenAI
export OPENAI_API_KEY=sk-...
  1. Using .env file (recommended for development):
# .env
ANTHROPIC_API_KEY=sk-ant-...
OPENAI_API_KEY=sk-...

Then in your code:

from dotenv import load_dotenv
load_dotenv()
  1. Setting in your deployment environment (recommended for production)

Remember to add .env to your .gitignore to protect your API keys.

Requirements

  • Python 3.10 or higher
  • Dependencies:
    • pydantic >= 2.0
    • langchain >= 0.1.0
    • langchain-openai >= 0.0.2
    • langchain-anthropic >= 0.1.1
    • pyyaml >= 6.0
    • python-dotenv >= 0.19.0
    • loguru >= 0.7.0

License

This project is licensed under the MIT License - see the LICENSE file for details.

Contributing

Contributions are welcome! Feel free to submit an issue or pull request.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

langtask-0.1.2.tar.gz (42.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

langtask-0.1.2-py3-none-any.whl (47.3 kB view details)

Uploaded Python 3

File details

Details for the file langtask-0.1.2.tar.gz.

File metadata

  • Download URL: langtask-0.1.2.tar.gz
  • Upload date:
  • Size: 42.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.9

File hashes

Hashes for langtask-0.1.2.tar.gz
Algorithm Hash digest
SHA256 d3ad68d55cf511fd8131fab7d21fd779fc6918745f911793ec82bd9945de01cf
MD5 3aac3c5869559e45df79712b0ed2a38d
BLAKE2b-256 535032a43857beccd151e48eb5eb18e82c4c9160c8b2c81515dfc45858dd9f8f

See more details on using hashes here.

File details

Details for the file langtask-0.1.2-py3-none-any.whl.

File metadata

  • Download URL: langtask-0.1.2-py3-none-any.whl
  • Upload date:
  • Size: 47.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/5.1.1 CPython/3.11.9

File hashes

Hashes for langtask-0.1.2-py3-none-any.whl
Algorithm Hash digest
SHA256 a7880170736b739bbe5ba8a13aa129a8a4cbad750fd5cb1a1a7c1a82de0b4c80
MD5 c46cd3b0a74eb1932da19703eda23ff5
BLAKE2b-256 fc8bf329f80eb773f2abf20d4ecb95270732a637877db2a4669e8d6b6e095d0e

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page