Skip to content

Commit b7c3795

Browse files
committed
Rendering
1 parent 45d8133 commit b7c3795

13 files changed

Lines changed: 392 additions & 94 deletions

File tree

README.md

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -47,55 +47,61 @@ Here's a simple example to get you started:
4747
```ruby
4848
require 'mars'
4949

50-
# Define agents
51-
class Agent1 < Mars::Agent
50+
# Define a RubyLLM agent
51+
class MyAgent < RubyLLM::Agent
52+
model "gpt-4o"
53+
instructions "You are a helpful assistant."
5254
end
5355

54-
class Agent2 < Mars::Agent
56+
# Wrap it in a MARS step
57+
class MyStep < MARS::AgentStep
58+
agent MyAgent
5559
end
5660

57-
class Agent3 < Mars::Agent
58-
end
59-
60-
# Create agents
61-
agent1 = Agent1.new
62-
agent2 = Agent2.new
63-
agent3 = Agent3.new
61+
# Create steps
62+
step1 = MyStep.new(name: "step1")
63+
step2 = MyStep.new(name: "step2")
64+
step3 = MyStep.new(name: "step3")
6465

6566
# Create a sequential workflow
66-
workflow = Mars::Workflows::Sequential.new(
67+
workflow = MARS::Workflows::Sequential.new(
6768
"My First Workflow",
68-
steps: [agent1, agent2, agent3]
69+
steps: [step1, step2, step3]
6970
)
7071

7172
# Run the workflow
72-
result = workflow.run("Your input here")
73+
context = workflow.run("Your input here")
74+
context.current_input # final output
75+
context[:step1] # access any step's output by name
7376
```
7477

7578
## Core Concepts
7679

77-
### Agents
80+
### Agent Steps
7881

79-
Agents are the basic building blocks of MARS. They represent individual units of work:
82+
Agent steps are the basic building blocks of MARS. They wrap a `RubyLLM::Agent` subclass for workflow orchestration:
8083

8184
```ruby
82-
class CustomAgent < Mars::Agent
83-
def system_prompt
84-
"You are a helpful assistant"
85-
end
85+
class ResearcherAgent < RubyLLM::Agent
86+
model "gpt-4o"
87+
instructions "You research topics thoroughly."
88+
tools WebSearch
89+
schema OutputSchema
8690
end
8791

88-
agent = CustomAgent.new(
89-
options: { model: "gpt-4o" }
90-
)
92+
class ResearcherStep < MARS::AgentStep
93+
agent ResearcherAgent
94+
end
95+
96+
step = ResearcherStep.new(name: "researcher")
9197
```
9298

9399
### Sequential Workflows
94100

95101
Execute agents one after another, passing outputs as inputs:
96102

97103
```ruby
98-
sequential = Mars::Workflows::Sequential.new(
104+
sequential = MARS::Workflows::Sequential.new(
99105
"Sequential Pipeline",
100106
steps: [agent1, agent2, agent3]
101107
)
@@ -106,12 +112,12 @@ sequential = Mars::Workflows::Sequential.new(
106112
Run multiple agents concurrently and aggregate their results:
107113

108114
```ruby
109-
aggregator = Mars::Aggregator.new(
115+
aggregator = MARS::Aggregator.new(
110116
"Results Aggregator",
111117
operation: lambda { |results| results.join(", ") }
112118
)
113119

114-
parallel = Mars::Workflows::Parallel.new(
120+
parallel = MARS::Workflows::Parallel.new(
115121
"Parallel Pipeline",
116122
steps: [agent1, agent2, agent3],
117123
aggregator: aggregator
@@ -123,7 +129,7 @@ parallel = Mars::Workflows::Parallel.new(
123129
Create conditional branching in your workflows:
124130

125131
```ruby
126-
gate = Mars::Gate.new(
132+
gate = MARS::Gate.new(
127133
"Decision Gate",
128134
condition: ->(input) { input[:score] > 0.5 ? :success : :failure },
129135
branches: {
@@ -138,7 +144,7 @@ gate = Mars::Gate.new(
138144
Generate Mermaid diagrams to visualize your workflows:
139145

140146
```ruby
141-
diagram = Mars::Rendering::Mermaid.new(workflow).render
147+
diagram = MARS::Rendering::Mermaid.new(workflow).render
142148
File.write("workflow_diagram.md", diagram)
143149
```
144150

@@ -197,7 +203,7 @@ The gem is available as open source under the terms of the [MIT License](https:/
197203

198204
## Code of Conduct
199205

200-
Everyone interacting in the Mars project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rootstrap/mars/blob/main/CODE_OF_CONDUCT.md).
206+
Everyone interacting in the MARS project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/rootstrap/mars/blob/main/CODE_OF_CONDUCT.md).
201207

202208
## Credits
203209

examples/complex_llm_workflow/generator.rb

Lines changed: 36 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -37,48 +37,52 @@ def execute(latitude:, longitude:)
3737
end
3838
end
3939

40-
# Define LLMs
41-
class Agent1 < MARS::Agent
42-
def system_prompt
43-
"You are a helpful assistant that can answer questions.
44-
When asked about a country, only answer with its name."
45-
end
40+
# Define RubyLLM agents
41+
class CountryAgent < RubyLLM::Agent
42+
model "gpt-4o"
43+
instructions "You are a helpful assistant that can answer questions. " \
44+
"When asked about a country, only answer with its name."
4645
end
4746

48-
class Agent2 < MARS::Agent
49-
def system_prompt
50-
"You are a helpful assistant that can answer questions and help with tasks.
51-
Return information about the typical food of the country."
52-
end
47+
class FoodAgent < RubyLLM::Agent
48+
model "gpt-4o"
49+
instructions "You are a helpful assistant. Return information about the typical food of the country."
5350
end
5451

55-
class Agent3 < MARS::Agent
56-
def system_prompt
57-
"You are a helpful assistant that can answer questions and help with tasks.
58-
Return information about the popular sports of the country."
59-
end
52+
class SportsAgent < RubyLLM::Agent
53+
model "gpt-4o"
54+
instructions "You are a helpful assistant. Return information about the popular sports of the country."
55+
schema SportsSchema
56+
end
6057

61-
def schema
62-
SportsSchema.new
63-
end
58+
class WeatherAgent < RubyLLM::Agent
59+
model "gpt-4o"
60+
instructions "You are a helpful assistant. Return the current weather of the country's capital."
61+
tools Weather
6462
end
6563

66-
class Agent4 < MARS::Agent
67-
def system_prompt
68-
"You are a helpful assistant that can answer questions and help with tasks.
69-
Return the current weather of the country's capital."
70-
end
64+
# Define MARS steps wrapping RubyLLM agents
65+
class CountryStep < MARS::AgentStep
66+
agent CountryAgent
67+
end
7168

72-
def tools
73-
[Weather.new]
74-
end
69+
class FoodStep < MARS::AgentStep
70+
agent FoodAgent
71+
end
72+
73+
class SportsStep < MARS::AgentStep
74+
agent SportsAgent
75+
end
76+
77+
class WeatherStep < MARS::AgentStep
78+
agent WeatherAgent
7579
end
7680

77-
# Create the LLMs
78-
llm1 = Agent1.new(options: { model: "gpt-4o" })
79-
llm2 = Agent2.new(options: { model: "gpt-4o" })
80-
llm3 = Agent3.new(options: { model: "gpt-4o" })
81-
llm4 = Agent4.new(options: { model: "gpt-4o" })
81+
# Create the steps
82+
llm1 = CountryStep.new(name: "Country")
83+
llm2 = FoodStep.new(name: "Food")
84+
llm3 = SportsStep.new(name: "Sports")
85+
llm4 = WeatherStep.new(name: "Weather")
8286

8387
parallel_workflow = MARS::Workflows::Parallel.new(
8488
"Parallel workflow",
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Main Pipeline</title>
7+
<style>
8+
body { font-family: system-ui, sans-serif; margin: 2rem; background: #fafafa; }
9+
h1 { color: #333; }
10+
#diagram { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
11+
</style>
12+
</head>
13+
<body>
14+
<h1>Main Pipeline</h1>
15+
<div id="diagram"></div>
16+
<script type="module">
17+
import { renderMermaidSVG } from "https://esm.sh/beautiful-mermaid@1";
18+
const diagram = `flowchart LR
19+
in((In))
20+
out((Out))
21+
agent1[agent1]
22+
gate{Gate}
23+
agent4[agent4]
24+
parallel_workflow_aggregator[Parallel workflow Aggregator]
25+
agent2[agent2]
26+
agent3[agent3]
27+
parallel_workflow_2_aggregator[Parallel workflow 2 Aggregator]
28+
agent5[agent5]
29+
subgraph main_pipeline["Main Pipeline"]
30+
agent1
31+
gate
32+
parallel_workflow_aggregator
33+
subgraph parallel_workflow_2["Parallel workflow 2"]
34+
subgraph sequential_workflow["Sequential workflow"]
35+
agent4
36+
subgraph parallel_workflow["Parallel workflow"]
37+
agent2
38+
agent3
39+
end
40+
parallel_workflow_aggregator
41+
end
42+
agent5
43+
end
44+
parallel_workflow_2_aggregator
45+
end
46+
in --> agent1
47+
agent1 --> gate
48+
gate -->|warning| agent4
49+
gate -->|error| agent2
50+
gate -->|error| agent3
51+
gate --> agent4
52+
gate --> agent5
53+
agent4 --> agent2
54+
agent4 --> agent3
55+
agent2 --> parallel_workflow_aggregator
56+
parallel_workflow_aggregator --> parallel_workflow_2_aggregator
57+
agent3 --> parallel_workflow_aggregator
58+
parallel_workflow_2_aggregator --> out
59+
agent5 --> parallel_workflow_2_aggregator`;
60+
const svg = renderMermaidSVG(diagram);
61+
document.getElementById("diagram").innerHTML = svg;
62+
</script>
63+
</body>
64+
</html>

examples/complex_workflow/diagram.md

Lines changed: 16 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,32 +2,29 @@
22
flowchart LR
33
in((In))
44
out((Out))
5-
agent1[Agent1]
5+
agent1[agent1]
66
gate{Gate}
7-
agent4[Agent4]
7+
agent4[agent4]
88
parallel_workflow_aggregator[Parallel workflow Aggregator]
9-
agent2[Agent2]
10-
agent3[Agent3]
9+
agent2[agent2]
10+
agent3[agent3]
1111
parallel_workflow_2_aggregator[Parallel workflow 2 Aggregator]
12-
agent5[Agent5]
13-
subgraph parallel_workflow_2["Parallel workflow 2"]
14-
sequential_workflow
15-
agent5
16-
end
17-
subgraph parallel_workflow["Parallel workflow"]
18-
agent2
19-
agent3
20-
end
21-
subgraph sequential_workflow["Sequential workflow"]
22-
agent4
23-
parallel_workflow
24-
parallel_workflow_aggregator
25-
end
12+
agent5[agent5]
2613
subgraph main_pipeline["Main Pipeline"]
2714
agent1
2815
gate
2916
parallel_workflow_aggregator
30-
parallel_workflow_2
17+
subgraph parallel_workflow_2["Parallel workflow 2"]
18+
subgraph sequential_workflow["Sequential workflow"]
19+
agent4
20+
subgraph parallel_workflow["Parallel workflow"]
21+
agent2
22+
agent3
23+
end
24+
parallel_workflow_aggregator
25+
end
26+
agent5
27+
end
3128
parallel_workflow_2_aggregator
3229
end
3330
in --> agent1

examples/complex_workflow/generator.rb

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,19 @@
44
require_relative "../../lib/mars"
55

66
# Define LLMs
7-
class Agent1 < MARS::Agent
7+
class Agent1 < MARS::AgentStep
88
end
99

10-
class Agent2 < MARS::Agent
10+
class Agent2 < MARS::AgentStep
1111
end
1212

13-
class Agent3 < MARS::Agent
13+
class Agent3 < MARS::AgentStep
1414
end
1515

16-
class Agent4 < MARS::Agent
16+
class Agent4 < MARS::AgentStep
1717
end
1818

19-
class Agent5 < MARS::Agent
19+
class Agent5 < MARS::AgentStep
2020
end
2121

2222
# Create the LLMs

examples/parallel_workflow/generator.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
require_relative "../../lib/mars"
55

66
# Define the LLMs
7-
class Agent1 < MARS::Agent
7+
class Agent1 < MARS::AgentStep
88
end
99

10-
class Agent2 < MARS::Agent
10+
class Agent2 < MARS::AgentStep
1111
end
1212

13-
class Agent3 < MARS::Agent
13+
class Agent3 < MARS::AgentStep
1414
end
1515

1616
# Create the LLMs

examples/simple_workflow/generator.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
require_relative "../../lib/mars"
55

66
# Define the LLMs
7-
class Agent1 < MARS::Agent
7+
class Agent1 < MARS::AgentStep
88
end
99

10-
class Agent2 < MARS::Agent
10+
class Agent2 < MARS::AgentStep
1111
end
1212

13-
class Agent3 < MARS::Agent
13+
class Agent3 < MARS::AgentStep
1414
end
1515

1616
# Create the LLMs

lib/mars/rendering/graph.rb

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ module MARS
44
module Rendering
55
module Graph
66
def self.include_extensions
7+
MARS::Runnable.include(Base)
78
MARS::AgentStep.include(AgentStep)
89
MARS::Gate.include(Gate)
910
MARS::Workflows::Sequential.include(SequentialWorkflow)

0 commit comments

Comments
 (0)