LLM-FSM is a Python framework for building robust, stateful conversational AI applications by combining the power of Large Language Models (LLMs) with the predictability of Finite State Machines (FSMs).
Large Language Models (LLMs) are phenomenal at understanding and generating human-like text. However, their inherent statelessness makes it challenging to build complex, multi-turn conversations that require remembering context, following structured flows, and making consistent decisions.
LLM-FSM bridges this gap by:
- ๐ง Leveraging LLMs: For natural language understanding, intent recognition, information extraction, and dynamic response generation.
- ๐ Employing Finite State Machines: To provide a clear, testable, and predictable structure for conversation flows.
- ๐พ Managing State & Context: Python handles the state transitions, context persistence, and business logic, allowing the LLM to focus on language tasks.
The result? You can build sophisticated conversational agents that:
- Follow well-defined paths.
- Remember information across multiple turns.
- Handle complex branching logic.
- Integrate with external systems seamlessly.
- Feel natural and intelligent to the user.
Get started with LLM-FSM in seconds:
pip install llm-fsmFor advanced workflow orchestration capabilities (event-driven flows, timers, parallel execution), install the optional workflows extension:
pip install llm-fsm[workflows]Before you run your first bot, you'll need to configure your LLM provider. LLM-FSM uses LiteLLM under the hood, giving you access to 100+ LLM providers (OpenAI, Anthropic, Cohere, local models via Ollama, etc.).
Create a .env file in your project root (or set environment variables):
# .env.example
OPENAI_API_KEY=sk-your-openai-key-here
LLM_MODEL=gpt-4o-mini # Or any LiteLLM supported model string
LLM_TEMPERATURE=0.7
LLM_MAX_TOKENS=1000(See .env.example for a template)
Let's create a simple bot that asks for your name and then greets you personally.
1. Define your FSM (e.g., my_first_bot.json):
{
"name": "MyFirstBot",
"description": "A simple bot to ask for a name and greet.",
"initial_state": "ask_name",
"persona": "A friendly and curious assistant.",
"states": {
"ask_name": {
"id": "ask_name",
"purpose": "Politely ask the user for their name.",
"transitions": [{
"target_state": "greet_user",
"description": "User has provided their name."
}]
},
"greet_user": {
"id": "greet_user",
"purpose": "Greet the user personally using their name.",
"required_context_keys": ["user_name"],
"transitions": []
}
}
}2. Write your Python script (e.g., run_bot.py):
from llm_fsm import API
import os
# Ensure your API key is set via environment variable or .env file
if not os.getenv("OPENAI_API_KEY"):
print("Error: OPENAI_API_KEY not found. Please set it in your environment or .env file.")
exit()
# Initialize the API with your FSM definition
# (Assumes my_first_bot.json and .env are in the same directory)
api = API.from_file("my_first_bot.json") # Model and API key are picked from .env
# Start the conversation
conversation_id, response = api.start_conversation()
print(f"Bot: {response}") # Expected: "Hello! I'm a friendly assistant. What's your name?"
# Interact with the bot
user_name = input("You: ")
response = api.converse(user_name, conversation_id)
print(f"Bot: {response}") # Expected: "Nice to meet you, [User's Name]! ..."
# Check the collected data
collected_data = api.get_data(conversation_id)
print(f"Data collected by bot: {collected_data}") # Expected: {'user_name': '[User's Name]', ...}
print("Conversation ended." if api.has_conversation_ended(conversation_id) else "Conversation ongoing.")3. Run it!
python run_bot.pyYou've just created a stateful conversation! The bot remembered the name you provided because LLM-FSM managed the state and context.
-
JSON-Defined FSMs: Design your conversation flows declaratively.
- Define states, their purposes, and instructions for the LLM.
- Specify transitions, conditions (using JsonLogic), and priorities.
- Set a global
personafor consistent bot behavior. - (See
docs/fsm_design.mdfor best practices)
-
Intelligent Prompt Engineering:
- Automatic generation of structured XML-like prompts for the LLM.
- Includes current state, context, history, valid transitions, and response format.
- Secure: Sanitizes inputs to prevent prompt injection.
- (See
LLM.mdfor the detailed prompt structure given to the LLM)
-
Context Management:
- Automatically collects data specified in
required_context_keys. - LLM can store additional relevant info in an
_extrafield. - Conversation history is managed and truncated to fit token limits.
- Automatically collects data specified in
-
Flexible LLM Integration:
- Powered by
LiteLLMfor broad provider compatibility (OpenAI, Anthropic, Cohere, Ollama, etc.). - Easily configure
model,temperature,max_tokens. - Plug in your custom
LLMInterfacefor specialized needs.
- Powered by
-
Powerful Handler System:
- Extend FSM behavior with custom Python functions at various
HandlerTimingpoints (e.g.,PRE_PROCESSING,POST_TRANSITION,CONTEXT_UPDATE). - Fluent
HandlerBuilderfor easy creation:def my_custom_logic(context): # ... do something ... return {"new_data": "value"} api.register_handler( api.create_handler("MyLogicHandler") .at(HandlerTiming.POST_PROCESSING) .on_state("some_state") .when_context_has("specific_key") .do(my_custom_logic) )
- (See
docs/handlers.mdfor details)
- Extend FSM behavior with custom Python functions at various
-
FSM Stacking & Workflows:
- Build complex, modular applications by stacking FSMs.
api.push_fsm(...)to delegate to a sub-FSM.api.pop_fsm(...)to return to the parent FSM.- Control context inheritance, sharing, and merge strategies.
- Preserve conversation history across the stack.
- (Explore
examples/advanced/e_commerce/run.py)
-
Expression Evaluation:
- Use JsonLogic for defining complex
conditionsin your FSM transitions. - (See
src/llm_fsm/expressions.pyandtests/test_llm_fsm/test_expressions.py)
- Use JsonLogic for defining complex
-
Comprehensive Observability:
- Detailed logging with
Loguru, including per-conversation context. api.get_data(),api.get_current_state(),api.get_conversation_history().api.save_conversation()to persist state.
- Detailed logging with
-
Command-Line Tools:
llm-fsm --fsm <path_to_fsm.json>: Run any FSM interactively.llm-fsm-visualize --fsm <path_to_fsm.json>: Generate an ASCII visualization.llm-fsm-validate --fsm <path_to_fsm.json>: Validate your FSM definition.
-
(Optional) Workflow Engine:
- If
llm-fsm[workflows]is installed, orchestrate FSMs with event-driven steps, timers, and parallel execution. - Define workflows using a Python DSL.
- (See
src/llm_fsm_workflows/for implementation)
- If
โโโ .github/workflows/ # CI/CD (GitHub Actions)
โโโ docs/ # Detailed documentation
โ โโโ architecture.md
โ โโโ api_reference.md
โ โโโ fsm_design.md
โ โโโ handlers.md
โ โโโ quickstart.md
โโโ examples/ # Practical examples
โ โโโ basic/
โ โโโ intermediate/
โ โโโ advanced/
โโโ src/
โ โโโ llm_fsm/ # Core LLM-FSM library
โ โ โโโ __init__.py # Main package exports
โ โ โโโ api.py # Primary user-facing API class
โ โ โโโ definitions.py # Pydantic models for FSM structure
โ โ โโโ fsm.py # FSMManager, core state logic
โ โ โโโ handlers.py # Handler system and builder
โ โ โโโ llm.py # LLM interface (LiteLLM)
โ โ โโโ prompts.py # Prompt engineering
โ โ โโโ expressions.py # JsonLogic evaluator
โ โ โโโ validator.py # FSM validation logic
โ โ โโโ visualizer.py # ASCII FSM visualizer
โ โ โโโ runner.py # CLI runner logic
โ โ โโโ __main__.py # CLI entry point
โ โ โโโ ... # Other utilities, constants, logging
โ โโโ llm_fsm_workflows/ # Optional workflow engine extension
โ โโโ __init__.py
โ โโโ engine.py
โ โโโ steps.py
โ โโโ ...
โโโ tests/ # Unit and integration tests
โ โโโ fixtures/
โ โโโ test_llm_fsm/
โ โโโ ...
โโโ .env.example # Example environment variables
โโโ LLM.md # Guide for how LLMs should interpret prompts
โโโ Makefile # Build/test automation
โโโ pyproject.toml # Project metadata and dependencies
โโโ requirements.txt # Core dependencies
โโโ README.md # This file
- Quick Start Guide: Your first steps with LLM-FSM.
- FSM Design Guide: Best practices for crafting effective FSMs.
- Handler Development: Adding custom logic and integrations.
- API Reference: Detailed documentation of the
APIclass and its methods. - Architecture Deep Dive: Understand the internals of LLM-FSM.
- LLM Interaction Guide: How LLM-FSM structures prompts for LLMs and expects responses.
We welcome contributions! Whether it's bug fixes, new features, examples, or documentation improvements, your help is valued.
Setup your development environment:
# Fork and clone the repository
git clone https://github.com/YOUR_USERNAME/llm-fsm.git
cd llm-fsm
# Create a virtual environment (recommended)
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install in editable mode with development dependencies
pip install -e ".[dev,workflows]" # Install with all optional extras
# Set up pre-commit hooks
pre-commit installRunning Tests:
pytest # Run all tests
# Or use Makefile:
make testContribution Guidelines:
- Fork the repository.
- Create a new branch for your feature or bug fix.
- Write tests for your changes.
- Ensure all tests pass (
pytest). - Format your code with
black .and check linting withflake8 .. - Update documentation if necessary.
- Submit a pull request!
LLM-FSM is ideal for building a wide range of stateful conversational applications, including:
- ๐ค Chatbots & Virtual Assistants: Customer service, personal assistants, technical support.
- ๐ Information Collection: Smart forms, surveys, user onboarding.
- โ๏ธ Workflow Automation: Guiding users through multi-step processes.
- ๐ฎ Interactive Storytelling: Choose-your-own-adventure games, educational narratives.
- ๐๏ธ E-commerce: Personalized shopping assistants, product recommenders.
- ๐ Tutoring Systems: Adaptive learning paths, interactive quizzes.
This project is licensed under the GNU General Public License v3.0. See the LICENSE file for details.
Give your LLM the memory and structure it deserves.
Build reliable, stateful conversational AI with LLM-FSM.
๐ฆ Install on PyPI |
๐ Explore Examples |
๐ฌ Join Discussions |
๐ Report Issues
