frankstate 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- frankstate-0.0.1/LICENSE +21 -0
- frankstate-0.0.1/PKG-INFO +331 -0
- frankstate-0.0.1/README.md +287 -0
- frankstate-0.0.1/pyproject.toml +54 -0
- frankstate-0.0.1/requirements-dev.txt +2 -0
- frankstate-0.0.1/requirements-examples.txt +21 -0
- frankstate-0.0.1/requirements-frank-base.txt +3 -0
- frankstate-0.0.1/setup.cfg +4 -0
- frankstate-0.0.1/src/frankstate/__init__.py +19 -0
- frankstate-0.0.1/src/frankstate/entity/__init__.py +0 -0
- frankstate-0.0.1/src/frankstate/entity/edge.py +33 -0
- frankstate-0.0.1/src/frankstate/entity/graph_layout.py +106 -0
- frankstate-0.0.1/src/frankstate/entity/node.py +52 -0
- frankstate-0.0.1/src/frankstate/entity/runnable_builder.py +100 -0
- frankstate-0.0.1/src/frankstate/entity/statehandler.py +125 -0
- frankstate-0.0.1/src/frankstate/managers/__init__.py +0 -0
- frankstate-0.0.1/src/frankstate/managers/edge_manager.py +72 -0
- frankstate-0.0.1/src/frankstate/managers/node_manager.py +102 -0
- frankstate-0.0.1/src/frankstate/workflow_builder.py +107 -0
- frankstate-0.0.1/src/frankstate.egg-info/PKG-INFO +331 -0
- frankstate-0.0.1/src/frankstate.egg-info/SOURCES.txt +22 -0
- frankstate-0.0.1/src/frankstate.egg-info/dependency_links.txt +1 -0
- frankstate-0.0.1/src/frankstate.egg-info/requires.txt +29 -0
- frankstate-0.0.1/src/frankstate.egg-info/top_level.txt +1 -0
frankstate-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Γngel M. AragonΓ©s
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,331 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: frankstate
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Frank brings order and helps you build complex LLM workflows using scalable, testable, and reusable components.
|
|
5
|
+
Author-email: eiingeeel <aangel.maragones@outlook.com>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: homepage, https://github.com/eiingeeel/frankenst-ai
|
|
8
|
+
Project-URL: issues, https://github.com/eiingeeel/frankenst-ai/issues
|
|
9
|
+
Project-URL: repository, https://github.com/eiingeeel/frankenst-ai
|
|
10
|
+
Keywords: LLM,azure,langgraph,langchain,azure-ai-foundry,unstructured,multimodal
|
|
11
|
+
Classifier: Programming Language :: Python :: 3
|
|
12
|
+
Classifier: Operating System :: OS Independent
|
|
13
|
+
Requires-Python: >=3.12.3
|
|
14
|
+
Description-Content-Type: text/markdown
|
|
15
|
+
License-File: LICENSE
|
|
16
|
+
Requires-Dist: langchain-core
|
|
17
|
+
Requires-Dist: langgraph
|
|
18
|
+
Requires-Dist: pydantic
|
|
19
|
+
Provides-Extra: examples
|
|
20
|
+
Requires-Dist: langchain; extra == "examples"
|
|
21
|
+
Requires-Dist: PyYAML; extra == "examples"
|
|
22
|
+
Requires-Dist: requests; extra == "examples"
|
|
23
|
+
Requires-Dist: azure-functions; extra == "examples"
|
|
24
|
+
Requires-Dist: azure-keyvault-secrets; extra == "examples"
|
|
25
|
+
Requires-Dist: azure-identity; extra == "examples"
|
|
26
|
+
Requires-Dist: azure-search-documents; extra == "examples"
|
|
27
|
+
Requires-Dist: azure-storage-blob; extra == "examples"
|
|
28
|
+
Requires-Dist: langchain-azure-ai[opentelemetry]; extra == "examples"
|
|
29
|
+
Requires-Dist: langchain-chroma; extra == "examples"
|
|
30
|
+
Requires-Dist: langchain-classic; extra == "examples"
|
|
31
|
+
Requires-Dist: langchain_mcp_adapters; extra == "examples"
|
|
32
|
+
Requires-Dist: langchain-ollama; extra == "examples"
|
|
33
|
+
Requires-Dist: mcp; extra == "examples"
|
|
34
|
+
Requires-Dist: Pillow; extra == "examples"
|
|
35
|
+
Requires-Dist: tenacity; extra == "examples"
|
|
36
|
+
Requires-Dist: unstructured[pdf]; extra == "examples"
|
|
37
|
+
Requires-Dist: ipykernel; extra == "examples"
|
|
38
|
+
Requires-Dist: ipywidgets; extra == "examples"
|
|
39
|
+
Requires-Dist: matplotlib; extra == "examples"
|
|
40
|
+
Provides-Extra: dev
|
|
41
|
+
Requires-Dist: pytest; extra == "dev"
|
|
42
|
+
Requires-Dist: streamlit; extra == "dev"
|
|
43
|
+
Dynamic: license-file
|
|
44
|
+
|
|
45
|
+
# π§ Frankenst-AI | LangGraph Patterns
|
|
46
|
+
**Frankenst-AI** is a project that introduces a **modular and scalable structure** based on design patterns and coding best practices, applied to **LangGraph**.
|
|
47
|
+
|
|
48
|
+
It is not a framework that replaces LangGraph. It is a reusable project layer that helps you organize components, layouts and runtime assembly so you can build LangGraph workflows with less duplication and stronger boundaries.
|
|
49
|
+
|
|
50
|
+
This project aims to improve **scalability**, **reusability**, **testability**, and **maintainability** through reusable, configurable, and highly decoupled components designed to assemble complex LLM workflows.
|
|
51
|
+
|
|
52
|
+
By leveraging a well-organized structure, the project enables the creation of composable and extensible AI systems (agent patterns, RAG patterns, MCPs, etc.) while still returning official LangGraph graphs at the end of the build process.
|
|
53
|
+
|
|
54
|
+
The project has been designed with the following goals:
|
|
55
|
+
|
|
56
|
+
- **Isolated logic and separation of concerns** between conditional edges, nodes, tools, and runnables, encapsulated as reusable and independent components.
|
|
57
|
+
|
|
58
|
+
- Key components like **StateEnhancer**, **StateCommander**, and **StateEvaluator** are designed to be reused across multiple workflows.
|
|
59
|
+
|
|
60
|
+
- Use of YAML, **centralized configurations**, and explicit layout classes managed with builders and managers to define, **modify**, and **scale** different graph architectures **without duplicating logic**.
|
|
61
|
+
|
|
62
|
+
## How Frankenst-AI Maps to LangGraph
|
|
63
|
+
|
|
64
|
+
Frankenst-AI keeps the official LangGraph runtime model and adds a small layer
|
|
65
|
+
of project-specific naming around it:
|
|
66
|
+
|
|
67
|
+
- **StateEnhancer** wraps the async node callable that reads the current state and returns a partial update.
|
|
68
|
+
- **StateEvaluator** wraps the callable passed to conditional edges and returns the routing key used in the path map.
|
|
69
|
+
- **StateCommander** wraps nodes that return an official LangGraph `Command` when routing and state updates must happen in the same step.
|
|
70
|
+
|
|
71
|
+
These names are project abstractions, but the compiled graph still relies on
|
|
72
|
+
`StateGraph`, `add_node()`, `add_edge()`, `add_conditional_edges()` and
|
|
73
|
+
`Command` from LangGraph.
|
|
74
|
+
|
|
75
|
+
In other words, Frankenst-AI helps you structure and assemble LangGraph workflows; it does not introduce a separate graph runtime.
|
|
76
|
+
|
|
77
|
+
## Runtime Support
|
|
78
|
+
|
|
79
|
+
Frankstate currently supports LangGraph as its implemented workflow runtime.
|
|
80
|
+
|
|
81
|
+
The abstractions in this repository are intentionally being shaped so they can
|
|
82
|
+
grow beyond a single runtime, and Microsoft Agent Framework is a planned future
|
|
83
|
+
integration direction. That future support does not exist yet in the published
|
|
84
|
+
package, examples or tests.
|
|
85
|
+
|
|
86
|
+
## Frankstate Public API
|
|
87
|
+
|
|
88
|
+
The root package `frankstate` intentionally exposes only one shortcut:
|
|
89
|
+
|
|
90
|
+
```python
|
|
91
|
+
from frankstate import WorkflowBuilder
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
That root import is reserved for the main assembly entrypoint.
|
|
95
|
+
|
|
96
|
+
All other reusable contracts should be imported from their concrete modules,
|
|
97
|
+
not from `frankstate.__init__`. For example:
|
|
98
|
+
|
|
99
|
+
```python
|
|
100
|
+
from frankstate.entity.graph_layout import GraphLayout
|
|
101
|
+
from frankstate.entity.node import SimpleNode, CommandNode
|
|
102
|
+
from frankstate.entity.edge import SimpleEdge, ConditionalEdge
|
|
103
|
+
from frankstate.entity.statehandler import StateEnhancer, StateEvaluator, StateCommander
|
|
104
|
+
from frankstate.entity.runnable_builder import RunnableBuilder
|
|
105
|
+
from frankstate.managers.node_manager import NodeManager
|
|
106
|
+
from frankstate.managers.edge_manager import EdgeManager
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
This keeps `frankstate` root stable and prevents it from turning into an absolute import bucket for every internal type.
|
|
110
|
+
|
|
111
|
+
## Repository Shape
|
|
112
|
+
|
|
113
|
+
This mono-repo has four layers with different responsibilities:
|
|
114
|
+
|
|
115
|
+
- `src/frankstate` is the reusable pattern layer. It contains the assembly utilities and contracts used to structure LangGraph projects with consistent design rules.
|
|
116
|
+
- `src/core_examples` is the repository's importable reference package. It demonstrates one concrete way to organize layouts, state models, components, YAML configuration and prompt assets on top of `frankstate`.
|
|
117
|
+
- `src/services` is the service and integration layer. It contains runtime-specific entrypoints such as MCP servers, Azure Functions handlers and shared provider adapters used by the repository.
|
|
118
|
+
- `research` is exploratory material. The notebooks are useful to understand how layouts are compiled and exercised, but they are not part of the project's contractual surface.
|
|
119
|
+
|
|
120
|
+
`src/core_examples` is supported as the repository reference package, but it is not the stable public API of the published base `frankstate` wheel. `src/services` is repository integration code, not an extension of the `frankstate` public API.
|
|
121
|
+
|
|
122
|
+
The published base wheel intentionally contains only `frankstate`. `core_examples` and `services` remain repository-level layers with different responsibilities.
|
|
123
|
+
|
|
124
|
+
If you are evaluating or reusing Frankenst-AI, start with `src/frankstate`, then move to `src/core_examples` for the concrete reference package, and only read `src/services` when you need repository runtime entrypoints or shared provider adapters.
|
|
125
|
+
|
|
126
|
+
## Prerequisites
|
|
127
|
+
|
|
128
|
+
- Python 3.12.3 or higher
|
|
129
|
+
- Ollama 0.20.2 or higher (free); or an Azure Foundry Deployment (payment)
|
|
130
|
+
- pip (Python package manager)
|
|
131
|
+
- uv (install with pip)
|
|
132
|
+
|
|
133
|
+
## Installation
|
|
134
|
+
|
|
135
|
+
1. Clone the repository
|
|
136
|
+
|
|
137
|
+
2. Create a virtual environment:
|
|
138
|
+
|
|
139
|
+
```python3 -m venv .venv```
|
|
140
|
+
|
|
141
|
+
3. Activate the virtual environment:
|
|
142
|
+
- On Windows:
|
|
143
|
+
```.venv\Scripts\activate```
|
|
144
|
+
- On macOS and Linux:
|
|
145
|
+
```source .venv/bin/activate```
|
|
146
|
+
|
|
147
|
+
4. Install the project:
|
|
148
|
+
|
|
149
|
+
Published package from PyPI:
|
|
150
|
+
|
|
151
|
+
```bash
|
|
152
|
+
pip install frankstate
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Published package with optional dependency profile:
|
|
156
|
+
|
|
157
|
+
```bash
|
|
158
|
+
pip install 'frankstate[examples]'
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
Local editable install from the repository:
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
python3 -m uv pip install -e .
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
Local editable install with examples and development dependencies:
|
|
168
|
+
|
|
169
|
+
```bash
|
|
170
|
+
python3 -m uv pip install -e '.[examples, dev]'
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
`frankstate` is both the distribution name used by `pip` and the public import surface:
|
|
174
|
+
|
|
175
|
+
```python
|
|
176
|
+
from frankstate import WorkflowBuilder
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
In this first public packaging phase, the published wheel still contains only `frankstate`.
|
|
180
|
+
The `examples` extra adds optional dependencies used by the reference assets in this
|
|
181
|
+
repository; it does not make `core_examples` or `services` part of the base installed
|
|
182
|
+
wheel from PyPI.
|
|
183
|
+
|
|
184
|
+
5. (Optional) Install system packages for the example extras:
|
|
185
|
+
```bash
|
|
186
|
+
sudo apt update
|
|
187
|
+
sudo apt-get install poppler-utils
|
|
188
|
+
sudo apt install tesseract-ocr
|
|
189
|
+
```
|
|
190
|
+
|
|
191
|
+
## Running the Project Locally
|
|
192
|
+
|
|
193
|
+
To run the project locally:
|
|
194
|
+
|
|
195
|
+
1. Choose an LLM Services backend
|
|
196
|
+
|
|
197
|
+
Choose one of the following options:
|
|
198
|
+
|
|
199
|
+
#### 1.1 Using a local model with Ollama
|
|
200
|
+
Start the Ollama service by running:
|
|
201
|
+
|
|
202
|
+
```ollama run ministral-3:8b```
|
|
203
|
+
|
|
204
|
+
#### 1.2 Using Azure AI Foundry Deployment
|
|
205
|
+
Configure your model variables in `.env`:
|
|
206
|
+
|
|
207
|
+
```cp .env.example .env```
|
|
208
|
+
2. Compile Graph Layouts with WorkflowBuilder
|
|
209
|
+
|
|
210
|
+
The minimal example below uses the reference package under `src/core_examples` to show how `src/frankstate` is consumed in a real project.
|
|
211
|
+
|
|
212
|
+
Reference layouts now follow a two-step contract:
|
|
213
|
+
|
|
214
|
+
- `build_runtime()` resolves runtime dependencies such as LLM services, runnable builders, embeddings or retrievers.
|
|
215
|
+
- The keys returned by `build_runtime()` are projected onto the layout instance and must be declared as annotated attributes in the layout class.
|
|
216
|
+
- `layout()` declares nodes and edges using those already-resolved attributes on the layout instance.
|
|
217
|
+
|
|
218
|
+
This keeps imports side-effect free while preserving a declarative layout file.
|
|
219
|
+
|
|
220
|
+
In that example:
|
|
221
|
+
|
|
222
|
+
- `WorkflowBuilder` is part of the reusable pattern in `src/frankstate`.
|
|
223
|
+
- `SimpleOakConfigGraph` and `SharedState` are concrete reference classes from `src/core_examples`.
|
|
224
|
+
- In your own project, those `src/core_examples` imports would be replaced by your own layouts and state schemas.
|
|
225
|
+
|
|
226
|
+
For exploratory examples and experimentation, refer to the `research/demo...ipynb` notebooks.
|
|
227
|
+
|
|
228
|
+
#### Minimal WorkflowBuilder Example
|
|
229
|
+
|
|
230
|
+
```python
|
|
231
|
+
from frankstate import WorkflowBuilder
|
|
232
|
+
from core_examples.config.layouts.simple_oak_config_graph import SimpleOakConfigGraph
|
|
233
|
+
from core_examples.models.stategraph.stategraph import SharedState
|
|
234
|
+
|
|
235
|
+
workflow_builder = WorkflowBuilder(
|
|
236
|
+
config=SimpleOakConfigGraph,
|
|
237
|
+
state_schema=SharedState,
|
|
238
|
+
)
|
|
239
|
+
|
|
240
|
+
graph = workflow_builder.compile()
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
`graph` is still a LangGraph graph object produced through LangGraph's own runtime.
|
|
244
|
+
|
|
245
|
+
## Running Tests
|
|
246
|
+
|
|
247
|
+
Use the root pytest entrypoint:
|
|
248
|
+
|
|
249
|
+
```bash
|
|
250
|
+
pytest -q
|
|
251
|
+
```
|
|
252
|
+
|
|
253
|
+
`python -m pytest -q` should behave the same way, but `pytest -q` is the canonical local and CI command.
|
|
254
|
+
|
|
255
|
+
## Local Functions Apps Container
|
|
256
|
+
- `src/services/functions/function_app.py` is an Azure Functions App Containers packaging
|
|
257
|
+
artifact. It is not a reusable Python module from the source tree and is
|
|
258
|
+
expected to load only after the container build reshapes the filesystem under
|
|
259
|
+
`/home/site/wwwroot`.
|
|
260
|
+
|
|
261
|
+
- Start your Function App Container recipes:
|
|
262
|
+
```bash
|
|
263
|
+
docker build <build args -> build-and-push-acr.yml> mylocalfunction:0.1 .
|
|
264
|
+
docker run -d -p 8080:80 mylocalfunction:0.1
|
|
265
|
+
docker logs <container_id>
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
- Docker deep debug recipes:
|
|
269
|
+
```bash
|
|
270
|
+
docker exec -it <container_id> /bin/bash
|
|
271
|
+
apt-get update
|
|
272
|
+
apt-get install azure-functions-core-tools-4
|
|
273
|
+
apt-get install azure-cli
|
|
274
|
+
cd /home/site/wwwroot
|
|
275
|
+
az login
|
|
276
|
+
func start --verbose
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
## Repository Structure
|
|
280
|
+
|
|
281
|
+
```bash
|
|
282
|
+
frankenst-ai/
|
|
283
|
+
βββ main.py # Local entry point to assemble and compile graph layouts
|
|
284
|
+
βββ app.py # Optional deployment-facing wrapper entry point
|
|
285
|
+
βββ requirements.txt # Aggregate dependency set for the full repository environment
|
|
286
|
+
βββ requirements-*.txt # Dependency profiles split into base frankstate, example backends and dev
|
|
287
|
+
βββ .env # Environment variables for local configuration; .env.example for reference
|
|
288
|
+
βββ README.md # Main project documentation
|
|
289
|
+
βββ src/
|
|
290
|
+
β βββ services/ # Service entrypoints plus shared provider adapters used by the repository
|
|
291
|
+
β βββ core_examples/ # Importable reference package showing how to structure a real LangGraph project using `frankstate`
|
|
292
|
+
β β βββ components/
|
|
293
|
+
β β β βββ nodes/
|
|
294
|
+
β β β β βββ enhancers/ # StateEnhancers for simple node logic modifying StateGraph via runnables or custom modules
|
|
295
|
+
β β β β βββ commands/ # StateCommander for routing and modifying state through LangGraph commands
|
|
296
|
+
β β β βββ edges/
|
|
297
|
+
β β β β βββ evaluators/ # StateEvaluator for conditional edge logic
|
|
298
|
+
β β β βββ tools/ # Tool definitions and integrations
|
|
299
|
+
β β β βββ retrievers/ # Retrievers definitions, builders and integrations
|
|
300
|
+
β β β βββ runnables/ # Executable LangChain RunnableBuilder modules for invoke or ainvoke logic
|
|
301
|
+
β β βββ config/
|
|
302
|
+
β β β βββ config.yml # Main runtime configuration file for the project
|
|
303
|
+
β β β βββ config_nodes.yml # Node registry used by the example graph layouts
|
|
304
|
+
β β β βββ layouts/ # Reference GraphLayout subclasses using build_runtime() + layout()
|
|
305
|
+
β β βββ constants/
|
|
306
|
+
β β βββ models/ # Structural models: StateGraph, tool properties, structured outputs, etc.
|
|
307
|
+
β β βββ utils/
|
|
308
|
+
β βββ frankstate/ # Frankstate utilities for assembling and compiling LangGraph
|
|
309
|
+
β βββ entity/
|
|
310
|
+
β β βββ graph_layout.py # Base GraphLayout contract: build runtime first, then declare nodes and edges
|
|
311
|
+
β β βββ runnable_builder.py # Builder class for LangChain Runnable objects
|
|
312
|
+
β β βββ statehandler.py # Core entities for handling StateGraph
|
|
313
|
+
β β βββ node.py # Core node-related entities
|
|
314
|
+
β β βββ edge.py # Core edge-related entities
|
|
315
|
+
β βββ managers/
|
|
316
|
+
β βββ workflow_builder.py # Workflow Builder to compile LangGraph from GraphLayout subclasses
|
|
317
|
+
βββ research/ # Exploratory notebooks and experiments; useful as reference
|
|
318
|
+
βββ tests/
|
|
319
|
+
β βββ integration_test/
|
|
320
|
+
β βββ unit_test/
|
|
321
|
+
βββ artifacts/ # Generated artifacts, static files and outputs
|
|
322
|
+
βββ logs/ # Log files and runtime logs
|
|
323
|
+
```
|
|
324
|
+
|
|
325
|
+
## Notes For Contributors
|
|
326
|
+
|
|
327
|
+
- Prefer adding documentation close to the contract it explains: docstrings in `src/frankstate`, comments in YAML and examples in layout classes.
|
|
328
|
+
- When a component reads or writes new state keys, document that change in the state schema and in the component docstring.
|
|
329
|
+
- Keep project abstractions aligned with official LangGraph terminology to avoid confusion in new layouts.
|
|
330
|
+
- Treat `src/core_examples` as the repository's reference package for the project's pattern and `research` as exploratory support material.
|
|
331
|
+
- Treat `src/services` as repository integration code, not as an extension of the public `frankstate` API.
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
# π§ Frankenst-AI | LangGraph Patterns
|
|
2
|
+
**Frankenst-AI** is a project that introduces a **modular and scalable structure** based on design patterns and coding best practices, applied to **LangGraph**.
|
|
3
|
+
|
|
4
|
+
It is not a framework that replaces LangGraph. It is a reusable project layer that helps you organize components, layouts and runtime assembly so you can build LangGraph workflows with less duplication and stronger boundaries.
|
|
5
|
+
|
|
6
|
+
This project aims to improve **scalability**, **reusability**, **testability**, and **maintainability** through reusable, configurable, and highly decoupled components designed to assemble complex LLM workflows.
|
|
7
|
+
|
|
8
|
+
By leveraging a well-organized structure, the project enables the creation of composable and extensible AI systems (agent patterns, RAG patterns, MCPs, etc.) while still returning official LangGraph graphs at the end of the build process.
|
|
9
|
+
|
|
10
|
+
The project has been designed with the following goals:
|
|
11
|
+
|
|
12
|
+
- **Isolated logic and separation of concerns** between conditional edges, nodes, tools, and runnables, encapsulated as reusable and independent components.
|
|
13
|
+
|
|
14
|
+
- Key components like **StateEnhancer**, **StateCommander**, and **StateEvaluator** are designed to be reused across multiple workflows.
|
|
15
|
+
|
|
16
|
+
- Use of YAML, **centralized configurations**, and explicit layout classes managed with builders and managers to define, **modify**, and **scale** different graph architectures **without duplicating logic**.
|
|
17
|
+
|
|
18
|
+
## How Frankenst-AI Maps to LangGraph
|
|
19
|
+
|
|
20
|
+
Frankenst-AI keeps the official LangGraph runtime model and adds a small layer
|
|
21
|
+
of project-specific naming around it:
|
|
22
|
+
|
|
23
|
+
- **StateEnhancer** wraps the async node callable that reads the current state and returns a partial update.
|
|
24
|
+
- **StateEvaluator** wraps the callable passed to conditional edges and returns the routing key used in the path map.
|
|
25
|
+
- **StateCommander** wraps nodes that return an official LangGraph `Command` when routing and state updates must happen in the same step.
|
|
26
|
+
|
|
27
|
+
These names are project abstractions, but the compiled graph still relies on
|
|
28
|
+
`StateGraph`, `add_node()`, `add_edge()`, `add_conditional_edges()` and
|
|
29
|
+
`Command` from LangGraph.
|
|
30
|
+
|
|
31
|
+
In other words, Frankenst-AI helps you structure and assemble LangGraph workflows; it does not introduce a separate graph runtime.
|
|
32
|
+
|
|
33
|
+
## Runtime Support
|
|
34
|
+
|
|
35
|
+
Frankstate currently supports LangGraph as its implemented workflow runtime.
|
|
36
|
+
|
|
37
|
+
The abstractions in this repository are intentionally being shaped so they can
|
|
38
|
+
grow beyond a single runtime, and Microsoft Agent Framework is a planned future
|
|
39
|
+
integration direction. That future support does not exist yet in the published
|
|
40
|
+
package, examples or tests.
|
|
41
|
+
|
|
42
|
+
## Frankstate Public API
|
|
43
|
+
|
|
44
|
+
The root package `frankstate` intentionally exposes only one shortcut:
|
|
45
|
+
|
|
46
|
+
```python
|
|
47
|
+
from frankstate import WorkflowBuilder
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
That root import is reserved for the main assembly entrypoint.
|
|
51
|
+
|
|
52
|
+
All other reusable contracts should be imported from their concrete modules,
|
|
53
|
+
not from `frankstate.__init__`. For example:
|
|
54
|
+
|
|
55
|
+
```python
|
|
56
|
+
from frankstate.entity.graph_layout import GraphLayout
|
|
57
|
+
from frankstate.entity.node import SimpleNode, CommandNode
|
|
58
|
+
from frankstate.entity.edge import SimpleEdge, ConditionalEdge
|
|
59
|
+
from frankstate.entity.statehandler import StateEnhancer, StateEvaluator, StateCommander
|
|
60
|
+
from frankstate.entity.runnable_builder import RunnableBuilder
|
|
61
|
+
from frankstate.managers.node_manager import NodeManager
|
|
62
|
+
from frankstate.managers.edge_manager import EdgeManager
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
This keeps `frankstate` root stable and prevents it from turning into an absolute import bucket for every internal type.
|
|
66
|
+
|
|
67
|
+
## Repository Shape
|
|
68
|
+
|
|
69
|
+
This mono-repo has four layers with different responsibilities:
|
|
70
|
+
|
|
71
|
+
- `src/frankstate` is the reusable pattern layer. It contains the assembly utilities and contracts used to structure LangGraph projects with consistent design rules.
|
|
72
|
+
- `src/core_examples` is the repository's importable reference package. It demonstrates one concrete way to organize layouts, state models, components, YAML configuration and prompt assets on top of `frankstate`.
|
|
73
|
+
- `src/services` is the service and integration layer. It contains runtime-specific entrypoints such as MCP servers, Azure Functions handlers and shared provider adapters used by the repository.
|
|
74
|
+
- `research` is exploratory material. The notebooks are useful to understand how layouts are compiled and exercised, but they are not part of the project's contractual surface.
|
|
75
|
+
|
|
76
|
+
`src/core_examples` is supported as the repository reference package, but it is not the stable public API of the published base `frankstate` wheel. `src/services` is repository integration code, not an extension of the `frankstate` public API.
|
|
77
|
+
|
|
78
|
+
The published base wheel intentionally contains only `frankstate`. `core_examples` and `services` remain repository-level layers with different responsibilities.
|
|
79
|
+
|
|
80
|
+
If you are evaluating or reusing Frankenst-AI, start with `src/frankstate`, then move to `src/core_examples` for the concrete reference package, and only read `src/services` when you need repository runtime entrypoints or shared provider adapters.
|
|
81
|
+
|
|
82
|
+
## Prerequisites
|
|
83
|
+
|
|
84
|
+
- Python 3.12.3 or higher
|
|
85
|
+
- Ollama 0.20.2 or higher (free); or an Azure Foundry Deployment (payment)
|
|
86
|
+
- pip (Python package manager)
|
|
87
|
+
- uv (install with pip)
|
|
88
|
+
|
|
89
|
+
## Installation
|
|
90
|
+
|
|
91
|
+
1. Clone the repository
|
|
92
|
+
|
|
93
|
+
2. Create a virtual environment:
|
|
94
|
+
|
|
95
|
+
```python3 -m venv .venv```
|
|
96
|
+
|
|
97
|
+
3. Activate the virtual environment:
|
|
98
|
+
- On Windows:
|
|
99
|
+
```.venv\Scripts\activate```
|
|
100
|
+
- On macOS and Linux:
|
|
101
|
+
```source .venv/bin/activate```
|
|
102
|
+
|
|
103
|
+
4. Install the project:
|
|
104
|
+
|
|
105
|
+
Published package from PyPI:
|
|
106
|
+
|
|
107
|
+
```bash
|
|
108
|
+
pip install frankstate
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
Published package with optional dependency profile:
|
|
112
|
+
|
|
113
|
+
```bash
|
|
114
|
+
pip install 'frankstate[examples]'
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
Local editable install from the repository:
|
|
118
|
+
|
|
119
|
+
```bash
|
|
120
|
+
python3 -m uv pip install -e .
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
Local editable install with examples and development dependencies:
|
|
124
|
+
|
|
125
|
+
```bash
|
|
126
|
+
python3 -m uv pip install -e '.[examples, dev]'
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
`frankstate` is both the distribution name used by `pip` and the public import surface:
|
|
130
|
+
|
|
131
|
+
```python
|
|
132
|
+
from frankstate import WorkflowBuilder
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
In this first public packaging phase, the published wheel still contains only `frankstate`.
|
|
136
|
+
The `examples` extra adds optional dependencies used by the reference assets in this
|
|
137
|
+
repository; it does not make `core_examples` or `services` part of the base installed
|
|
138
|
+
wheel from PyPI.
|
|
139
|
+
|
|
140
|
+
5. (Optional) Install system packages for the example extras:
|
|
141
|
+
```bash
|
|
142
|
+
sudo apt update
|
|
143
|
+
sudo apt-get install poppler-utils
|
|
144
|
+
sudo apt install tesseract-ocr
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
## Running the Project Locally
|
|
148
|
+
|
|
149
|
+
To run the project locally:
|
|
150
|
+
|
|
151
|
+
1. Choose an LLM Services backend
|
|
152
|
+
|
|
153
|
+
Choose one of the following options:
|
|
154
|
+
|
|
155
|
+
#### 1.1 Using a local model with Ollama
|
|
156
|
+
Start the Ollama service by running:
|
|
157
|
+
|
|
158
|
+
```ollama run ministral-3:8b```
|
|
159
|
+
|
|
160
|
+
#### 1.2 Using Azure AI Foundry Deployment
|
|
161
|
+
Configure your model variables in `.env`:
|
|
162
|
+
|
|
163
|
+
```cp .env.example .env```
|
|
164
|
+
2. Compile Graph Layouts with WorkflowBuilder
|
|
165
|
+
|
|
166
|
+
The minimal example below uses the reference package under `src/core_examples` to show how `src/frankstate` is consumed in a real project.
|
|
167
|
+
|
|
168
|
+
Reference layouts now follow a two-step contract:
|
|
169
|
+
|
|
170
|
+
- `build_runtime()` resolves runtime dependencies such as LLM services, runnable builders, embeddings or retrievers.
|
|
171
|
+
- The keys returned by `build_runtime()` are projected onto the layout instance and must be declared as annotated attributes in the layout class.
|
|
172
|
+
- `layout()` declares nodes and edges using those already-resolved attributes on the layout instance.
|
|
173
|
+
|
|
174
|
+
This keeps imports side-effect free while preserving a declarative layout file.
|
|
175
|
+
|
|
176
|
+
In that example:
|
|
177
|
+
|
|
178
|
+
- `WorkflowBuilder` is part of the reusable pattern in `src/frankstate`.
|
|
179
|
+
- `SimpleOakConfigGraph` and `SharedState` are concrete reference classes from `src/core_examples`.
|
|
180
|
+
- In your own project, those `src/core_examples` imports would be replaced by your own layouts and state schemas.
|
|
181
|
+
|
|
182
|
+
For exploratory examples and experimentation, refer to the `research/demo...ipynb` notebooks.
|
|
183
|
+
|
|
184
|
+
#### Minimal WorkflowBuilder Example
|
|
185
|
+
|
|
186
|
+
```python
|
|
187
|
+
from frankstate import WorkflowBuilder
|
|
188
|
+
from core_examples.config.layouts.simple_oak_config_graph import SimpleOakConfigGraph
|
|
189
|
+
from core_examples.models.stategraph.stategraph import SharedState
|
|
190
|
+
|
|
191
|
+
workflow_builder = WorkflowBuilder(
|
|
192
|
+
config=SimpleOakConfigGraph,
|
|
193
|
+
state_schema=SharedState,
|
|
194
|
+
)
|
|
195
|
+
|
|
196
|
+
graph = workflow_builder.compile()
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
`graph` is still a LangGraph graph object produced through LangGraph's own runtime.
|
|
200
|
+
|
|
201
|
+
## Running Tests
|
|
202
|
+
|
|
203
|
+
Use the root pytest entrypoint:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
pytest -q
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
`python -m pytest -q` should behave the same way, but `pytest -q` is the canonical local and CI command.
|
|
210
|
+
|
|
211
|
+
## Local Functions Apps Container
|
|
212
|
+
- `src/services/functions/function_app.py` is an Azure Functions App Containers packaging
|
|
213
|
+
artifact. It is not a reusable Python module from the source tree and is
|
|
214
|
+
expected to load only after the container build reshapes the filesystem under
|
|
215
|
+
`/home/site/wwwroot`.
|
|
216
|
+
|
|
217
|
+
- Start your Function App Container recipes:
|
|
218
|
+
```bash
|
|
219
|
+
docker build <build args -> build-and-push-acr.yml> mylocalfunction:0.1 .
|
|
220
|
+
docker run -d -p 8080:80 mylocalfunction:0.1
|
|
221
|
+
docker logs <container_id>
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
- Docker deep debug recipes:
|
|
225
|
+
```bash
|
|
226
|
+
docker exec -it <container_id> /bin/bash
|
|
227
|
+
apt-get update
|
|
228
|
+
apt-get install azure-functions-core-tools-4
|
|
229
|
+
apt-get install azure-cli
|
|
230
|
+
cd /home/site/wwwroot
|
|
231
|
+
az login
|
|
232
|
+
func start --verbose
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Repository Structure
|
|
236
|
+
|
|
237
|
+
```bash
|
|
238
|
+
frankenst-ai/
|
|
239
|
+
βββ main.py # Local entry point to assemble and compile graph layouts
|
|
240
|
+
βββ app.py # Optional deployment-facing wrapper entry point
|
|
241
|
+
βββ requirements.txt # Aggregate dependency set for the full repository environment
|
|
242
|
+
βββ requirements-*.txt # Dependency profiles split into base frankstate, example backends and dev
|
|
243
|
+
βββ .env # Environment variables for local configuration; .env.example for reference
|
|
244
|
+
βββ README.md # Main project documentation
|
|
245
|
+
βββ src/
|
|
246
|
+
β βββ services/ # Service entrypoints plus shared provider adapters used by the repository
|
|
247
|
+
β βββ core_examples/ # Importable reference package showing how to structure a real LangGraph project using `frankstate`
|
|
248
|
+
β β βββ components/
|
|
249
|
+
β β β βββ nodes/
|
|
250
|
+
β β β β βββ enhancers/ # StateEnhancers for simple node logic modifying StateGraph via runnables or custom modules
|
|
251
|
+
β β β β βββ commands/ # StateCommander for routing and modifying state through LangGraph commands
|
|
252
|
+
β β β βββ edges/
|
|
253
|
+
β β β β βββ evaluators/ # StateEvaluator for conditional edge logic
|
|
254
|
+
β β β βββ tools/ # Tool definitions and integrations
|
|
255
|
+
β β β βββ retrievers/ # Retrievers definitions, builders and integrations
|
|
256
|
+
β β β βββ runnables/ # Executable LangChain RunnableBuilder modules for invoke or ainvoke logic
|
|
257
|
+
β β βββ config/
|
|
258
|
+
β β β βββ config.yml # Main runtime configuration file for the project
|
|
259
|
+
β β β βββ config_nodes.yml # Node registry used by the example graph layouts
|
|
260
|
+
β β β βββ layouts/ # Reference GraphLayout subclasses using build_runtime() + layout()
|
|
261
|
+
β β βββ constants/
|
|
262
|
+
β β βββ models/ # Structural models: StateGraph, tool properties, structured outputs, etc.
|
|
263
|
+
β β βββ utils/
|
|
264
|
+
β βββ frankstate/ # Frankstate utilities for assembling and compiling LangGraph
|
|
265
|
+
β βββ entity/
|
|
266
|
+
β β βββ graph_layout.py # Base GraphLayout contract: build runtime first, then declare nodes and edges
|
|
267
|
+
β β βββ runnable_builder.py # Builder class for LangChain Runnable objects
|
|
268
|
+
β β βββ statehandler.py # Core entities for handling StateGraph
|
|
269
|
+
β β βββ node.py # Core node-related entities
|
|
270
|
+
β β βββ edge.py # Core edge-related entities
|
|
271
|
+
β βββ managers/
|
|
272
|
+
β βββ workflow_builder.py # Workflow Builder to compile LangGraph from GraphLayout subclasses
|
|
273
|
+
βββ research/ # Exploratory notebooks and experiments; useful as reference
|
|
274
|
+
βββ tests/
|
|
275
|
+
β βββ integration_test/
|
|
276
|
+
β βββ unit_test/
|
|
277
|
+
βββ artifacts/ # Generated artifacts, static files and outputs
|
|
278
|
+
βββ logs/ # Log files and runtime logs
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Notes For Contributors
|
|
282
|
+
|
|
283
|
+
- Prefer adding documentation close to the contract it explains: docstrings in `src/frankstate`, comments in YAML and examples in layout classes.
|
|
284
|
+
- When a component reads or writes new state keys, document that change in the state schema and in the component docstring.
|
|
285
|
+
- Keep project abstractions aligned with official LangGraph terminology to avoid confusion in new layouts.
|
|
286
|
+
- Treat `src/core_examples` as the repository's reference package for the project's pattern and `research` as exploratory support material.
|
|
287
|
+
- Treat `src/services` as repository integration code, not as an extension of the public `frankstate` API.
|