sublayer 0.1.0.pre.alpha.3 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 80d1bcf936b12b7638feb1ddc87d0369dd7438f535837e0c0353ffa4e717a9ac
4
- data.tar.gz: a2113a776870928e115e62a318e29e149ecc791633ad7b47f218a9f4d3df75ca
3
+ metadata.gz: c0266ca3b856c768f521cf65a907ebe9d411f5420f83bfb62455912075253820
4
+ data.tar.gz: 1b32e201baa8f26e8caa3a124b4ebe9aeeb652b31745ec0fe6b06ab0cee57da2
5
5
  SHA512:
6
- metadata.gz: ee8d2b20c430e814e400a224f351ac0dd8d4f4e0428f30fc490a3085d40f3fd1e3112044ab9365d4373e4ce1e4035a3a5acf58522fb9d63ec17abc75daa9efff
7
- data.tar.gz: 5c35b019b2e111f935f171fce4d22681195cc0c9d4f40f066283497cd5a99e090505dd8acfc05a3dabd7c241f8455c4c32a2b3916f4f71eb14c1c1f34b235abb
6
+ metadata.gz: 417a853211fb739887936804948c5758d3880431b2b8252df5e3fc58beb6464f44d6f3e1efb0945b0e72a4f80b7135eec8b9813fbffbe9a6cfbe0c4a1d4bf63a
7
+ data.tar.gz: 4ee873c4e5edbe289211320573847cd58273b959e001ad3db8fadf68fdedc0bdc9e957b103573c3d31080acc69886dd58d0146906122192bd75fce1e24724d49
data/README.md CHANGED
@@ -14,12 +14,18 @@ for new features and bug fixes.
14
14
 
15
15
  To maintain stability in your application, we recommend pinning the version of
16
16
  Sublayer in your Gemfile to a specific minor version. For example, to pin to
17
- version 0.1.x, you would add the following line to your Gemfile:
17
+ version 0.2.x, you would add the following line to your Gemfile:
18
18
 
19
19
  ```ruby
20
- gem 'sublayer', '~> 0.1'
20
+ gem 'sublayer', '~> 0.2'
21
21
  ```
22
22
 
23
+ ## Notes on 0.2
24
+
25
+ New default model update: gpt 4 turbo -> gpt 4o
26
+
27
+ Gemini: Updates include the use of beta API function calling features. Experimental and unstable.
28
+
23
29
  ## Installation
24
30
 
25
31
  Install the gem by running the following commands:
@@ -29,12 +35,12 @@ Install the gem by running the following commands:
29
35
  Or add this line to your application's Gemfile:
30
36
 
31
37
  ```ruby
32
- gem 'sublayer', '~> 0.1'
38
+ gem 'sublayer', '~> 0.2'
33
39
  ```
34
40
 
35
41
  ## Choose your AI Model
36
42
 
37
- Sublayer is model-agnostic and can be used with any AI model. Below are the
43
+ Sublayer is model-agnostic and can be used with any AI model. Below are the supported LLM Providers. Check out our [docs](https://docs.sublayer.com) to add your own custom Provider.
38
44
 
39
45
  ### OpenAI (Default)
40
46
 
@@ -45,10 +51,12 @@ Visit [OpenAI](https://openai.com/product) to get an API key.
45
51
  Usage:
46
52
  ```ruby
47
53
  Sublayer.configuration.ai_provider = Sublayer::Providers::OpenAI
48
- Sublayer.configuration.ai_model = "gpt-4-turbo-preview"
54
+ Sublayer.configuration.ai_model = "gpt-4o"
49
55
  ```
50
56
 
51
- ### Gemini
57
+ ### Gemini [UNSTABLE]
58
+
59
+ (Gemini's function calling API is in beta. Not recommended for production use.)
52
60
 
53
61
  Expects you to have a Gemini API key set in the `GEMINI_API_KEY` environment variable.
54
62
 
@@ -57,7 +65,7 @@ Visit [Google AI Studio](https://ai.google.dev/) to get an API key.
57
65
  Usage:
58
66
  ```ruby
59
67
  Sublayer.configuration.ai_provider = Sublayer::Providers::Gemini
60
- Sublayer.configuration.ai_model = "gemini-pro"
68
+ Sublayer.configuration.ai_model = "gemini-1.5-pro"
61
69
  ```
62
70
 
63
71
  ### Claude
@@ -70,7 +78,7 @@ Visit [Anthropic](https://anthropic.com/) to get an API key.
70
78
  Usage:
71
79
  ```ruby
72
80
  Sublayer.configuration.ai_provider = Sublayer::Providers::Claude
73
- Sublayer.configuration.ai_model ="claude-3-opus-20240229"
81
+ Sublayer.configuration.ai_model ="claude-3-5-sonnet-20240620"
74
82
  ```
75
83
 
76
84
  ## Concepts
@@ -81,49 +89,46 @@ Generators are responsible for generating specific outputs based on input data.
81
89
  They focus on a single generation task and do not perform any actions or complex
82
90
  decision-making. Generators are the building blocks of the Sublayer framework.
83
91
 
84
- Examples (in the `/lib/sublayer/generators/examples` directory):
85
- - `CodeFromDescriptionGenerator`: Generates code based on a description and the
86
- technologies used.
87
- - `DescriptionFromCodeGenerator`: Generates a description of the code passed in to
88
- it.
89
- - `CodeFromBlueprintGenerator`: Generates code based on a blueprint, a blueprint
90
- description, and a description of the desired code.
92
+ Examples (in the `/spec/generators/examples` directory):
93
+ - [CodeFromDescriptionGenerator](https://github.com/sublayerapp/sublayer/blob/main/spec/generators/examples/code_from_description_generator.rb):
94
+ Generates code based on a description and the technologies used.
95
+ - [DescriptionFromCodeGenerator](https://github.com/sublayerapp/sublayer/blob/main/spec/generators/description_from_code_generator_spec.rb):
96
+ Generates a description of the code passed in to it.
97
+ - [CodeFromBlueprintGenerator](https://github.com/sublayerapp/sublayer/blob/main/spec/generators/examples/code_from_blueprint_generator.rb):
98
+ Generates code based on a blueprint, a blueprint description, and a description of the desired code.
91
99
 
92
100
 
93
- ### Actions (Coming Soon)
101
+ ### Actions
94
102
 
95
- Actions are responsible for performing specific operations to get inputs for a
96
- Generator or based on the generated output from a Generator. They encapsulate a
97
- single action and do not involve complex decision-making. Actions are the
98
- executable units that bring the generated inputs to life.
103
+ Actions perform specific operations to either get inputs for a Generator or use
104
+ the generated output from a Generator. Actions do not involve complex decision making.
99
105
 
100
106
  Examples:
101
- - SaveToFileAction: Saves generated output to a file.
102
- - RunCommandLineCommandAction: Runs a generated command line command.
107
+ - [WriteFileAction](https://github.com/sublayerapp/tddbot/blob/43297c5da9445bd6c8882d5e3876cff5fc6b2650/lib/tddbot/sublayer/actions/write_file_action.rb):
108
+ Saves generated output to a file.
109
+ - [RunTestCommandAction](https://github.com/sublayerapp/tddbot/blob/43297c5da9445bd6c8882d5e3876cff5fc6b2650/lib/tddbot/sublayer/actions/run_test_command_action.rb):
110
+ Runs a generated command line command.
103
111
 
104
- ### Tasks (Coming Soon)
112
+ ### Agents
105
113
 
106
- Tasks combine Generators and Actions to accomplish a specific goal. They involve
107
- a sequence of generation and action steps that may include basic decision-making
108
- and flow control. Tasks are the high-level building blocks that define the
109
- desired outcome.
114
+ Sublayer Agents are autonomous entities designed to perform specific
115
+ tasks or monitor systems.
110
116
 
111
117
  Examples:
112
- - ModifyFileContentsTask: Generates new file contents based on the existing
113
- contents and a set of rules, and then saves the new contents to the file.
118
+ - [RSpecAgent](https://github.com/sublayerapp/sublayer/blob/main/spec/agents/examples/rspec_agent.rb):
119
+ Runs tests whenever a file is changed. If the tests fail the code is changed
120
+ by the agent to pass the tests.
114
121
 
115
- ### Agents (Coming Soon)
122
+ ### Triggers
116
123
 
117
- Agents are high-level entities that coordinate and orchestrate multiple Tasks to
118
- achieve a broader goal. They involve complex decision-making, monitoring, and
119
- adaptation based on the outcomes of the Tasks. Agents are the intelligent
120
- supervisors that manage the overall workflow.
124
+ Sublayer Triggers are used in agents. Triggers decide when an agent is activated
125
+ and performs its task
121
126
 
122
127
  Examples:
123
- - CustomerSupportAgent: Handles customer support inquiries by using various
124
- Tasks such as understanding the customer's issue, generating appropriate
125
- responses, and performing actions like sending emails or creating support
126
- tickets.
128
+ - [FileChange](https://github.com/sublayerapp/sublayer/blob/main/lib/sublayer/triggers/file_change.rb):
129
+ This built in sublayer trigger, listens for file changes
130
+ - [TimeInterval](https://docs.sublayer.com/docs/guides/build-a-custom-trigger)
131
+ This custom trigger tutorial shows how to create your own trigger, this one activates on a time interval
127
132
 
128
133
  ## Usage Examples
129
134
 
@@ -2,48 +2,52 @@ module Sublayer
2
2
  module Agents
3
3
  class Base
4
4
  class << self
5
- attr_accessor :goal_condition_block, :trigger_condition_block, :trigger_on_files_changed_block, :check_status_block, :step_block
5
+ attr_reader :triggers, :goal_condition_block, :check_status_block, :step_block, :listeners
6
6
 
7
- def trigger_condition(&block)
8
- self.trigger_condition_block = block
7
+ def trigger(trigger_instance = nil)
8
+ @triggers ||= []
9
+
10
+ if trigger_instance
11
+ @triggers << trigger_instance
12
+ else
13
+ raise ArgumentError, "Either a trigger instance or a block must be provided"
14
+ end
9
15
  end
10
16
 
11
17
  def trigger_on_files_changed(&block)
12
- self.trigger_on_files_changed_block = block
18
+ trigger(Triggers::FileChange.new(&block))
13
19
  end
14
20
 
15
21
  def goal_condition(&block)
16
- self.goal_condition_block = block
22
+ @goal_condition_block = block
17
23
  end
18
24
 
19
25
  def check_status(&block)
20
- self.check_status_block = block
26
+ @check_status_block = block
21
27
  end
22
28
 
23
29
  def step(&block)
24
- self.step_block = block
30
+ @step_block = block
25
31
  end
26
32
  end
27
33
 
28
34
  def run
29
- files_to_listen_to = instance_eval(&self.class.trigger_on_files_changed_block).map { |file| File.expand_path(file) }
30
- folders = files_to_listen_to.map { |file| File.dirname(file) }.uniq
31
-
32
- listener = Listen.to(*folders) do |modified, added, removed|
33
- if files_to_listen_to.any? { |file| modified.include?(file) }
34
- take_step
35
- end
36
- end
37
-
38
- listener.start
39
-
35
+ setup_triggers
40
36
  take_step
41
-
42
37
  sleep
43
38
  end
44
39
 
45
40
  private
46
41
 
42
+ def setup_triggers
43
+ @listeners = []
44
+
45
+ self.class.triggers.each do |trigger|
46
+ listener = trigger.setup(self)
47
+ @listeners << listener if listener
48
+ end
49
+ end
50
+
47
51
  def take_step
48
52
  instance_eval(&self.class.check_status_block)
49
53
  instance_eval(&self.class.step_block) unless instance_eval(&self.class.goal_condition_block)
@@ -0,0 +1,29 @@
1
+ module Sublayer
2
+ module Components
3
+ module OutputAdapters
4
+ module Formattable
5
+ def format_properties
6
+ formatted_properties = {}
7
+ self.properties.each do |prop|
8
+ property = {
9
+ type: prop.type,
10
+ description: prop.description
11
+ }
12
+
13
+ property[:enum] = prop.enum if prop.respond_to?(:enum) && prop.enum
14
+ property[:default] = prop.default if prop.respond_to?(:default) && !prop.default.nil?
15
+ property[:minimum] = prop.minimum if prop.respond_to?(:minimum) && !prop.minimum.nil?
16
+ property[:maximum] = prop.maximum if prop.respond_to?(:maximum) && !prop.maximum.nil?
17
+ property[:items] = prop.items if prop.respond_to?(:items) && prop.items
18
+ formatted_properties[prop.name.to_sym] = property
19
+ end
20
+ formatted_properties
21
+ end
22
+
23
+ def format_required
24
+ self.properties.select(&:required).map(&:name)
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,28 @@
1
+ module Sublayer
2
+ module Components
3
+ module OutputAdapters
4
+ class ListOfStrings
5
+ attr_reader :name, :description
6
+
7
+ def initialize(options)
8
+ @name = options[:name]
9
+ @description = options[:description]
10
+ end
11
+
12
+ def properties
13
+ [
14
+ OpenStruct.new(
15
+ name: @name,
16
+ type: 'array',
17
+ description: @description,
18
+ required: true,
19
+ items: {
20
+ type: 'string'
21
+ }
22
+ )
23
+ ]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -18,6 +18,9 @@ module Sublayer
18
18
  else
19
19
  raise "Output adapter must be specified with :class or :type"
20
20
  end
21
+
22
+ options[:name] = options[:name].to_s if options[:name].is_a?(Symbol)
23
+
21
24
  klass.new(options)
22
25
  end
23
26
  end
@@ -4,7 +4,7 @@ module Sublayer
4
4
  attr_reader :results
5
5
 
6
6
  def self.llm_output_adapter(options)
7
- output_adapter = Sublayer::Components::OutputAdapters.create(options)
7
+ output_adapter = Sublayer::Components::OutputAdapters.create(options).extend(Sublayer::Components::OutputAdapters::Formattable)
8
8
  const_set(:OUTPUT_ADAPTER, output_adapter)
9
9
  end
10
10
 
@@ -1,5 +1,5 @@
1
1
  # Sublayer.configuration.ai_provider = Sublayer::Providers::Claude
2
- # Sublayer.configuration.ai_model ="claude-3-opus-20240229"
2
+ # Sublayer.configuration.ai_model ="claude-3-5-sonnet-20240620"
3
3
 
4
4
  module Sublayer
5
5
  module Providers
@@ -22,8 +22,8 @@ module Sublayer
22
22
  description: output_adapter.description,
23
23
  input_schema: {
24
24
  type: "object",
25
- properties: format_properties(output_adapter),
26
- required: output_adapter.properties.select(&:required).map(&:name)
25
+ properties: output_adapter.format_properties,
26
+ required: output_adapter.format_required
27
27
  }
28
28
  }
29
29
  ],
@@ -35,20 +35,6 @@ module Sublayer
35
35
  function_input = JSON.parse(response.body).dig("content").find {|content| content['type'] == 'tool_use'}.dig("input")
36
36
  function_input[output_adapter.name]
37
37
  end
38
-
39
- private
40
- def self.format_properties(output_adapter)
41
- output_adapter.properties.each_with_object({}) do |property, hash|
42
- hash[property.name] = {
43
- type: property.type,
44
- description: property.description
45
- }
46
-
47
- if property.enum
48
- hash[property.name][:enum] = property.enum
49
- end
50
- end
51
- end
52
38
  end
53
39
  end
54
40
  end
@@ -1,44 +1,41 @@
1
+ # *UNSTABLE* Gemini function calling API is in beta.
2
+ # Provider is not recommended until API update.
3
+
1
4
  # Sublayer.configuration.ai_provider = Sublayer::Providers::Gemini
2
- # Sublayer.configuration.ai_model = "gemini-pro"
5
+ # Sublayer.configuration.ai_model = "gemini-1.5-pro"
3
6
 
4
7
  module Sublayer
5
8
  module Providers
6
9
  class Gemini
7
10
  def self.call(prompt:, output_adapter:)
8
- system_prompt = <<-PROMPT
9
- You have access to a set of tools to answer the prompt.
10
-
11
- You may call tools like this:
12
- <tool_calls>
13
- <tool_call>
14
- <tool_name>$TOOL_NAME</tool_name>
15
- <parameters>
16
- <$PARAMETER_NAME>$VALUE</$PARAMETER_NAME>
17
- ...
18
- </parameters>
19
- </tool_call>
20
- </tool_calls>
21
-
22
- Here are the tools available:
23
- <tools>
24
- <tool_description>
25
- <tool_name>#{output_adapter.name}</tool_name>
26
- <tool_description>#{output_adapter.description}</tool_description>
27
- <parameters>
28
- #{format_properties(output_adapter)}
29
- </parameters>
30
- </tool_description>
31
- </tools>
32
-
33
- Respond only with valid xml.
34
- The entire response should be wrapped in a <response> tag.
35
- Your response should call a tool inside a <tool_calls> tag.
36
- PROMPT
37
-
38
11
  response = HTTParty.post(
39
12
  "https://generativelanguage.googleapis.com/v1beta/models/#{Sublayer.configuration.ai_model}:generateContent?key=#{ENV['GEMINI_API_KEY']}",
40
13
  body: {
41
- contents: { role: "user", parts: { text: "#{system_prompt}\n#{prompt}" } }
14
+ contents: {
15
+ role: "user",
16
+ parts: {
17
+ text: "#{prompt}"
18
+ },
19
+ },
20
+ tools: {
21
+ functionDeclarations: [
22
+ {
23
+ name: output_adapter.name,
24
+ description: output_adapter.description,
25
+ parameters: {
26
+ type: "OBJECT",
27
+ properties: output_adapter.format_properties,
28
+ required: output_adapter.format_required
29
+ }
30
+ }
31
+ ]
32
+ },
33
+ tool_config: {
34
+ function_calling_config: {
35
+ mode: "ANY",
36
+ allowed_function_names: [output_adapter.name]
37
+ }
38
+ }
42
39
  }.to_json,
43
40
  headers: {
44
41
  "Content-Type" => "application/json"
@@ -47,22 +44,7 @@ module Sublayer
47
44
 
48
45
  raise "Error generating with Gemini, error: #{response.body}" unless response.success?
49
46
 
50
- text_containing_xml = response.dig('candidates', 0, 'content', 'parts', 0, 'text')
51
- tool_output = Nokogiri::HTML.parse(text_containing_xml.match(/\<#{output_adapter.name}\>(.*?)\<\/#{output_adapter.name}\>/m)[1]).text
52
-
53
- raise "Gemini did not format response, error: #{response.body}" unless tool_output
54
- return tool_output
55
- end
56
-
57
- private
58
- def self.format_properties(output_adapter)
59
- output_adapter.properties.each_with_object("") do |property, xml|
60
- xml << "<name>#{property.name}</name>"
61
- xml << "<type>#{property.type}</type>"
62
- xml << "<description>#{property.description}</description>"
63
- xml << "<required>#{property.required}</required>"
64
- xml << "<enum>#{property.enum}</enum>" if property.enum
65
- end
47
+ argument = response.dig("candidates", 0, "content", "parts", 0, "functionCall", "args", output_adapter.name)
66
48
  end
67
49
  end
68
50
  end
@@ -1,5 +1,5 @@
1
1
  # Sublayer.configuration.ai_provider = Sublayer::Providers::OpenAI
2
- # Sublayer.configuration.ai_model = "gpt-4-turbo-preview"
2
+ # Sublayer.configuration.ai_model = "gpt-4o"
3
3
 
4
4
  module Sublayer
5
5
  module Providers
@@ -25,9 +25,9 @@ module Sublayer
25
25
  description: output_adapter.description,
26
26
  parameters: {
27
27
  type: "object",
28
- properties: OpenAI.format_properties(output_adapter)
28
+ properties: output_adapter.format_properties
29
29
  },
30
- required: [output_adapter.properties.select(&:required).map(&:name)]
30
+ required: output_adapter.format_required
31
31
  }
32
32
  }
33
33
  ]
@@ -41,20 +41,6 @@ module Sublayer
41
41
  function_body = message.dig("tool_calls", 0, "function", "arguments")
42
42
  JSON.parse(function_body)[output_adapter.name]
43
43
  end
44
-
45
- private
46
- def self.format_properties(output_adapter)
47
- output_adapter.properties.each_with_object({}) do |property, hash|
48
- hash[property.name] = {
49
- type: property.type,
50
- description: property.description
51
- }
52
-
53
- if property.enum
54
- hash[property.name][:enum] = property.enum
55
- end
56
- end
57
- end
58
44
  end
59
45
  end
60
46
  end
@@ -0,0 +1,13 @@
1
+ module Sublayer
2
+ module Triggers
3
+ class Base
4
+ def setup(agent)
5
+ raise NotImplementedError, "Subclasses must implement setup method"
6
+ end
7
+
8
+ def activate(agent)
9
+ agent.send(:take_step)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Sublayer
2
+ module Triggers
3
+ class FileChange < Base
4
+ def initialize(&block)
5
+ @block = block
6
+ end
7
+
8
+ def setup(agent)
9
+ files_to_watch = agent.instance_eval(&@block)
10
+ folders = files_to_watch.map { |file| File.dirname(File.expand_path(file)) }.uniq
11
+
12
+ Listen.to(*folders) do |modified, added, removed|
13
+ if files_to_watch.any? { |file| modified.include?(File.expand_path(file)) }
14
+ activate(agent)
15
+ end
16
+ end.start
17
+ end
18
+ end
19
+ end
20
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Sublayer
4
- VERSION = "0.1.0-alpha.3"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/sublayer.rb CHANGED
@@ -22,7 +22,7 @@ module Sublayer
22
22
  def self.configuration
23
23
  @configuration ||= OpenStruct.new(
24
24
  ai_provider: Sublayer::Providers::OpenAI,
25
- ai_model: "gpt-4-turbo-preview"
25
+ ai_model: "gpt-4o"
26
26
  )
27
27
  end
28
28
 
data/sublayer.gemspec CHANGED
@@ -41,6 +41,6 @@ Gem::Specification.new do |spec|
41
41
  spec.add_development_dependency "rspec", "~> 3.12"
42
42
  spec.add_development_dependency "pry", "~> 0.14"
43
43
  spec.add_development_dependency "vcr", "~> 6.0"
44
- spec.add_development_dependency "webmock", "~> 3.0"
44
+ spec.add_development_dependency "webmock", "~> 3"
45
45
  spec.add_development_dependency "clag"
46
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sublayer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0.pre.alpha.3
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Scott Werner
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-05-17 00:00:00.000000000 Z
11
+ date: 2024-07-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ruby-openai
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '3.0'
159
+ version: '3'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '3.0'
166
+ version: '3'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: clag
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -193,19 +193,17 @@ files:
193
193
  - lib/sublayer/actions/base.rb
194
194
  - lib/sublayer/agents/base.rb
195
195
  - lib/sublayer/components/output_adapters.rb
196
+ - lib/sublayer/components/output_adapters/formattable.rb
197
+ - lib/sublayer/components/output_adapters/list_of_strings.rb
196
198
  - lib/sublayer/components/output_adapters/single_string.rb
197
199
  - lib/sublayer/components/output_adapters/string_selection_from_list.rb
198
200
  - lib/sublayer/generators/base.rb
199
- - lib/sublayer/generators/examples/code_from_blueprint_generator.rb
200
- - lib/sublayer/generators/examples/code_from_description_generator.rb
201
- - lib/sublayer/generators/examples/description_from_code_generator.rb
202
- - lib/sublayer/generators/examples/invalid_to_valid_json_generator.rb
203
- - lib/sublayer/generators/examples/route_selection_from_user_intent_generator.rb
204
- - lib/sublayer/generators/examples/sentiment_from_text_generator.rb
205
201
  - lib/sublayer/providers/claude.rb
206
202
  - lib/sublayer/providers/gemini.rb
207
203
  - lib/sublayer/providers/open_ai.rb
208
204
  - lib/sublayer/tasks/base.rb
205
+ - lib/sublayer/triggers/base.rb
206
+ - lib/sublayer/triggers/file_change.rb
209
207
  - lib/sublayer/version.rb
210
208
  - sublayer.gemspec
211
209
  homepage: https://docs.sublayer.com
@@ -227,11 +225,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
227
225
  version: 2.6.0
228
226
  required_rubygems_version: !ruby/object:Gem::Requirement
229
227
  requirements:
230
- - - ">"
228
+ - - ">="
231
229
  - !ruby/object:Gem::Version
232
- version: 1.3.1
230
+ version: '0'
233
231
  requirements: []
234
- rubygems_version: 3.3.26
232
+ rubygems_version: 3.5.3
235
233
  signing_key:
236
234
  specification_version: 4
237
235
  summary: A model-agnostic Ruby GenerativeAI DSL and Framework
@@ -1,30 +0,0 @@
1
- class CodeFromBlueprintGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "generated_code",
4
- description: "The generated code for the description"
5
-
6
- def initialize(blueprint_description:, blueprint_code:, description:)
7
- @blueprint_description = blueprint_description
8
- @blueprint_code = blueprint_code
9
- @description = description
10
- end
11
-
12
- def generate
13
- super
14
- end
15
-
16
- def prompt
17
- <<-PROMPT
18
- You are an expert programmer and are great at looking at and understanding existing patterns and applying them to new situations.
19
-
20
- The blueprint we're working with is: #{@blueprint_description}.
21
- The code for that blueprint is:
22
- #{@blueprint_code}
23
-
24
- You need to use the blueprint above and modify it so that it satisfied the following description:
25
- #{@description}
26
-
27
- Take a deep breath and think step by step before you start coding.
28
- PROMPT
29
- end
30
- end
@@ -1,26 +0,0 @@
1
- class CodeFromDescriptionGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "generated_code",
4
- description: "The generated code in the requested language"
5
-
6
- def initialize(description:, technologies:)
7
- @description = description
8
- @technologies = technologies
9
- end
10
-
11
- def generate
12
- super
13
- end
14
-
15
- def prompt
16
- <<-PROMPT
17
- You are an expert programmer in #{@technologies.join(", ")}.
18
-
19
- You are tasked with writing code using the following technologies: #{@technologies.join(", ")}.
20
-
21
- The description of the task is #{@description}
22
-
23
- Take a deep breath and think step by step before you start coding.
24
- PROMPT
25
- end
26
- end
@@ -1,23 +0,0 @@
1
- class DescriptionFromCodeGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "code_description",
4
- description: "A description of what the code in the file does"
5
-
6
- def initialize(code:)
7
- @code = code
8
- end
9
-
10
- def generate
11
- super
12
- end
13
-
14
- def prompt
15
- <<-PROMPT
16
- You are an experienced software engineer. Below is a chunk of code:
17
-
18
- #{@code}
19
-
20
- Please read the code carefully and provide a high-level description of what this code does, including its purpose, functionalities, and any noteworthy details.
21
- PROMPT
22
- end
23
- end
@@ -1,23 +0,0 @@
1
- class InvalidToValidJsonGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :single_string,
3
- name: "valid_json",
4
- description: "The valid JSON string"
5
-
6
- def initialize(invalid_json:)
7
- @invalid_json = invalid_json
8
- end
9
-
10
- def generate
11
- super
12
- end
13
-
14
- def prompt
15
- <<-PROMPT
16
- You are an expert in JSON parsing.
17
-
18
- The given string is not a valid JSON: #{@invalid_json}
19
-
20
- Please fix this and produce a valid JSON.
21
- PROMPT
22
- end
23
- end
@@ -1,29 +0,0 @@
1
- class RouteSelectionFromUserIntentGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :string_selection_from_list,
3
- name: "route",
4
- description: "A route selected from the list",
5
- options: :available_routes
6
-
7
- def initialize(user_intent:)
8
- @user_intent = user_intent
9
- end
10
-
11
- def generate
12
- super
13
- end
14
-
15
- def available_routes
16
- ["GET /", "GET /users", "GET /users/:id", "POST /users", "PUT /users/:id", "DELETE /users/:id"]
17
- end
18
-
19
- def prompt
20
- <<-PROMPT
21
- You are skilled at selecting routes based on user intent.
22
-
23
- Your task is to choose a route based on the following intent:
24
-
25
- The user's intent is:
26
- #{@user_intent}
27
- PROMPT
28
- end
29
- end
@@ -1,26 +0,0 @@
1
- class SentimentFromTextGenerator < Sublayer::Generators::Base
2
- llm_output_adapter type: :string_selection_from_list,
3
- name: "sentiment_value",
4
- description: "A sentiment value from the list",
5
- options: -> { @sentiment_options }
6
-
7
- def initialize(text:, sentiment_options:)
8
- @text = text
9
- @sentiment_options = sentiment_options
10
- end
11
-
12
- def generate
13
- super
14
- end
15
-
16
- def prompt
17
- <<-PROMPT
18
- You are an expert at determining sentiment from text.
19
-
20
- You are tasked with analyzing the following text and determining its sentiment value.
21
-
22
- The text is:
23
- #{@text}
24
- PROMPT
25
- end
26
- end