Skip to content

Commit 08074c9

Browse files
committed
Finish the example
1 parent d40c812 commit 08074c9

File tree

7 files changed

+99
-28
lines changed

7 files changed

+99
-28
lines changed

re_act/README.md

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
# Restack AI - ReAct Example
2+
3+
## Prerequisites
4+
5+
- Python 3.11
6+
- Poetry (for dependency management)
7+
- Docker (for running the Restack services)
8+
9+
## Usage
10+
11+
2. Open the web UI to see the workflows:
12+
13+
```bash
14+
http://localhost:5233
15+
```
16+
17+
3. Clone this repository:
18+
19+
```bash
20+
git clone https://github.com/restackio/examples-python
21+
cd examples-python/re_act
22+
```
23+
24+
4. Install dependencies using Poetry:
25+
26+
```bash
27+
poetry env use 3.11
28+
```
29+
30+
```bash
31+
poetry shell
32+
```
33+
34+
```bash
35+
poetry install
36+
```
37+
38+
```bash
39+
poetry env info # Optional: copy the interpreter path to use in your IDE (e.g. Cursor, VSCode, etc.)
40+
```
41+
42+
5. Run the services:
43+
44+
```bash
45+
poetry run services
46+
```
47+
48+
6. Schedule workflow
49+
50+
```bash
51+
poetry run schedule_workflow
52+
```
53+

re_act/schedule_workflow.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,11 @@ async def main():
99
workflow_id = f"{int(time.time() * 1000)}-ParentWorkflow"
1010
runId = await client.schedule_workflow(
1111
workflow_name="ParentWorkflow",
12-
workflow_id=workflow_id
12+
workflow_id=workflow_id,
13+
input={
14+
"email": "[email protected]",
15+
"current_accepted_applicants_count": 9
16+
}
1317
)
1418

1519
await client.get_workflow_result(

re_act/src/functions/generate_email_content.py

Lines changed: 25 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,23 +12,30 @@ class GenerateEmailInput:
1212

1313
@function.defn()
1414
async def generate_email_content(input: GenerateEmailInput):
15-
16-
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
1715

18-
response = client.chat.completions.create(
19-
model="gpt-4o-mini",
20-
messages=[
21-
{
22-
"role": "system",
23-
"content": "You are a helpful assistant that generates short emails based on the provided context."
24-
},
25-
{
26-
"role": "user",
27-
"content": f"Generate a short email based on the following context: {input.email_context}"
28-
}
29-
],
30-
max_tokens=150
31-
)
32-
33-
return response.choices[0].message.content
16+
try:
17+
client = OpenAI(api_key=os.environ.get("OPENAI_API_KEY"))
18+
19+
response = client.chat.completions.create(
20+
model="gpt-4o-mini",
21+
messages=[
22+
{
23+
"role": "system",
24+
"content": f"""
25+
You are a helpful assistant that generates short emails based on the provided context.
26+
"""
27+
},
28+
{
29+
"role": "user",
30+
"content": f"""Generate a short email based on the following context: {input.email_context}
31+
"""
32+
}
33+
],
34+
max_tokens=150
35+
)
36+
37+
return response.choices[0].message.content
38+
except Exception as e:
39+
log.error("Failed to generate email content", error=e)
40+
raise FunctionFailure("Failed to generate email content", non_retryable=True)
3441

re_act/src/functions/send_email.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,4 +36,4 @@ async def send_email(input: SendEmailInput):
3636
sg.send(message)
3737
except Exception as e:
3838
log.error("Failed to send email", error=e)
39-
raise e
39+
raise FunctionFailure("Failed to send email", non_retryable=True)

re_act/src/workflows/child_workflow_a.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
@workflow.defn()
1010
class ChildWorkflowA:
1111
@workflow.run
12-
async def run(self):
13-
log.info(f"Sending email to [email protected]")
12+
async def run(self, email: str):
13+
log.info(f"Sending email to {email}")
1414

1515
text = await workflow.step(
1616
generate_email_content,

re_act/src/workflows/child_workflow_b.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
@workflow.defn()
1010
class ChildWorkflowB:
1111
@workflow.run
12-
async def run(self):
13-
log.info(f"Sending email to [email protected]")
12+
async def run(self, email: str):
13+
log.info(f"Sending email to {email}")
1414

1515
text = await workflow.step(
1616
generate_email_content,

re_act/src/workflows/parent_workflow.py

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,29 @@
11
from restack_ai.workflow import workflow, log, workflow_info, import_functions
22
from datetime import timedelta
33
import json
4-
4+
from dataclasses import dataclass
55
from .child_workflow_a import ChildWorkflowA
66
from .child_workflow_b import ChildWorkflowB
77

88
with import_functions():
99
from src.functions.decide import decide, DecideInput
1010

11+
@dataclass
12+
class ParentWorkflowInput:
13+
email: str
14+
current_accepted_applicants_count: int
15+
1116
@workflow.defn()
1217
class ParentWorkflow:
1318
@workflow.run
14-
async def run(self):
19+
async def run(self, input: ParentWorkflowInput):
1520
parent_workflow_id = workflow_info().workflow_id
1621

1722
decide_result = await workflow.step(
1823
decide,
1924
input=DecideInput(
20-
21-
current_accepted_applicants_count=9
25+
email=input.email,
26+
current_accepted_applicants_count=input.current_accepted_applicants_count
2227
),
2328
start_to_close_timeout=timedelta(seconds=120)
2429
)
@@ -30,11 +35,13 @@ async def run(self):
3035
child_workflow_result = await workflow.child_execute(
3136
ChildWorkflowA,
3237
workflow_id=f"{parent_workflow_id}-child-a",
38+
input=input.email
3339
)
3440
elif not decision:
3541
child_workflow_result = await workflow.child_execute(
3642
ChildWorkflowB,
3743
workflow_id=f"{parent_workflow_id}-child-b",
44+
input=input.email
3845
)
3946

4047
return child_workflow_result

0 commit comments

Comments
 (0)