soprano-sdk 0.1.99__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.
- soprano_sdk-0.1.99/.github/workflows/test_build_and_publish.yaml +63 -0
- soprano_sdk-0.1.99/.gitignore +11 -0
- soprano_sdk-0.1.99/.python-version +1 -0
- soprano_sdk-0.1.99/CLAUDE.md +51 -0
- soprano_sdk-0.1.99/LICENSE +21 -0
- soprano_sdk-0.1.99/PKG-INFO +420 -0
- soprano_sdk-0.1.99/README.md +381 -0
- soprano_sdk-0.1.99/examples/framework_example.yaml +48 -0
- soprano_sdk-0.1.99/examples/greeting_functions.py +14 -0
- soprano_sdk-0.1.99/examples/greeting_workflow.yaml +224 -0
- soprano_sdk-0.1.99/examples/main.py +32 -0
- soprano_sdk-0.1.99/examples/persistence/README.md +297 -0
- soprano_sdk-0.1.99/examples/persistence/conversation_based.py +135 -0
- soprano_sdk-0.1.99/examples/persistence/entity_based.py +83 -0
- soprano_sdk-0.1.99/examples/persistence/mongodb_demo.py +138 -0
- soprano_sdk-0.1.99/examples/return_functions.py +68 -0
- soprano_sdk-0.1.99/examples/return_workflow.yaml +129 -0
- soprano_sdk-0.1.99/examples/structured_output_example.yaml +67 -0
- soprano_sdk-0.1.99/examples/supervisors/README.md +265 -0
- soprano_sdk-0.1.99/examples/supervisors/crewai_supervisor_ui.py +170 -0
- soprano_sdk-0.1.99/examples/supervisors/langgraph_supervisor_ui.py +179 -0
- soprano_sdk-0.1.99/examples/supervisors/tools/__init__.py +1 -0
- soprano_sdk-0.1.99/examples/supervisors/tools/crewai_tools.py +100 -0
- soprano_sdk-0.1.99/examples/supervisors/tools/langgraph_tools.py +90 -0
- soprano_sdk-0.1.99/examples/supervisors/workflow_tools.py +75 -0
- soprano_sdk-0.1.99/examples/tools/__init__.py +0 -0
- soprano_sdk-0.1.99/examples/tools/address.py +34 -0
- soprano_sdk-0.1.99/examples/validator.py +36 -0
- soprano_sdk-0.1.99/legacy/langgraph_demo.py +92 -0
- soprano_sdk-0.1.99/legacy/langgraph_selfloop_demo.py +167 -0
- soprano_sdk-0.1.99/legacy/langgraph_v.py +319 -0
- soprano_sdk-0.1.99/legacy/main.py +240 -0
- soprano_sdk-0.1.99/legacy/return_fsm.excalidraw +1310 -0
- soprano_sdk-0.1.99/legacy/return_state_machine.png +0 -0
- soprano_sdk-0.1.99/legacy/ui.py +20 -0
- soprano_sdk-0.1.99/pyproject.toml +63 -0
- soprano_sdk-0.1.99/scripts/visualize_workflow.py +56 -0
- soprano_sdk-0.1.99/scripts/workflow_demo.py +125 -0
- soprano_sdk-0.1.99/scripts/workflow_demo_ui.py +112 -0
- soprano_sdk-0.1.99/soprano_sdk/__init__.py +10 -0
- soprano_sdk-0.1.99/soprano_sdk/agents/__init__.py +30 -0
- soprano_sdk-0.1.99/soprano_sdk/agents/adaptor.py +90 -0
- soprano_sdk-0.1.99/soprano_sdk/agents/factory.py +228 -0
- soprano_sdk-0.1.99/soprano_sdk/agents/structured_output.py +97 -0
- soprano_sdk-0.1.99/soprano_sdk/core/__init__.py +0 -0
- soprano_sdk-0.1.99/soprano_sdk/core/constants.py +59 -0
- soprano_sdk-0.1.99/soprano_sdk/core/engine.py +225 -0
- soprano_sdk-0.1.99/soprano_sdk/core/rollback_strategies.py +258 -0
- soprano_sdk-0.1.99/soprano_sdk/core/state.py +71 -0
- soprano_sdk-0.1.99/soprano_sdk/engine.py +381 -0
- soprano_sdk-0.1.99/soprano_sdk/nodes/__init__.py +0 -0
- soprano_sdk-0.1.99/soprano_sdk/nodes/base.py +56 -0
- soprano_sdk-0.1.99/soprano_sdk/nodes/call_function.py +112 -0
- soprano_sdk-0.1.99/soprano_sdk/nodes/collect_input.py +542 -0
- soprano_sdk-0.1.99/soprano_sdk/nodes/factory.py +46 -0
- soprano_sdk-0.1.99/soprano_sdk/routing/__init__.py +0 -0
- soprano_sdk-0.1.99/soprano_sdk/routing/router.py +97 -0
- soprano_sdk-0.1.99/soprano_sdk/tools.py +206 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/__init__.py +0 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/function.py +35 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/logger.py +6 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/template.py +27 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/tool.py +60 -0
- soprano_sdk-0.1.99/soprano_sdk/utils/tracing.py +69 -0
- soprano_sdk-0.1.99/soprano_sdk/validation/__init__.py +13 -0
- soprano_sdk-0.1.99/soprano_sdk/validation/schema.py +297 -0
- soprano_sdk-0.1.99/soprano_sdk/validation/validator.py +173 -0
- soprano_sdk-0.1.99/tests/debug_jinja2.py +30 -0
- soprano_sdk-0.1.99/tests/test_agent_factory.py +151 -0
- soprano_sdk-0.1.99/tests/test_collect_input_refactor.py +27 -0
- soprano_sdk-0.1.99/tests/test_external_values.py +70 -0
- soprano_sdk-0.1.99/tests/test_inputs_validation.py +77 -0
- soprano_sdk-0.1.99/tests/test_jinja2_path.py +63 -0
- soprano_sdk-0.1.99/tests/test_jinja2_standalone.py +103 -0
- soprano_sdk-0.1.99/tests/test_persistence.py +160 -0
- soprano_sdk-0.1.99/tests/test_structured_output.py +165 -0
- soprano_sdk-0.1.99/tests/test_transition_routing.py +136 -0
- soprano_sdk-0.1.99/todo.md +24 -0
- soprano_sdk-0.1.99/uv.lock +5165 -0
- soprano_sdk-0.1.99/workflow-visualizer/.eslintrc.cjs +21 -0
- soprano_sdk-0.1.99/workflow-visualizer/.gitignore +24 -0
- soprano_sdk-0.1.99/workflow-visualizer/README.md +8 -0
- soprano_sdk-0.1.99/workflow-visualizer/index.html +13 -0
- soprano_sdk-0.1.99/workflow-visualizer/package-lock.json +5931 -0
- soprano_sdk-0.1.99/workflow-visualizer/package.json +33 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/App.jsx +217 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/CustomNode.jsx +124 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/StepDetailsModal.jsx +267 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/WorkflowGraph.jsx +286 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/WorkflowInfoPanel.jsx +170 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/assets/react.svg +1 -0
- soprano_sdk-0.1.99/workflow-visualizer/src/main.jsx +9 -0
- soprano_sdk-0.1.99/workflow-visualizer/vite.config.js +7 -0
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
name: Conversational SOP Framework CI/CD
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [ main ]
|
|
6
|
+
tags: [ 'v*' ]
|
|
7
|
+
pull_request:
|
|
8
|
+
branches: [ main ]
|
|
9
|
+
|
|
10
|
+
jobs:
|
|
11
|
+
test:
|
|
12
|
+
name: Test and Lint
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
steps:
|
|
15
|
+
- uses: actions/checkout@v4
|
|
16
|
+
|
|
17
|
+
- name: Install uv
|
|
18
|
+
uses: astral-sh/setup-uv@v3
|
|
19
|
+
with:
|
|
20
|
+
version: "latest"
|
|
21
|
+
|
|
22
|
+
- name: Set up Python
|
|
23
|
+
uses: actions/setup-python@v5
|
|
24
|
+
with:
|
|
25
|
+
python-version-file: ".python-version"
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --all-extras --dev
|
|
29
|
+
|
|
30
|
+
- name: Lint with ruff
|
|
31
|
+
run: uv run ruff check .
|
|
32
|
+
|
|
33
|
+
- name: Run tests
|
|
34
|
+
run: uv run pytest
|
|
35
|
+
|
|
36
|
+
release:
|
|
37
|
+
name: Build and Publish
|
|
38
|
+
needs: test
|
|
39
|
+
if: startsWith(github.ref, 'refs/tags/v')
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
permissions:
|
|
42
|
+
id-token: write
|
|
43
|
+
contents: read
|
|
44
|
+
steps:
|
|
45
|
+
- uses: actions/checkout@v4
|
|
46
|
+
|
|
47
|
+
- name: Install uv
|
|
48
|
+
uses: astral-sh/setup-uv@v3
|
|
49
|
+
with:
|
|
50
|
+
version: "latest"
|
|
51
|
+
|
|
52
|
+
- name: Set up Python
|
|
53
|
+
uses: actions/setup-python@v5
|
|
54
|
+
with:
|
|
55
|
+
python-version-file: ".python-version"
|
|
56
|
+
|
|
57
|
+
- name: Build package
|
|
58
|
+
run: uv build
|
|
59
|
+
|
|
60
|
+
- name: Publish to PyPI
|
|
61
|
+
run: uv publish
|
|
62
|
+
env:
|
|
63
|
+
UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.12
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Development Commands
|
|
6
|
+
|
|
7
|
+
- **Install dependencies**: `uv sync` (uses uv.lock)
|
|
8
|
+
- **Run the application**: `python ui.py` (launches Gradio interface)
|
|
9
|
+
- **Run core logic directly**: `python main.py` (for testing state machine)
|
|
10
|
+
|
|
11
|
+
## Project Architecture
|
|
12
|
+
|
|
13
|
+
This is a conversational SOP (Standard Operating Procedure) framework that implements a return processing workflow using finite state machines. The architecture consists of:
|
|
14
|
+
|
|
15
|
+
### Core Components
|
|
16
|
+
|
|
17
|
+
1. **State Machine (`main.py`)**:
|
|
18
|
+
- Uses `transitions` library to implement a finite state machine
|
|
19
|
+
- Defines `States` enum with 6 states: COLLECTING_ORDER_ID → CHECKING_RETURN_ELIGIBILITY → COLLECTING_RETURN_REASON → CHECKING_REASON_VALIDITY → PROCESSING_RETURN → COMPLETED
|
|
20
|
+
- `ReturnProcessor` class manages state transitions and business logic
|
|
21
|
+
- Integrates with `agno` AI agent framework using OpenAI GPT models
|
|
22
|
+
|
|
23
|
+
2. **UI Layer (`ui.py`)**:
|
|
24
|
+
- Gradio-based chat interface that wraps the core state machine
|
|
25
|
+
- `run()` function serves as the main entry point for user interactions
|
|
26
|
+
- Passes conversation history and current date to the return processor
|
|
27
|
+
|
|
28
|
+
### Key Dependencies
|
|
29
|
+
|
|
30
|
+
- **agno**: AI agent framework for conversational interactions
|
|
31
|
+
- **transitions**: State machine implementation
|
|
32
|
+
- **gradio**: Web-based chat interface
|
|
33
|
+
- **openai**: LLM integration (currently using gpt-5-mini)
|
|
34
|
+
|
|
35
|
+
### State Flow
|
|
36
|
+
|
|
37
|
+
The return processing follows this workflow:
|
|
38
|
+
1. Collect order ID from user
|
|
39
|
+
2. Check if order is eligible for return
|
|
40
|
+
3. Collect return reason from user
|
|
41
|
+
4. Validate the return reason
|
|
42
|
+
5. Process the return
|
|
43
|
+
6. Complete the workflow
|
|
44
|
+
|
|
45
|
+
Each state has corresponding trigger methods that advance the workflow or terminate it based on business rules.
|
|
46
|
+
|
|
47
|
+
### Development Notes
|
|
48
|
+
|
|
49
|
+
- The main logic is partially implemented with some placeholder/test code (random number generation)
|
|
50
|
+
- The AI agent in `collect_order_id()` currently has hardcoded instructions for "loan number" capture
|
|
51
|
+
- State machine callbacks are configured but not all are fully implemented
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Arvind Thangamani
|
|
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,420 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: soprano-sdk
|
|
3
|
+
Version: 0.1.99
|
|
4
|
+
Summary: YAML-driven workflow engine with AI agent integration for building conversational SOPs
|
|
5
|
+
Author: Arvind Thangamani
|
|
6
|
+
License: MIT
|
|
7
|
+
License-File: LICENSE
|
|
8
|
+
Keywords: agent,ai,conversational,langgraph,sop,soprano,workflow
|
|
9
|
+
Classifier: Development Status :: 3 - Alpha
|
|
10
|
+
Classifier: Intended Audience :: Developers
|
|
11
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Requires-Python: >=3.12
|
|
15
|
+
Requires-Dist: agno>=2.0.7
|
|
16
|
+
Requires-Dist: crewai>=0.186.1
|
|
17
|
+
Requires-Dist: jsonschema>=4.0.0
|
|
18
|
+
Requires-Dist: langchain-community>=0.4.1
|
|
19
|
+
Requires-Dist: langchain-core>=0.3.67
|
|
20
|
+
Requires-Dist: langchain-openai>=1.0.3
|
|
21
|
+
Requires-Dist: langchain>=1.0.7
|
|
22
|
+
Requires-Dist: langfuse>=3.10.1
|
|
23
|
+
Requires-Dist: langgraph==1.0.2
|
|
24
|
+
Requires-Dist: openai>=1.92.1
|
|
25
|
+
Requires-Dist: pydantic-ai>=1.22.0
|
|
26
|
+
Requires-Dist: pydantic>=2.0.0
|
|
27
|
+
Requires-Dist: pytest>=9.0.1
|
|
28
|
+
Requires-Dist: pyyaml>=6.0
|
|
29
|
+
Provides-Extra: dev
|
|
30
|
+
Requires-Dist: gradio>=5.46.0; extra == 'dev'
|
|
31
|
+
Requires-Dist: pytest>=7.0.0; extra == 'dev'
|
|
32
|
+
Provides-Extra: persistence
|
|
33
|
+
Requires-Dist: langgraph-checkpoint-mongodb>=0.2.0; extra == 'persistence'
|
|
34
|
+
Requires-Dist: pymongo>=4.0.0; extra == 'persistence'
|
|
35
|
+
Provides-Extra: supervisors
|
|
36
|
+
Requires-Dist: crewai>=0.1.0; extra == 'supervisors'
|
|
37
|
+
Requires-Dist: langchain-openai>=0.3.34; extra == 'supervisors'
|
|
38
|
+
Description-Content-Type: text/markdown
|
|
39
|
+
|
|
40
|
+
# Conversational SOP Framework
|
|
41
|
+
|
|
42
|
+
A YAML-driven workflow engine with AI agent integration for building conversational Standard Operating Procedures (SOPs).
|
|
43
|
+
|
|
44
|
+
## Features
|
|
45
|
+
|
|
46
|
+
- **YAML Configuration**: Define workflows declaratively using YAML
|
|
47
|
+
- **AI Agent Integration**: Built-in support for conversational data collection using OpenAI models
|
|
48
|
+
- **State Management**: Powered by LangGraph for robust workflow execution
|
|
49
|
+
- **External Context Injection**: Support for pre-populated fields from external orchestrators
|
|
50
|
+
- **Pattern Matching**: Flexible transition logic based on patterns and conditions
|
|
51
|
+
- **Visualization**: Generate workflow graphs as images or Mermaid diagrams
|
|
52
|
+
|
|
53
|
+
## Installation
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
pip install conversational-sop-framework
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Or using uv:
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uv add conversational-sop-framework
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
## Quick Start
|
|
66
|
+
|
|
67
|
+
### 1. Define a Workflow in YAML
|
|
68
|
+
|
|
69
|
+
```yaml
|
|
70
|
+
name: "User Greeting Workflow"
|
|
71
|
+
description: "Collects user information and provides a personalized greeting"
|
|
72
|
+
version: "1.0"
|
|
73
|
+
|
|
74
|
+
data:
|
|
75
|
+
- name: name
|
|
76
|
+
type: text
|
|
77
|
+
description: "User's name"
|
|
78
|
+
- name: age
|
|
79
|
+
type: number
|
|
80
|
+
description: "User's age in years"
|
|
81
|
+
|
|
82
|
+
steps:
|
|
83
|
+
- id: get_name
|
|
84
|
+
action: collect_input_with_agent
|
|
85
|
+
field: name
|
|
86
|
+
max_attempts: 3
|
|
87
|
+
agent:
|
|
88
|
+
name: "NameCollector"
|
|
89
|
+
model: "gpt-4o-mini"
|
|
90
|
+
instructions: |
|
|
91
|
+
Your goal is to capture the user's name.
|
|
92
|
+
Start with a friendly greeting and ask for their name.
|
|
93
|
+
Once you have a clear name, respond with: 'NAME_CAPTURED: [name]'
|
|
94
|
+
transitions:
|
|
95
|
+
- pattern: "NAME_CAPTURED:"
|
|
96
|
+
next: get_age
|
|
97
|
+
- pattern: "NAME_FAILED:"
|
|
98
|
+
next: end_failed
|
|
99
|
+
|
|
100
|
+
- id: get_age
|
|
101
|
+
action: collect_input_with_agent
|
|
102
|
+
field: age
|
|
103
|
+
max_attempts: 3
|
|
104
|
+
agent:
|
|
105
|
+
name: "AgeCollector"
|
|
106
|
+
model: "gpt-4o-mini"
|
|
107
|
+
instructions: |
|
|
108
|
+
Ask for the user's age.
|
|
109
|
+
Once you have a valid age, respond with: 'AGE_CAPTURED: [age]'
|
|
110
|
+
transitions:
|
|
111
|
+
- pattern: "AGE_CAPTURED:"
|
|
112
|
+
next: end_success
|
|
113
|
+
- pattern: "AGE_FAILED:"
|
|
114
|
+
next: end_failed
|
|
115
|
+
|
|
116
|
+
outcomes:
|
|
117
|
+
- id: end_success
|
|
118
|
+
type: success
|
|
119
|
+
message: "Hello {name}! You are {age} years old."
|
|
120
|
+
|
|
121
|
+
- id: end_failed
|
|
122
|
+
type: failure
|
|
123
|
+
message: "Sorry, I couldn't complete the workflow."
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### 2. Load and Execute the Workflow
|
|
127
|
+
|
|
128
|
+
```python
|
|
129
|
+
from soprano_sdk import load_workflow
|
|
130
|
+
from langgraph.types import Command
|
|
131
|
+
import uuid
|
|
132
|
+
|
|
133
|
+
# Load workflow
|
|
134
|
+
graph, engine = load_workflow("greeting_workflow.yaml")
|
|
135
|
+
|
|
136
|
+
# Setup execution
|
|
137
|
+
thread_id = str(uuid.uuid4())
|
|
138
|
+
config = {"configurable": {"thread_id": thread_id}}
|
|
139
|
+
|
|
140
|
+
# Start workflow
|
|
141
|
+
result = graph.invoke({}, config=config)
|
|
142
|
+
|
|
143
|
+
# Interaction loop
|
|
144
|
+
while True:
|
|
145
|
+
if "__interrupt__" in result and result["__interrupt__"]:
|
|
146
|
+
# Get prompt from workflow
|
|
147
|
+
prompt = result["__interrupt__"][0].value
|
|
148
|
+
print(f"Bot: {prompt}")
|
|
149
|
+
|
|
150
|
+
# Get user input
|
|
151
|
+
user_input = input("You: ")
|
|
152
|
+
|
|
153
|
+
# Resume workflow with user input
|
|
154
|
+
result = graph.invoke(Command(resume=user_input), config=config)
|
|
155
|
+
else:
|
|
156
|
+
# Workflow completed
|
|
157
|
+
message = engine.get_outcome_message(result)
|
|
158
|
+
print(f"Bot: {message}")
|
|
159
|
+
break
|
|
160
|
+
```
|
|
161
|
+
|
|
162
|
+
### 3. External Context Injection
|
|
163
|
+
|
|
164
|
+
You can inject external context into workflows:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
# Pre-populate fields from external orchestrator
|
|
168
|
+
result = graph.invoke({
|
|
169
|
+
"name": "Alice",
|
|
170
|
+
"age": 30
|
|
171
|
+
}, config=config)
|
|
172
|
+
|
|
173
|
+
# Workflow will automatically skip collection steps
|
|
174
|
+
# and proceed to validation/processing
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 4. Persistence
|
|
178
|
+
|
|
179
|
+
The library supports pluggable persistence through LangGraph's checkpointer system.
|
|
180
|
+
|
|
181
|
+
#### In-Memory (Default)
|
|
182
|
+
|
|
183
|
+
```python
|
|
184
|
+
# No persistence - state lost when process ends
|
|
185
|
+
graph, engine = load_workflow("workflow.yaml")
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
#### MongoDB Persistence
|
|
189
|
+
|
|
190
|
+
```python
|
|
191
|
+
from soprano_sdk import load_workflow
|
|
192
|
+
from langgraph.checkpoint.mongodb import MongoDBSaver
|
|
193
|
+
from pymongo import MongoClient
|
|
194
|
+
|
|
195
|
+
# Setup MongoDB persistence (local)
|
|
196
|
+
client = MongoClient("mongodb://localhost:27017")
|
|
197
|
+
checkpointer = MongoDBSaver(client=client, db_name="workflows")
|
|
198
|
+
|
|
199
|
+
# Or MongoDB Atlas (cloud)
|
|
200
|
+
client = MongoClient("mongodb+srv://user:pass@cluster.mongodb.net")
|
|
201
|
+
checkpointer = MongoDBSaver(client=client, db_name="workflows")
|
|
202
|
+
|
|
203
|
+
# Load workflow with persistence
|
|
204
|
+
graph, engine = load_workflow("workflow.yaml", checkpointer=checkpointer)
|
|
205
|
+
|
|
206
|
+
# Execute with thread_id for state tracking
|
|
207
|
+
config = {"configurable": {"thread_id": "user-123-return"}}
|
|
208
|
+
result = graph.invoke({}, config=config)
|
|
209
|
+
|
|
210
|
+
# Later, resume using same thread_id
|
|
211
|
+
result = graph.invoke(Command(resume="continue"), config=config)
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
#### Thread ID Strategies
|
|
215
|
+
|
|
216
|
+
Choose a thread_id strategy based on your use case:
|
|
217
|
+
|
|
218
|
+
| Strategy | Thread ID Pattern | Best For |
|
|
219
|
+
|----------|-------------------|----------|
|
|
220
|
+
| **Entity-Based** | `f"return_{order_id}"` | One workflow per business entity |
|
|
221
|
+
| **Conversation** | `str(uuid.uuid4())` | Multiple concurrent workflows |
|
|
222
|
+
| **User+Workflow** | `f"{user_id}_{workflow_type}"` | One workflow type per user |
|
|
223
|
+
| **Session-Based** | `session_id` | Web apps with sessions |
|
|
224
|
+
|
|
225
|
+
**Examples**: See `examples/persistence/` for detailed examples of each strategy.
|
|
226
|
+
|
|
227
|
+
## Workflow Actions
|
|
228
|
+
|
|
229
|
+
### collect_input_with_agent
|
|
230
|
+
|
|
231
|
+
Collects user input using an AI agent with conversation history.
|
|
232
|
+
|
|
233
|
+
```yaml
|
|
234
|
+
- id: collect_field
|
|
235
|
+
action: collect_input_with_agent
|
|
236
|
+
field: field_name
|
|
237
|
+
max_attempts: 5
|
|
238
|
+
agent:
|
|
239
|
+
name: "CollectorAgent"
|
|
240
|
+
model: "gpt-4o-mini"
|
|
241
|
+
instructions: |
|
|
242
|
+
Instructions for the agent...
|
|
243
|
+
transitions:
|
|
244
|
+
- pattern: "SUCCESS:"
|
|
245
|
+
next: next_step
|
|
246
|
+
- pattern: "FAILED:"
|
|
247
|
+
next: failure_outcome
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### call_function
|
|
251
|
+
|
|
252
|
+
Calls a Python function with workflow state.
|
|
253
|
+
|
|
254
|
+
```yaml
|
|
255
|
+
- id: process_data
|
|
256
|
+
action: call_function
|
|
257
|
+
function: "my_module.my_function"
|
|
258
|
+
inputs:
|
|
259
|
+
field1: "{field_name}"
|
|
260
|
+
field2: "static_value"
|
|
261
|
+
output: result_field
|
|
262
|
+
transitions:
|
|
263
|
+
- condition: true
|
|
264
|
+
next: success_step
|
|
265
|
+
- condition: false
|
|
266
|
+
next: failure_step
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
## Examples
|
|
270
|
+
|
|
271
|
+
See the `examples/` directory for complete workflow examples:
|
|
272
|
+
|
|
273
|
+
- `greeting_workflow.yaml` - Simple user greeting workflow
|
|
274
|
+
- `return_workflow.yaml` - Customer return processing workflow
|
|
275
|
+
- Function modules with business logic (`greeting_functions.py`, `return_functions.py`)
|
|
276
|
+
- `persistence/` - Persistence strategy examples (entity-based, conversation-based, SQLite demo)
|
|
277
|
+
|
|
278
|
+
## Running Workflows
|
|
279
|
+
|
|
280
|
+
### CLI Demo
|
|
281
|
+
|
|
282
|
+
```bash
|
|
283
|
+
# Basic usage (in-memory)
|
|
284
|
+
python scripts/workflow_demo.py examples/greeting_workflow.yaml
|
|
285
|
+
|
|
286
|
+
# With MongoDB persistence (local)
|
|
287
|
+
python scripts/workflow_demo.py examples/greeting_workflow.yaml --mongodb mongodb://localhost:27017
|
|
288
|
+
|
|
289
|
+
# Resume existing workflow
|
|
290
|
+
python scripts/workflow_demo.py examples/greeting_workflow.yaml --mongodb mongodb://localhost:27017 --thread-id abc-123
|
|
291
|
+
|
|
292
|
+
# With MongoDB Atlas
|
|
293
|
+
python scripts/workflow_demo.py examples/greeting_workflow.yaml --mongodb mongodb+srv://user:pass@cluster.mongodb.net
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
### Gradio UI
|
|
297
|
+
|
|
298
|
+
```bash
|
|
299
|
+
# Basic usage (in-memory)
|
|
300
|
+
python scripts/workflow_demo_ui.py examples/greeting_workflow.yaml
|
|
301
|
+
|
|
302
|
+
# With MongoDB persistence
|
|
303
|
+
python scripts/workflow_demo_ui.py examples/greeting_workflow.yaml --mongodb mongodb://localhost:27017
|
|
304
|
+
|
|
305
|
+
# With MongoDB Atlas
|
|
306
|
+
python scripts/workflow_demo_ui.py examples/greeting_workflow.yaml --mongodb mongodb+srv://user:pass@cluster.mongodb.net
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
### Persistence Examples
|
|
310
|
+
|
|
311
|
+
```bash
|
|
312
|
+
cd examples/persistence
|
|
313
|
+
|
|
314
|
+
# Entity-based (order ID as thread ID)
|
|
315
|
+
python entity_based.py ORDER-123
|
|
316
|
+
|
|
317
|
+
# Conversation-based (UUID with supervisor pattern)
|
|
318
|
+
python conversation_based.py ../return_workflow.yaml --order-id ORDER-456
|
|
319
|
+
|
|
320
|
+
# MongoDB demo with pause/resume
|
|
321
|
+
python mongodb_demo.py
|
|
322
|
+
|
|
323
|
+
# Use MongoDB Atlas
|
|
324
|
+
python mongodb_demo.py --mongodb mongodb+srv://user:pass@cluster.mongodb.net
|
|
325
|
+
```
|
|
326
|
+
|
|
327
|
+
### Visualize Workflow
|
|
328
|
+
|
|
329
|
+
```bash
|
|
330
|
+
python scripts/visualize_workflow.py examples/greeting_workflow.yaml
|
|
331
|
+
```
|
|
332
|
+
|
|
333
|
+
## Development
|
|
334
|
+
|
|
335
|
+
### Setup
|
|
336
|
+
|
|
337
|
+
```bash
|
|
338
|
+
git clone https://github.com/dnivra26/soprano_sdk_framework.git
|
|
339
|
+
cd soprano_sdk_framework
|
|
340
|
+
uv sync --dev
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
### Run Tests
|
|
344
|
+
|
|
345
|
+
```bash
|
|
346
|
+
python tests/test_external_values.py
|
|
347
|
+
```
|
|
348
|
+
|
|
349
|
+
## Architecture
|
|
350
|
+
|
|
351
|
+
- **soprano_sdk/**: Core library package
|
|
352
|
+
- `engine.py`: Workflow engine implementation
|
|
353
|
+
- `__init__.py`: Public API exports
|
|
354
|
+
|
|
355
|
+
- **examples/**: Example workflows and persistence patterns
|
|
356
|
+
- Workflow YAML definitions
|
|
357
|
+
- Function modules with business logic
|
|
358
|
+
- `persistence/`: Different persistence strategy examples
|
|
359
|
+
|
|
360
|
+
- **scripts/**: Utility tools for running and visualizing workflows
|
|
361
|
+
- `workflow_demo.py`: CLI runner with persistence support
|
|
362
|
+
- `workflow_demo_ui.py`: Gradio UI with thread management
|
|
363
|
+
- `visualize_workflow.py`: Workflow graph generator
|
|
364
|
+
|
|
365
|
+
- **tests/**: Test suite
|
|
366
|
+
- **legacy/**: Previous implementations (FSM, direct LangGraph)
|
|
367
|
+
|
|
368
|
+
## Requirements
|
|
369
|
+
|
|
370
|
+
### Core Dependencies
|
|
371
|
+
|
|
372
|
+
- Python >= 3.12
|
|
373
|
+
- agno >= 2.0.7
|
|
374
|
+
- langgraph >= 0.6.8
|
|
375
|
+
- openai >= 1.108.1
|
|
376
|
+
- pyyaml >= 6.0
|
|
377
|
+
|
|
378
|
+
### Optional Dependencies
|
|
379
|
+
|
|
380
|
+
For MongoDB persistence:
|
|
381
|
+
```bash
|
|
382
|
+
# Using pip
|
|
383
|
+
pip install langgraph-checkpoint-mongodb pymongo
|
|
384
|
+
|
|
385
|
+
# Using uv (recommended)
|
|
386
|
+
uv add langgraph-checkpoint-mongodb pymongo --optional persistence
|
|
387
|
+
|
|
388
|
+
# Or install library with persistence support
|
|
389
|
+
pip install conversational-sop-framework[persistence]
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
For development (includes Gradio UI and tests):
|
|
393
|
+
```bash
|
|
394
|
+
pip install conversational-sop-framework[dev]
|
|
395
|
+
# or
|
|
396
|
+
uv sync --dev
|
|
397
|
+
```
|
|
398
|
+
|
|
399
|
+
## License
|
|
400
|
+
|
|
401
|
+
MIT
|
|
402
|
+
|
|
403
|
+
## Contributing
|
|
404
|
+
|
|
405
|
+
Contributions are welcome! Please open an issue or submit a pull request.
|
|
406
|
+
|
|
407
|
+
## To Do
|
|
408
|
+
|
|
409
|
+
- ✅ Database persistence (SqliteSaver, PostgresSaver supported)
|
|
410
|
+
- ✅ Pluggable checkpointer system
|
|
411
|
+
- ✅ Thread ID strategies and examples
|
|
412
|
+
- Additional action types (webhook, conditional branching, parallel execution)
|
|
413
|
+
- More workflow examples (customer onboarding, support ticketing, approval flows)
|
|
414
|
+
- Workflow testing utilities
|
|
415
|
+
- Metrics and monitoring hooks
|
|
416
|
+
|
|
417
|
+
## Links
|
|
418
|
+
|
|
419
|
+
- [GitHub Repository](https://github.com/dnivra26/soprano_sdk_framework)
|
|
420
|
+
- [Issues](https://github.com/dnivra26/soprano_sdk_framework/issues)
|