reprompt 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.rspec +3 -0
- data/.rubocop.yml +13 -0
- data/LICENSE.txt +21 -0
- data/README.md +217 -0
- data/Rakefile +12 -0
- data/lib/reprompt/clients/base.rb +10 -0
- data/lib/reprompt/clients/ollama.rb +22 -0
- data/lib/reprompt/conversation.rb +67 -0
- data/lib/reprompt/templates/base.rb +14 -0
- data/lib/reprompt/templates/five_whys.rb +20 -0
- data/lib/reprompt/templates/technical_outline.rb +17 -0
- data/lib/reprompt/version.rb +5 -0
- data/lib/reprompt.rb +16 -0
- data/reprompt.gemspec +36 -0
- data/sig/reprompt.rbs +4 -0
- metadata +60 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 13fa55af8b7e2e77547d77b1df26c68d47b1814c6de4908289391cc0949c3449
|
4
|
+
data.tar.gz: '07548880dfcf028f0d915aa93650b8702b9461003782d338e7d0c83b87b006c6'
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: c2708cbec2de58e96fd3bbd3bc574750102d3ab48887972c8232c863fb1cfc58a1bc954c3bd946da6fe7a0933a3c485ca688f911567b211bd52cb428a48cc5f2
|
7
|
+
data.tar.gz: 436bce970274e743914da901726dff36d0df5d7a0035c3ab5168f457efd418f43973c46a28dff729e732969757b464af297594adb4e71323134defc396d6b17e
|
data/.rspec
ADDED
data/.rubocop.yml
ADDED
data/LICENSE.txt
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
The MIT License (MIT)
|
2
|
+
|
3
|
+
Copyright (c) 2024 Jim Jones
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
7
|
+
in the Software without restriction, including without limitation the rights
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
10
|
+
furnished to do so, subject to the following conditions:
|
11
|
+
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
13
|
+
all copies or substantial portions of the Software.
|
14
|
+
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,217 @@
|
|
1
|
+
# Reprompt
|
2
|
+
|
3
|
+
Provides a pattern for iteratively prompting an LLM and asking follow up questions based on the response.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
|
+
|
9
|
+
$ bundle add reprompt
|
10
|
+
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
12
|
+
|
13
|
+
$ gem install reprompt
|
14
|
+
|
15
|
+
The only client adapter at the current moment is for Ollama. So you'll have to run a model locally.
|
16
|
+
|
17
|
+
Mistral is really good.
|
18
|
+
|
19
|
+
```
|
20
|
+
brew install ollama
|
21
|
+
brew services start ollama
|
22
|
+
ollama pull mistral
|
23
|
+
```
|
24
|
+
|
25
|
+
## Pattern
|
26
|
+
|
27
|
+
Take a look in `reprompt/templates`. Return a `true/false` for the `stop_condition` callback.
|
28
|
+
Return a string (question, response, etc) for the `follow_up_on` callback.
|
29
|
+
|
30
|
+
Here's the basic pattern.
|
31
|
+
|
32
|
+
```ruby
|
33
|
+
require_relative 'base'
|
34
|
+
|
35
|
+
class TechnicalOutline < Base
|
36
|
+
def prompt(question)
|
37
|
+
@conversation = Conversation.new(client, max_responses) do
|
38
|
+
stop_condition do |depth, response|
|
39
|
+
response.include?("we are done") || depth >= max_responses
|
40
|
+
end
|
41
|
+
|
42
|
+
follow_up_on do |response|
|
43
|
+
# We'll have the Mistral LLM create our next follow up question
|
44
|
+
prompt "What is a good follow up question for #{response}? Or are we done?"
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
conversation.start(question)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
```
|
52
|
+
|
53
|
+
## Usage
|
54
|
+
|
55
|
+
```ruby
|
56
|
+
template = TechnicalOutline.new
|
57
|
+
template.prompt("Outline the difference between a Ruby include vs prepend")
|
58
|
+
```
|
59
|
+
|
60
|
+
### The Resulting Article
|
61
|
+
|
62
|
+
### Q: Outline the difference between a Ruby include vs prepend
|
63
|
+
#### A: In Ruby, `include` and `prepend` are two methods used to add functionality to a class or module. However, they serve different purposes:
|
64
|
+
|
65
|
+
1. **Include:** The `include` method adds the methods (and constants, if any) of one module into another module or class. When you include a module into a class, all the methods defined in that module become available in the class. The instance methods are mixed-in and will be accessible on instances of the class. The class itself does not inherit from the included module.
|
66
|
+
|
67
|
+
2. **Prepend:** The `prepend` method also adds the functionality of one module into another module or class, but it does so in a different way. When you prepend a module to a class, the methods defined in that module are added at the beginning (before all other instances and class methods) of the class's method chain. This can be useful when you want to modify or extend existing methods without overriding them completely.
|
68
|
+
|
69
|
+
Here is an example to illustrate the difference between `include` and `prepend`. Let's assume we have two modules: `MyModule1` and `MyModule2`. Both modules define a method called `my_method`.
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
module MyModule1
|
73
|
+
def my_method
|
74
|
+
puts "MyModule1: my_method"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
module MyModule2
|
79
|
+
def my_method
|
80
|
+
puts "MyModule2: my_method"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
```
|
84
|
+
|
85
|
+
Now, let's see how we can use these modules with the `include` and `prepend` methods:
|
86
|
+
|
87
|
+
**Using include:**
|
88
|
+
|
89
|
+
```ruby
|
90
|
+
class MyClass
|
91
|
+
include MyModule1
|
92
|
+
include MyModule2
|
93
|
+
end
|
94
|
+
|
95
|
+
MyClass.new.my_method # Output: "MyModule1: my_method" (because MyModule1 is included last)
|
96
|
+
```
|
97
|
+
|
98
|
+
In this example, `MyModule1` and `MyModule2` are included in the order they appear, so when you call `my_method` on an instance of `MyClass`, it will output "MyModule1: my_method". If we want to change the order, we would have to change the order in which the modules are included.
|
99
|
+
|
100
|
+
**Using prepend:**
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
class MyClass
|
104
|
+
prepend MyModule2
|
105
|
+
include MyModule1
|
106
|
+
end
|
107
|
+
|
108
|
+
MyClass.new.my_method # Output: "MyModule2: my_method" (because MyModule2 is prepended)
|
109
|
+
```
|
110
|
+
|
111
|
+
In this example, `MyModule2` is prepended to the class before including `MyModule1`. When you call `my_method` on an instance of `MyClass`, it will output "MyModule2: my_method" because `MyModule2` is added at the beginning of the method chain.
|
112
|
+
### Q: A possible follow-up question could be:
|
113
|
+
|
114
|
+
Can you explain some use cases where it would be more appropriate to use `include` instead of `prepend`, and vice versa, when extending or modifying the functionality of a class or module in Ruby? Also, are there any limitations or drawbacks to using one method over the other, depending on the specific scenario?
|
115
|
+
#### A: Sure! The choice between `include` and `prepend` depends on your specific use case and the desired outcome. Here are some common scenarios where each method might be more appropriate:
|
116
|
+
|
117
|
+
**Use Cases for Include:**
|
118
|
+
|
119
|
+
1. When you want to add new methods or functionalities to an existing class or module, without modifying any of the existing methods. This is because `include` adds the methods at the end of the class's method chain.
|
120
|
+
2. When you have multiple modules that define similar but not identical functionality and you want to mix them into a single class or module. The order in which you include these modules may impact the behavior of your class/module, so consider the dependencies carefully.
|
121
|
+
3. When the added methods are optional or can be easily overridden by other methods in the class/module.
|
122
|
+
4. When working with mixins or libraries that provide additional functionality to your classes or modules.
|
123
|
+
|
124
|
+
**Use Cases for Prepend:**
|
125
|
+
|
126
|
+
1. When you want to modify existing methods without overriding them completely. By prepending a module, you can add new behavior at the beginning of the method chain, which will be executed before the original implementation of the method. This is useful when you need to perform some additional setup or validation for a method.
|
127
|
+
2. When dealing with third-party libraries that provide methods or functionalities that you want to modify or extend without modifying the library's source code directly. Prepending your custom module allows you to hook into existing methods and add new functionality while keeping the original behavior intact.
|
128
|
+
3. When working on deeply nested inheritance hierarchies, where you need to modify the behavior of a method at a specific level in the hierarchy. By prepending the modifying module at that level, you can modify the behavior without affecting other levels in the hierarchy.
|
129
|
+
|
130
|
+
Limitations and Drawbacks:
|
131
|
+
|
132
|
+
1. **Naming Conflicts:** If two included modules or prepended modules define methods with the same name, there will be a naming conflict. In this case, you need to provide an alias or rename one of the conflicting methods.
|
133
|
+
2. **Complexity:** Using both `include` and `prepend` in the same class/module can make the codebase more complex and harder to understand for other developers. Try to keep your use of these methods clear and concise.
|
134
|
+
3. **Ordering Dependencies:** The order in which you include or prepend modules matters, as it impacts the method chain. Make sure to consider the dependencies carefully and provide a clear ordering if necessary.
|
135
|
+
### Q: What are some best practices for managing the order of dependencies when using `include` and `prepend` in Ruby?
|
136
|
+
#### A: When managing dependencies in Ruby with `include` and `prepend`, here are some best practices to ensure clear and consistent code:
|
137
|
+
|
138
|
+
1. **Declare dependencies explicitly:** Make sure to declare all dependencies (included modules or prepended modules) at the beginning of your class definition, preferably in the order they should be processed. This makes it easier for other developers to understand the flow of your code.
|
139
|
+
|
140
|
+
2. **Use descriptive names:** Give meaningful and descriptive names to your modules to make it clear what functionality they provide. This helps when determining the correct order of dependencies.
|
141
|
+
|
142
|
+
3. **Minimize the number of dependencies:** Try to keep the number of dependencies to a minimum, as more dependencies lead to increased complexity and potential for conflicts. If possible, refactor your code to reduce the number of dependencies.
|
143
|
+
|
144
|
+
4. **Consider encapsulation:** Encapsulate related functionality within the same module or library to minimize dependency conflicts and simplify the ordering process.
|
145
|
+
|
146
|
+
5. **Maintain a clear documentation:** Clearly document each module's purpose and intended use, along with any specific requirements or dependencies. This will help other developers understand the context of your code.
|
147
|
+
|
148
|
+
6. **Test thoroughly:** Thoroughly test your code to ensure that the order of dependencies does not impact the functionality or behavior of your classes or modules. This can help you identify and resolve potential conflicts early in the development process.
|
149
|
+
### Q: A possible follow-up question could be: "What are some common pitfalls to avoid when managing dependencies with `include` and `prepend` in Ruby?" or "Can you provide examples of how these best practices for managing dependencies with `include` and `prepend` in Ruby can be implemented in practice?"
|
150
|
+
#### A: When managing dependencies with `include` and `prepend` in Ruby, there are some common pitfalls to avoid:
|
151
|
+
|
152
|
+
1. **Naming conflicts:** As mentioned earlier, if two included modules or prepended modules define methods with the same name, there will be a naming conflict. To avoid this, you can provide an alias or rename one of the conflicting methods. Make sure to check for potential naming conflicts before incorporating new dependencies into your codebase.
|
153
|
+
2. **Complexity:** Using both `include` and `prepend` in the same class/module can make the codebase more complex and harder to understand for other developers. Try to keep your use of these methods clear and concise, and avoid adding unnecessary dependencies.
|
154
|
+
3. **Inconsistent ordering:** The order in which you include or prepend modules matters. If dependencies are not declared consistently across your codebase, it can lead to unexpected behavior or bugs. Be sure to declare all dependencies at the beginning of your class definition, preferably in the correct order.
|
155
|
+
4. **Circular dependencies:** Circular dependencies occur when modules A and B each depend on the other. This can create a deadlock situation where neither module can be loaded properly. Avoid circular dependencies by ensuring that each module depends only on its direct dependencies and not on indirect dependencies.
|
156
|
+
5. **Lack of documentation:** Failing to document your dependencies clearly can lead to confusion and misinterpretation of your code. Be sure to provide clear and concise documentation for each module, including its purpose, intended use, and any specific requirements or dependencies.
|
157
|
+
|
158
|
+
Here's an example of how you might implement some of these best practices in practice:
|
159
|
+
|
160
|
+
```ruby
|
161
|
+
# Define a simple logging module with two methods: info and error
|
162
|
+
module Logging
|
163
|
+
def log_info(message)
|
164
|
+
puts "[INFO] #{message}"
|
165
|
+
end
|
166
|
+
|
167
|
+
def log_error(message)
|
168
|
+
puts "[ERROR] #{message}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
|
172
|
+
# Define a validation module with two methods: validate_presence and validate_format
|
173
|
+
module Validation
|
174
|
+
def validate_presence(attribute, value)
|
175
|
+
raise "Attribute '#{attribute}' is missing" if value.nil?
|
176
|
+
end
|
177
|
+
|
178
|
+
def validate_format(attribute, format)
|
179
|
+
raise "Invalid format for attribute '#{attribute}' (expected: #{format})" unless value =~ /#{format}/
|
180
|
+
end
|
181
|
+
end
|
182
|
+
|
183
|
+
# Define a User class that includes Logging and Validation modules
|
184
|
+
class User
|
185
|
+
include Logging
|
186
|
+
include Validation
|
187
|
+
|
188
|
+
attr_accessor :name, :email
|
189
|
+
|
190
|
+
def initialize(name, email)
|
191
|
+
@name = name
|
192
|
+
@email = email
|
193
|
+
end
|
194
|
+
|
195
|
+
# Method to create a new user with validation and logging
|
196
|
+
def create
|
197
|
+
validate_presence(:name, @name)
|
198
|
+
validate_format(:email, /\A[\w+\-.]+@[a-z\d\-]+(\.[a-z\d\-]+)*\.([a-z\d]([a-z\d\-.]*){2,})\z/)
|
199
|
+
|
200
|
+
log_info("Created new user: #{@name}")
|
201
|
+
end
|
202
|
+
end
|
203
|
+
```
|
204
|
+
|
205
|
+
In this example, we define two simple modules (Logging and Validation) with their respective methods. We then include these modules in a User class, which includes both logging and validation functionality. By documenting each module clearly and encapsulating related functionality within the same module, we can minimize complexity and potential for conflicts. Additionally, by declaring dependencies explicitly at the beginning of our class definition, we make it easier for other developers to understand the flow of our code.
|
206
|
+
### Q: A possible follow-up question could be: "Can you explain how the order of inclusion matters when dealing with dependencies in Ruby using `include` and `prepend`, and provide an example of unexpected behavior that might occur due to inconsistent ordering?"
|
207
|
+
#### A: Absolutely! When managing dependencies in Ruby with `include` and `prepend`, the order in which you include or prepend modules is crucial. This is because the order determines the method chain for each class or module, and can impact the behavior of your code.\
|
208
|
+
\
|
209
|
+
Let's consider an example where we have two modules, `ModuleA` and `ModuleB`, with each defining a method named `method_x`. If we include or prepend these modules in different orders, it can lead to unexpected behavior:\
|
210
|
+
```ruby\n\n# Define ModuleA with method x\nmodule ModuleA\n def method_x\n puts "Method X from Module A"\n end\nend\n\n# Define ModuleB with method x\nmodule ModuleB\n def method_x\n puts "Method X from Module B"\n end\nend\n\nclass MyClass\n # Inconsistent ordering: include ModuleA, then include ModuleB\n include ModuleA\n include ModuleB\n\n # Expected output: "Method X from Module A" when calling method_x\nend\n\n# Output: "Method X from Module B" instead of "Method X from Module A", due to inconsistent ordering\nMyClass.new.method_x\n```
|
211
|
+
In the example above, we define two modules, `ModuleA` and `ModuleB`, each with a method named `method_x`. We then create a class called `MyClass`, which includes both `ModuleA` and `ModuleB` in an inconsistent order. This results in the `method_x` from `ModuleB` being called instead of `ModuleA` when we call `my_class.new.method_x`.
|
212
|
+
\
|
213
|
+
The inconsistent ordering can cause unexpected behavior because each module extends the previous one, creating a chain of inheritance that determines which method is actually called when you invoke a method with that name. In our example, because we included `ModuleB` after `ModuleA`, Ruby uses the definition of `method_x` from `ModuleB` instead of `ModuleA`.
|
214
|
+
\
|
215
|
+
To avoid unexpected behavior due to inconsistent ordering, make sure to declare all dependencies at the beginning of your class definition, preferably in the correct order. In our example above, we should have included `ModuleA` before `ModuleB`:
|
216
|
+
```ruby\nclass MyClass\n include ModuleA\n include ModuleB\n # Expected output: "Method X from Module A" when calling method_x\nend\n```
|
217
|
+
This way, we ensure that the definition of `method_x` from `ModuleA` is used instead of `ModuleB`, as intended.
|
data/Rakefile
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
require_relative 'base'
|
5
|
+
|
6
|
+
class Ollama < Base
|
7
|
+
def initialize
|
8
|
+
@uri = URI('http://localhost:11434/api/chat')
|
9
|
+
end
|
10
|
+
|
11
|
+
def prompt(question)
|
12
|
+
response = Net::HTTP.start(@uri.hostname, @uri.port, use_ssl: @uri.scheme == 'https') do |http|
|
13
|
+
http.post(@uri, JSON.dump({
|
14
|
+
messages: [{ role: 'user', content: question }],
|
15
|
+
model: 'mistral',
|
16
|
+
stream: false
|
17
|
+
}), 'Content-Type' => 'application/json')
|
18
|
+
end
|
19
|
+
|
20
|
+
(JSON.parse(response.body) || {}).dig('message', 'content')
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
class Conversation
|
2
|
+
attr_accessor :max_responses, :conversation_context, :client
|
3
|
+
|
4
|
+
def initialize(client, max_responses = 5, &configuration)
|
5
|
+
@client = client
|
6
|
+
@max_responses = max_responses
|
7
|
+
@stop_condition_block = nil
|
8
|
+
@follow_up_block = nil
|
9
|
+
@conversation_context = []
|
10
|
+
instance_eval(&configuration) if block_given?
|
11
|
+
end
|
12
|
+
|
13
|
+
def stop_condition(&block)
|
14
|
+
@stop_condition_block = block
|
15
|
+
end
|
16
|
+
|
17
|
+
def follow_up_on(&block)
|
18
|
+
@follow_up_block = block
|
19
|
+
end
|
20
|
+
|
21
|
+
def start(initial_question)
|
22
|
+
depth = 0
|
23
|
+
conversation_context.clear
|
24
|
+
current_question = initial_question
|
25
|
+
previous_response = ""
|
26
|
+
|
27
|
+
while continue_conversation?(depth, previous_response)
|
28
|
+
response = @client.prompt(current_question_with_previous_context(current_question, conversation_context))
|
29
|
+
puts "###Q: #{current_question}"
|
30
|
+
puts "####A: #{response}"
|
31
|
+
conversation_context << { role: 'system', content: response }
|
32
|
+
|
33
|
+
previous_response = response
|
34
|
+
depth += 1
|
35
|
+
|
36
|
+
break unless @follow_up_block
|
37
|
+
|
38
|
+
current_question = instance_exec(response, &@follow_up_block)
|
39
|
+
end
|
40
|
+
|
41
|
+
current_conversation
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def current_question_with_previous_context(current_question, conversation_context)
|
47
|
+
"#{current_conversation}#{current_question}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def current_conversation
|
51
|
+
conversation_context.join("\n")
|
52
|
+
end
|
53
|
+
|
54
|
+
def previous_context
|
55
|
+
conversation_context.join("\n")
|
56
|
+
end
|
57
|
+
|
58
|
+
def continue_conversation?(depth, previous_response)
|
59
|
+
return !@stop_condition_block.call(depth, previous_response) if @stop_condition_block
|
60
|
+
|
61
|
+
depth < @max_responses
|
62
|
+
end
|
63
|
+
|
64
|
+
def prompt(question)
|
65
|
+
client.prompt(question)
|
66
|
+
end
|
67
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative '../clients/ollama'
|
2
|
+
|
3
|
+
class Base
|
4
|
+
attr_accessor :client, :conversation, :max_responses
|
5
|
+
|
6
|
+
def initialize(max_responses = 5)
|
7
|
+
@client = Ollama.new
|
8
|
+
@max_responses = max_responses
|
9
|
+
end
|
10
|
+
|
11
|
+
def prompt(question)
|
12
|
+
raise NotImplementedError, "Each template should implement it's own conversation."
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
class FiveWhys < Base
|
4
|
+
def prompt(question)
|
5
|
+
@conversation = Conversation.new(client, max_responses) do
|
6
|
+
stop_condition do |depth, response|
|
7
|
+
response.include?("i do not know") || depth >= @max_responses
|
8
|
+
end
|
9
|
+
|
10
|
+
follow_up_on do |_response|
|
11
|
+
['Why is that?',
|
12
|
+
'What do you mean by that?',
|
13
|
+
'Are there other approaches?',
|
14
|
+
'Can you clarify?'].shuffle.first
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
conversation.start(question)
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require_relative 'base'
|
2
|
+
|
3
|
+
class TechnicalOutline < Base
|
4
|
+
def prompt(question)
|
5
|
+
@conversation = Conversation.new(client, max_responses) do
|
6
|
+
stop_condition do |depth, response|
|
7
|
+
response.include?("we are done") || depth >= max_responses
|
8
|
+
end
|
9
|
+
|
10
|
+
follow_up_on do |response|
|
11
|
+
prompt "What is a good follow up question for #{response}? No compliments, no commentary, just a short follow up question. Or are we done?"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
conversation.start(question)
|
16
|
+
end
|
17
|
+
end
|
data/lib/reprompt.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "reprompt/version"
|
4
|
+
require_relative 'reprompt/conversation'
|
5
|
+
|
6
|
+
require_relative 'reprompt/clients/base'
|
7
|
+
require_relative 'reprompt/clients/ollama'
|
8
|
+
|
9
|
+
require_relative 'reprompt/templates/base'
|
10
|
+
require_relative 'reprompt/templates/five_whys'
|
11
|
+
require_relative 'reprompt/templates/technical_outline'
|
12
|
+
|
13
|
+
module Reprompt
|
14
|
+
class Error < StandardError; end
|
15
|
+
# Your code goes here...
|
16
|
+
end
|
data/reprompt.gemspec
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "lib/reprompt/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "reprompt"
|
7
|
+
spec.version = Reprompt::VERSION
|
8
|
+
spec.authors = ["Jim Jones"]
|
9
|
+
spec.email = ["jim.jones1@gmail.com"]
|
10
|
+
|
11
|
+
spec.summary = "Create Ruby classes that iteratively solve problems or create content."
|
12
|
+
spec.homepage = "https://www.github.com/aantix/reprompter"
|
13
|
+
spec.license = "MIT"
|
14
|
+
spec.required_ruby_version = ">= 2.6.0"
|
15
|
+
|
16
|
+
spec.metadata["homepage_uri"] = spec.homepage
|
17
|
+
spec.metadata["source_code_uri"] = "https://www.github.com/aantix/reprompter"
|
18
|
+
|
19
|
+
# Specify which files should be added to the gem when it is released.
|
20
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
21
|
+
spec.files = Dir.chdir(__dir__) do
|
22
|
+
`git ls-files -z`.split("\x0").reject do |f|
|
23
|
+
(File.expand_path(f) == __FILE__) ||
|
24
|
+
f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
|
25
|
+
end
|
26
|
+
end
|
27
|
+
spec.bindir = "exe"
|
28
|
+
spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
|
29
|
+
spec.require_paths = ["lib"]
|
30
|
+
|
31
|
+
# Uncomment to register a new dependency of your gem
|
32
|
+
# spec.add_dependency "example-gem", "~> 1.0"
|
33
|
+
|
34
|
+
# For more information and examples about making a new gem, check out our
|
35
|
+
# guide at: https://bundler.io/guides/creating_gem.html
|
36
|
+
end
|
data/sig/reprompt.rbs
ADDED
metadata
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: reprompt
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jim Jones
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2024-03-29 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
- jim.jones1@gmail.com
|
16
|
+
executables: []
|
17
|
+
extensions: []
|
18
|
+
extra_rdoc_files: []
|
19
|
+
files:
|
20
|
+
- ".rspec"
|
21
|
+
- ".rubocop.yml"
|
22
|
+
- LICENSE.txt
|
23
|
+
- README.md
|
24
|
+
- Rakefile
|
25
|
+
- lib/reprompt.rb
|
26
|
+
- lib/reprompt/clients/base.rb
|
27
|
+
- lib/reprompt/clients/ollama.rb
|
28
|
+
- lib/reprompt/conversation.rb
|
29
|
+
- lib/reprompt/templates/base.rb
|
30
|
+
- lib/reprompt/templates/five_whys.rb
|
31
|
+
- lib/reprompt/templates/technical_outline.rb
|
32
|
+
- lib/reprompt/version.rb
|
33
|
+
- reprompt.gemspec
|
34
|
+
- sig/reprompt.rbs
|
35
|
+
homepage: https://www.github.com/aantix/reprompter
|
36
|
+
licenses:
|
37
|
+
- MIT
|
38
|
+
metadata:
|
39
|
+
homepage_uri: https://www.github.com/aantix/reprompter
|
40
|
+
source_code_uri: https://www.github.com/aantix/reprompter
|
41
|
+
post_install_message:
|
42
|
+
rdoc_options: []
|
43
|
+
require_paths:
|
44
|
+
- lib
|
45
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
46
|
+
requirements:
|
47
|
+
- - ">="
|
48
|
+
- !ruby/object:Gem::Version
|
49
|
+
version: 2.6.0
|
50
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
requirements: []
|
56
|
+
rubygems_version: 3.2.3
|
57
|
+
signing_key:
|
58
|
+
specification_version: 4
|
59
|
+
summary: Create Ruby classes that iteratively solve problems or create content.
|
60
|
+
test_files: []
|