diff --git a/examples/complex_llm_workflow/diagram.md b/examples/complex_llm_workflow/diagram.md new file mode 100644 index 0000000..3e86da4 --- /dev/null +++ b/examples/complex_llm_workflow/diagram.md @@ -0,0 +1,21 @@ +```mermaid +flowchart LR +in((In)) +out((Out)) +llm_1[LLM 1] +gate{Gate} +parallel_workflow_aggregator[Parallel workflow Aggregator] +llm_2[LLM 2] +llm_3[LLM 3] +llm_4[LLM 4] +in --> llm_1 +llm_1 --> gate +gate -->|success| llm_2 +gate -->|success| llm_3 +gate -->|success| llm_4 +gate -->|default| out +llm_2 --> parallel_workflow_aggregator +parallel_workflow_aggregator --> out +llm_3 --> parallel_workflow_aggregator +llm_4 --> parallel_workflow_aggregator +``` diff --git a/examples/complex_llm_workflow/generator.rb b/examples/complex_llm_workflow/generator.rb index d96acd4..ce1b5e6 100755 --- a/examples/complex_llm_workflow/generator.rb +++ b/examples/complex_llm_workflow/generator.rb @@ -7,23 +7,62 @@ config.openai_api_key = ENV.fetch("OPENAI_API_KEY", nil) end +# Define schema for sports +class SportsSchema < RubyLLM::Schema + array :sports do + object do + string :name + array :top_3_players do + string :name + end + end + end +end + +sports_schema = SportsSchema.new + +# Define weather tool +class Weather < RubyLLM::Tool + description "Gets current weather for a location" + + params do + string :latitude, description: "Latitude (e.g., 52.5200)" + string :longitude, description: "Longitude (e.g., 13.4050)" + end + + def execute(latitude:, longitude:) + url = "https://api.open-meteo.com/v1/forecast?latitude=#{latitude}&longitude=#{longitude}¤t=temperature_2m,wind_speed_10m" + response = Net::HTTP.get_response(URI(url)) + JSON.parse(response.body) + rescue StandardError => e + { error: e.message } + end +end + +weather_tool = Weather.new + # Create the LLMs llm1 = Mars::Agent.new( name: "LLM 1", options: { model: "gpt-4o" }, - instructions: "You are a helpful assistant that can answer questions and help with tasks. Only answer with the result" + instructions: "You are a helpful assistant that can answer questions. + When asked about a country, only answer with its name." ) llm2 = Mars::Agent.new(name: "LLM 2", options: { model: "gpt-4o" }, instructions: "You are a helpful assistant that can answer questions and help with tasks. Return information about the typical food of the country.") -llm3 = Mars::Agent.new(name: "LLM 3", options: { model: "gpt-4o" }, +llm3 = Mars::Agent.new(name: "LLM 3", options: { model: "gpt-4o" }, schema: sports_schema, instructions: "You are a helpful assistant that can answer questions and help with tasks. Return information about the popular sports of the country.") +llm4 = Mars::Agent.new(name: "LLM 4", options: { model: "gpt-4o" }, tools: [weather_tool], + instructions: "You are a helpful assistant that can answer questions and help with tasks. + Return the current weather of the country's capital.") + parallel_workflow = Mars::Workflows::Parallel.new( "Parallel workflow", - steps: [llm2, llm3] + steps: [llm2, llm3, llm4] ) gate = Mars::Gate.new( @@ -39,4 +78,10 @@ steps: [llm1, gate] ) -puts sequential_workflow.run("Which is the last country to declare independence?") +# Generate and save the diagram +diagram = Mars::Rendering::Mermaid.new(sequential_workflow).render +File.write("examples/complex_llm_workflow/diagram.md", diagram) +puts "Complex workflow diagram saved to: examples/complex_llm_workflow/diagram.md" + +# Run the workflow +puts sequential_workflow.run("Which is the largest country in South America?") diff --git a/lib/mars.rb b/lib/mars.rb index 68e23d7..6e04847 100644 --- a/lib/mars.rb +++ b/lib/mars.rb @@ -3,6 +3,7 @@ require "zeitwerk" require "async" require "ruby_llm" +require "ruby_llm/schema" loader = Zeitwerk::Loader.for_gem loader.setup diff --git a/mars.gemspec b/mars.gemspec index 3d4bd97..00ac76e 100644 --- a/mars.gemspec +++ b/mars.gemspec @@ -36,7 +36,7 @@ Gem::Specification.new do |spec| # Uncomment to register a new dependency of your gem spec.add_dependency "async", "~> 2.34" - spec.add_dependency "ruby_llm", "~> 1.0" + spec.add_dependency "ruby_llm", "~> 1.9" spec.add_dependency "zeitwerk", "~> 2.7" # For more information and examples about making a new gem, check out our