Skip to content

Commit 2a51a3c

Browse files
committed
Add an example of the Chaining workflow
1 parent e1453d0 commit 2a51a3c

File tree

3 files changed

+194
-0
lines changed

3 files changed

+194
-0
lines changed

README.md

Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,91 @@ python translator.py
111111

112112
## Patterns
113113

114+
### Workflow: Chaining
115+
116+
**Chaining** decomposes a task into a sequence of steps, where each agent processes the output of the previous one.
117+
118+
<p align="center">
119+
<img src="assets/patterns-chaining.png">
120+
</p>
121+
122+
**When to use this workflow:** This workflow is ideal for situations where the task can be easily and cleanly decomposed into fixed subtasks. The main goal is to trade off latency for higher accuracy, by making each agent an easier task.
123+
124+
**Example** (see [examples/patterns/chaining.py](examples/patterns/chaining.py) for a runnable example):
125+
126+
```python
127+
from coagent.agents import ChatAgent, StreamChatAgent, Sequential, ModelClient
128+
from coagent.core import AgentSpec, new
129+
130+
client = ModelClient(...)
131+
132+
extractor = AgentSpec(
133+
"extractor",
134+
new(
135+
ChatAgent,
136+
system="""\
137+
Extract only the numerical values and their associated metrics from the text.
138+
Format each as 'value: metric' on a new line.
139+
Example format:
140+
92: customer satisfaction
141+
45%: revenue growth\
142+
""",
143+
client=client,
144+
),
145+
)
146+
147+
converter = AgentSpec(
148+
"converter",
149+
new(
150+
ChatAgent,
151+
system="""\
152+
Convert all numerical values to percentages where possible.
153+
If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
154+
Keep one number per line.
155+
Example format:
156+
92%: customer satisfaction
157+
45%: revenue growth\
158+
""",
159+
client=client,
160+
),
161+
)
162+
163+
sorter = AgentSpec(
164+
"sorter",
165+
new(
166+
ChatAgent,
167+
system="""\
168+
Sort all lines in descending order by numerical value.
169+
Keep the format 'value: metric' on each line.
170+
Example:
171+
92%: customer satisfaction
172+
87%: employee satisfaction\
173+
""",
174+
client=client,
175+
),
176+
)
177+
178+
formatter = AgentSpec(
179+
"formatter",
180+
new(
181+
StreamChatAgent,
182+
system="""\
183+
Format the sorted data as a markdown table with columns:
184+
| Metric | Value |
185+
|:--|--:|
186+
| Customer Satisfaction | 92% |\
187+
""",
188+
client=client,
189+
),
190+
)
191+
192+
chain = AgentSpec(
193+
"chain", new(Sequential, "extractor", "converter", "sorter", "formatter")
194+
)
195+
```
196+
197+
### Agents
198+
114199
TODO
115200

116201

assets/patterns-chaining.png

30.2 KB
Loading

examples/patterns/chaining.py

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
import asyncio
2+
import os
3+
4+
from coagent.agents import ChatAgent, StreamChatAgent, Sequential, ModelClient
5+
from coagent.agents.messages import ChatMessage
6+
from coagent.core import AgentSpec, new, set_stderr_logger
7+
from coagent.runtimes import LocalRuntime
8+
9+
client = ModelClient(
10+
model=os.getenv("MODEL_NAME"),
11+
api_base=os.getenv("MODEL_API_BASE"),
12+
api_version=os.getenv("MODEL_API_VERSION"),
13+
api_key=os.getenv("MODEL_API_KEY"),
14+
)
15+
16+
extractor = AgentSpec(
17+
"extractor",
18+
new(
19+
ChatAgent,
20+
system="""\
21+
Extract only the numerical values and their associated metrics from the text.
22+
Format each as 'value: metric' on a new line.
23+
Example format:
24+
92: customer satisfaction
25+
45%: revenue growth\
26+
""",
27+
client=client,
28+
),
29+
)
30+
31+
converter = AgentSpec(
32+
"converter",
33+
new(
34+
ChatAgent,
35+
system="""\
36+
Convert all numerical values to percentages where possible.
37+
If not a percentage or points, convert to decimal (e.g., 92 points -> 92%).
38+
Keep one number per line.
39+
Example format:
40+
92%: customer satisfaction
41+
45%: revenue growth\
42+
""",
43+
client=client,
44+
),
45+
)
46+
47+
sorter = AgentSpec(
48+
"sorter",
49+
new(
50+
ChatAgent,
51+
system="""\
52+
Sort all lines in descending order by numerical value.
53+
Keep the format 'value: metric' on each line.
54+
Example:
55+
92%: customer satisfaction
56+
87%: employee satisfaction\
57+
""",
58+
client=client,
59+
),
60+
)
61+
62+
formatter = AgentSpec(
63+
"formatter",
64+
new(
65+
StreamChatAgent,
66+
system="""\
67+
Format the sorted data as a markdown table with columns:
68+
| Metric | Value |
69+
|:--|--:|
70+
| Customer Satisfaction | 92% |\
71+
""",
72+
client=client,
73+
),
74+
)
75+
76+
chain = AgentSpec(
77+
"chain", new(Sequential, "extractor", "converter", "sorter", "formatter")
78+
)
79+
80+
81+
async def main():
82+
async with LocalRuntime() as runtime:
83+
for spec in [extractor, converter, sorter, formatter, chain]:
84+
await runtime.register_spec(spec)
85+
86+
result = chain.run_stream(
87+
ChatMessage(
88+
role="user",
89+
content="""\
90+
Q3 Performance Summary:
91+
Our customer satisfaction score rose to 92 points this quarter.
92+
Revenue grew by 45% compared to last year.
93+
Market share is now at 23% in our primary market.
94+
Customer churn decreased to 5% from 8%.
95+
New user acquisition cost is $43 per user.
96+
Product adoption rate increased to 78%.
97+
Employee satisfaction is at 87 points.
98+
Operating margin improved to 34%.\
99+
""",
100+
).encode()
101+
)
102+
async for chunk in result:
103+
msg = ChatMessage.decode(chunk)
104+
print(msg.content, end="", flush=True)
105+
106+
107+
if __name__ == "__main__":
108+
set_stderr_logger()
109+
asyncio.run(main())

0 commit comments

Comments
 (0)