Skip to content

Commit 7aedbaf

Browse files
committed
Update tutorials
1 parent f8fb7cd commit 7aedbaf

File tree

5 files changed

+508
-96
lines changed

5 files changed

+508
-96
lines changed

bindings/ceylon/examples/llm/simple_app.py

-96
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
# Copyright 2024-Present, Syigen Ltd. and Syigen Private Limited. All rights reserved.
2+
# Licensed under the Apache License, Version 2.0 (See LICENSE.md or http://www.apache.org/licenses/LICENSE-2.0).
3+
#
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
# Step-by-Step Tutorial: Ceylon ProcessPlayGround with ProcessWorker
2+
3+
This tutorial will guide you through creating a simple text processing application using Ceylon's ProcessPlayGround and
4+
ProcessWorker. We'll build a system that converts text to uppercase.
5+
6+
## Prerequisites
7+
8+
1. Python 3.7 or higher installed
9+
2. Ceylon package installed
10+
3. Basic understanding of Python async/await
11+
12+
## Step 1: Project Setup
13+
14+
First, create a new directory for your project and create a new Python file:
15+
16+
```bash
17+
mkdir ceylon_tutorial
18+
cd ceylon_tutorial
19+
touch uppercase_processor.py
20+
```
21+
22+
## Step 2: Import Required Dependencies
23+
24+
Open `uppercase_processor.py` and add the necessary imports:
25+
26+
```python
27+
import asyncio
28+
from typing import Any
29+
from ceylon.processor.agent import ProcessWorker
30+
from ceylon.processor.playground import ProcessPlayGround
31+
from ceylon.processor.data import ProcessRequest, ProcessResponse, ProcessState
32+
```
33+
34+
## Step 3: Create the ProcessWorker
35+
36+
Create a custom ProcessWorker class that will handle the text conversion:
37+
38+
```python
39+
class UpperCaseProcessor(ProcessWorker):
40+
"""A simple processor that converts input text to uppercase"""
41+
42+
async def _processor(self, request: ProcessRequest, time: int) -> tuple[Any, dict]:
43+
"""Process the input text by converting it to uppercase"""
44+
try:
45+
# Convert input to string and make uppercase
46+
if isinstance(request.data, str):
47+
result = request.data.upper()
48+
else:
49+
result = str(request.data).upper()
50+
51+
# Return result and empty metadata
52+
return result, {}
53+
54+
except Exception as e:
55+
raise Exception(f"Error processing text: {str(e)}")
56+
```
57+
58+
Key points about the ProcessWorker:
59+
60+
- Inherits from `ProcessWorker`
61+
- Takes a name parameter in `__init__`
62+
- Implements `_processor` method that receives a request and returns a tuple of (result, metadata)
63+
64+
## Step 4: Create the Main Function
65+
66+
Add the main function that sets up and runs the playground:
67+
68+
```python
69+
async def main():
70+
# Create playground and worker
71+
playground = ProcessPlayGround(name="text_playground", port=8888)
72+
worker = UpperCaseProcessor()
73+
74+
# Start playground with worker
75+
async with playground.play(workers=[worker]) as pg:
76+
# Create a process request
77+
request = ProcessRequest(
78+
task_type="uppercase_processor",
79+
data="Hello, World!"
80+
)
81+
82+
# Send request and wait for response
83+
response = await pg.process_request(request)
84+
85+
# Print results
86+
print(f"Original text: {request.data}")
87+
print(f"Processed text: {response.result}")
88+
print(f"Process status: {response.status}")
89+
90+
# Signal playground to finish
91+
await pg.finish()
92+
```
93+
94+
## Step 5: Add Entry Point
95+
96+
Add the entry point at the bottom of the file:
97+
98+
```python
99+
if __name__ == "__main__":
100+
# Run the example
101+
asyncio.run(main())
102+
```
103+
104+
## Understanding the Components
105+
106+
### ProcessPlayGround
107+
108+
- Acts as a central hub for processing requests
109+
- Manages workers and their connections
110+
- Handles message routing between components
111+
112+
### ProcessWorker
113+
114+
- Performs the actual processing work
115+
- Defines processing logic in `_processor` method
116+
- Can handle specific types of requests based on role
117+
118+
### ProcessRequest
119+
120+
- Contains the data to be processed
121+
- Includes task type that matches worker role
122+
- Can include additional metadata
123+
124+
### ProcessResponse
125+
126+
- Contains the processed result
127+
- Includes status (SUCCESS/ERROR)
128+
- Can include error messages and metadata
129+
130+
## Running the Example
131+
132+
1. Save all the code in `uppercase_processor.py`
133+
2. Open a terminal in your project directory
134+
3. Run the script:
135+
136+
```bash
137+
python uppercase_processor.py
138+
```
139+
140+
Expected output:
141+
142+
```
143+
Original text: Hello, World!
144+
Processed text: HELLO, WORLD!
145+
Process status: ProcessState.SUCCESS
146+
```
147+
148+
## Common Issues and Solutions
149+
150+
1. **Port Already in Use**
151+
- Error: "Address already in use"
152+
- Solution: Change the port number in playground initialization
153+
154+
2. **Worker Not Connected**
155+
- Error: "No worker available for task type"
156+
- Solution: Ensure worker role matches task_type in request
157+
158+
3. **Async Context Issues**
159+
- Error: "Event loop is closed"
160+
- Solution: Ensure all async code is within the main function
161+
162+
## Next Steps
163+
164+
1. Add error handling:
165+
166+
```python
167+
try:
168+
response = await pg.process_request(request)
169+
except Exception as e:
170+
print(f"Error processing request: {e}")
171+
```
172+
173+
2. Process multiple requests:
174+
175+
```python
176+
requests = [
177+
ProcessRequest(task_type="uppercase_processor", data="first request"),
178+
ProcessRequest(task_type="uppercase_processor", data="second request")
179+
]
180+
for request in requests:
181+
response = await pg.process_request(request)
182+
print(response.result)
183+
```
184+
185+
3. Add metadata to track processing time:
186+
187+
```python
188+
import time
189+
190+
191+
async def _processor(self, request: ProcessRequest, time: int) -> tuple[Any, dict]:
192+
start_time = time.time()
193+
result = request.data.upper()
194+
processing_time = time.time() - start_time
195+
return result, {"processing_time": processing_time}
196+
```
197+
198+
## Tips for Production Use
199+
200+
1. Always implement proper error handling
201+
2. Use logging instead of print statements
202+
3. Consider implementing request timeouts
203+
4. Add monitoring and metrics collection
204+
5. Implement proper cleanup in case of failures
205+
206+
## Conclusion
207+
208+
This tutorial covered the basics of creating a Ceylon ProcessPlayGround with a custom ProcessWorker. The example
209+
demonstrates:
210+
211+
- Setting up a processing system
212+
- Creating custom workers
213+
- Handling requests and responses
214+
- Basic error handling
215+
216+
As you build more complex systems, you can extend this pattern to handle different types of data, implement more
217+
sophisticated processing logic, and add additional features like load balancing and error recovery.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
# Copyright 2024-Present, Syigen Ltd. and Syigen Private Limited. All rights reserved.
2+
# Licensed under the Apache License, Version 2.0 (See LICENSE.md or http://www.apache.org/licenses/LICENSE-2.0).
3+
#
4+
import asyncio
5+
from typing import Any
6+
7+
from ceylon.processor.agent import ProcessWorker
8+
from ceylon.processor.data import ProcessRequest
9+
from ceylon.processor.playground import ProcessPlayGround
10+
11+
12+
class UpperCaseProcessor(ProcessWorker):
13+
14+
async def _processor(self, request: ProcessRequest, time: int) -> tuple[Any, dict]:
15+
"""Process the input text by converting it to uppercase"""
16+
try:
17+
# Convert input to string and make uppercase
18+
if isinstance(request.data, str):
19+
result = request.data.upper()
20+
else:
21+
result = str(request.data).upper()
22+
23+
# Return result and empty metadata
24+
return result, {}
25+
26+
except Exception as e:
27+
raise Exception(f"Error processing text: {str(e)}")
28+
29+
30+
async def main():
31+
# Create playground and worker
32+
playground = ProcessPlayGround(name="text_playground", port=8888)
33+
worker = UpperCaseProcessor(name="uppercase_worker", role="uppercase_processor")
34+
35+
# Start playground with worker
36+
async with playground.play(workers=[worker]) as pg:
37+
# Create a process request
38+
request = ProcessRequest(
39+
task_type="uppercase_processor",
40+
data="Hello, World!"
41+
)
42+
43+
# Send request and wait for response
44+
response = await pg.process_request(request)
45+
46+
# Print results
47+
print(f"Original text: {request.data}")
48+
print(f"Processed text: {response.result}")
49+
print(f"Process status: {response.status}")
50+
51+
# Signal playground to finish
52+
await pg.finish()
53+
54+
55+
if __name__ == "__main__":
56+
# Run the example
57+
asyncio.run(main())

0 commit comments

Comments
 (0)