deepagents_rails 0.1.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 +7 -0
- data/LICENSE +21 -0
- data/README.md +309 -0
- data/lib/deepagents_rails/service.rb +93 -0
- data/lib/deepagents_rails/version.rb +3 -0
- data/lib/deepagents_rails.rb +31 -0
- data/lib/generators/deepagents/agent/agent_generator.rb +55 -0
- data/lib/generators/deepagents/agent/templates/agent.rb +99 -0
- data/lib/generators/deepagents/agent/templates/agent_spec.rb +33 -0
- data/lib/generators/deepagents/agent/templates/controller.rb +44 -0
- data/lib/generators/deepagents/agent/templates/index.html.erb +178 -0
- data/lib/generators/deepagents/agent/templates/show.html.erb +131 -0
- data/lib/generators/deepagents/controller/controller_generator.rb +51 -0
- data/lib/generators/deepagents/controller/templates/api_controller.rb +87 -0
- data/lib/generators/deepagents/controller/templates/serializer.rb +22 -0
- data/lib/generators/deepagents/install/install_generator.rb +41 -0
- data/lib/generators/deepagents/install/templates/deepagents.yml +38 -0
- data/lib/generators/deepagents/install/templates/initializer.rb +35 -0
- data/lib/generators/deepagents/model/model_generator.rb +43 -0
- data/lib/generators/deepagents/model/templates/conversation.rb +73 -0
- data/lib/generators/deepagents/model/templates/create_conversations_migration.rb +16 -0
- data/lib/generators/deepagents/model/templates/create_files_migration.rb +17 -0
- data/lib/generators/deepagents/model/templates/create_messages_migration.rb +17 -0
- data/lib/generators/deepagents/model/templates/file.rb +96 -0
- data/lib/generators/deepagents/model/templates/message.rb +30 -0
- data/lib/generators/deepagents/tool/templates/tool.rb +27 -0
- data/lib/generators/deepagents/tool/templates/tool_spec.rb +36 -0
- data/lib/generators/deepagents/tool/tool_generator.rb +58 -0
- data/lib/generators/deepagents/view/templates/_conversation.html.erb +10 -0
- data/lib/generators/deepagents/view/templates/_form.html.erb +33 -0
- data/lib/generators/deepagents/view/templates/_message.html.erb +31 -0
- data/lib/generators/deepagents/view/templates/index.html.erb +35 -0
- data/lib/generators/deepagents/view/templates/javascript.js +199 -0
- data/lib/generators/deepagents/view/templates/new.html.erb +10 -0
- data/lib/generators/deepagents/view/templates/show.html.erb +54 -0
- data/lib/generators/deepagents/view/templates/stylesheet.css +397 -0
- data/lib/generators/deepagents/view/view_generator.rb +50 -0
- metadata +121 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 942335db72adaeaf978062114daab11271909b68fb6e1c1323744a7c45d2593e
|
|
4
|
+
data.tar.gz: 3d78ea62b62e1ea92cd8c403d5044c091e68feeff9d0c7c0a6dc430dac3f28be
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: a536b7e86fdd1b388cfc1396348cd2b26883bad3d47d916c5699930264454016c71820e45af7980da97ec79ec0fe96f5b7f7470cb629e6937120193f74dda76b
|
|
7
|
+
data.tar.gz: 0fa9aa9200c7bc02f19228cdbc5a632120fe09f6da5e114022d587acad04e2d75387d3c42178e5fe1228188be84c921c91380935a3871f24875ee6d1eac77f8f
|
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Chris Davis
|
|
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 all
|
|
13
|
+
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 THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,309 @@
|
|
|
1
|
+
# DeepAgents for Rails
|
|
2
|
+
|
|
3
|
+
DeepAgents Rails is a Ruby on Rails integration for the [DeepAgents](https://github.com/yourusername/deepagents) gem, providing easy setup and scaffolding for adding AI agent capabilities to your Rails applications.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- **Rails Integration**: Seamlessly integrate DeepAgents with your Rails application
|
|
8
|
+
- **Generators**: Quickly scaffold agents, tools, models, controllers, and views
|
|
9
|
+
- **UI Components**: Pre-built UI for agent conversations
|
|
10
|
+
- **API Endpoints**: Ready-to-use API endpoints for agent interactions
|
|
11
|
+
- **Database Models**: Store and retrieve conversation history
|
|
12
|
+
- **File Handling**: Upload and process files with your agents
|
|
13
|
+
|
|
14
|
+
## Installation
|
|
15
|
+
|
|
16
|
+
Add this line to your application's Gemfile:
|
|
17
|
+
|
|
18
|
+
```ruby
|
|
19
|
+
gem 'deepagents_rails'
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
And then execute:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
$ bundle install
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
Or install it yourself as:
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
$ gem install deepagents_rails
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Then run the installation generator:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
$ rails generate deepagents:install
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
This will:
|
|
41
|
+
- Create a configuration file at `config/deepagents.yml`
|
|
42
|
+
- Create an initializer at `config/initializers/deepagents.rb`
|
|
43
|
+
- Mount the DeepAgents Rails engine in your routes
|
|
44
|
+
- Add environment variable examples to `.env.example`
|
|
45
|
+
|
|
46
|
+
## Configuration
|
|
47
|
+
|
|
48
|
+
After installation, you can configure DeepAgents Rails in `config/initializers/deepagents.rb`:
|
|
49
|
+
|
|
50
|
+
```ruby
|
|
51
|
+
# config/initializers/deepagents.rb
|
|
52
|
+
DeepagentsRails::Engine.config.deepagents.tap do |config|
|
|
53
|
+
config.api_key = ENV['DEEPAGENTS_API_KEY']
|
|
54
|
+
config.provider = ENV['DEEPAGENTS_PROVIDER']&.to_sym || :claude
|
|
55
|
+
config.model = ENV['DEEPAGENTS_MODEL'] || 'claude-3-sonnet-20240229'
|
|
56
|
+
config.temperature = ENV['DEEPAGENTS_TEMPERATURE']&.to_f || 0.7
|
|
57
|
+
config.max_tokens = ENV['DEEPAGENTS_MAX_TOKENS']&.to_i || 2000
|
|
58
|
+
end
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
You can also use the YAML configuration file at `config/deepagents.yml`:
|
|
62
|
+
|
|
63
|
+
```yaml
|
|
64
|
+
# config/deepagents.yml
|
|
65
|
+
default: &default
|
|
66
|
+
provider: claude
|
|
67
|
+
model: claude-3-sonnet-20240229
|
|
68
|
+
temperature: 0.7
|
|
69
|
+
max_tokens: 2000
|
|
70
|
+
|
|
71
|
+
development:
|
|
72
|
+
<<: *default
|
|
73
|
+
api_key: <%= ENV['DEEPAGENTS_API_KEY'] %>
|
|
74
|
+
|
|
75
|
+
test:
|
|
76
|
+
<<: *default
|
|
77
|
+
provider: mock
|
|
78
|
+
api_key: test_key
|
|
79
|
+
|
|
80
|
+
production:
|
|
81
|
+
<<: *default
|
|
82
|
+
api_key: <%= ENV['DEEPAGENTS_API_KEY'] %>
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Usage
|
|
86
|
+
|
|
87
|
+
### Creating an Agent
|
|
88
|
+
|
|
89
|
+
Generate a new agent with:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
$ rails generate deepagents:agent research
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
This will create:
|
|
96
|
+
- An agent class at `app/deepagents/agents/research_agent.rb`
|
|
97
|
+
- A controller at `app/controllers/researches_controller.rb`
|
|
98
|
+
- Views at `app/views/researches/`
|
|
99
|
+
- A test file at `spec/deepagents/agents/research_agent_spec.rb`
|
|
100
|
+
- Routes for the agent
|
|
101
|
+
|
|
102
|
+
You can then customize your agent:
|
|
103
|
+
|
|
104
|
+
```ruby
|
|
105
|
+
# app/deepagents/agents/research_agent.rb
|
|
106
|
+
module Deepagents
|
|
107
|
+
module Agents
|
|
108
|
+
class ResearchAgent
|
|
109
|
+
def initialize(options = {})
|
|
110
|
+
@model = DeepAgents::Models::Claude.new(
|
|
111
|
+
api_key: DeepagentsRails::Engine.config.deepagents.api_key,
|
|
112
|
+
model: DeepagentsRails::Engine.config.deepagents.model
|
|
113
|
+
)
|
|
114
|
+
@agent = DeepAgents::Agent.new(@model)
|
|
115
|
+
setup_tools
|
|
116
|
+
setup_subagents
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def setup_tools
|
|
120
|
+
# Add your tools here
|
|
121
|
+
@agent.add_tool(Deepagents::Tools::SearchTool.build)
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def setup_subagents
|
|
125
|
+
# Add your subagents here
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def run(input, context = {})
|
|
129
|
+
@agent.run(input, context)
|
|
130
|
+
end
|
|
131
|
+
end
|
|
132
|
+
end
|
|
133
|
+
end
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### Creating a Tool
|
|
137
|
+
|
|
138
|
+
Generate a new tool with:
|
|
139
|
+
|
|
140
|
+
```bash
|
|
141
|
+
$ rails generate deepagents:tool search --description="Search for information" --parameters=query,limit
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
This will create:
|
|
145
|
+
- A tool class at `app/deepagents/tools/search_tool.rb`
|
|
146
|
+
- A test file at `spec/deepagents/tools/search_tool_spec.rb`
|
|
147
|
+
|
|
148
|
+
You can then customize your tool:
|
|
149
|
+
|
|
150
|
+
```ruby
|
|
151
|
+
# app/deepagents/tools/search_tool.rb
|
|
152
|
+
module Deepagents
|
|
153
|
+
module Tools
|
|
154
|
+
class SearchTool
|
|
155
|
+
def self.build
|
|
156
|
+
DeepAgents::Tool.new(
|
|
157
|
+
"search",
|
|
158
|
+
"Search for information"
|
|
159
|
+
) do |query, limit|
|
|
160
|
+
# Implement your tool's functionality here
|
|
161
|
+
# This block will be called when the agent uses this tool
|
|
162
|
+
|
|
163
|
+
begin
|
|
164
|
+
# Example implementation
|
|
165
|
+
"Found #{limit || 10} results for: #{query}"
|
|
166
|
+
rescue => e
|
|
167
|
+
"Error in search tool: #{e.message}"
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
end
|
|
174
|
+
```
|
|
175
|
+
|
|
176
|
+
### Creating Models for Conversation Storage
|
|
177
|
+
|
|
178
|
+
Generate models for storing conversations:
|
|
179
|
+
|
|
180
|
+
```bash
|
|
181
|
+
$ rails generate deepagents:model chat
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This will create:
|
|
185
|
+
- Models at `app/models/deepagents/chat_conversation.rb`, `app/models/deepagents/chat_message.rb`, and `app/models/deepagents/chat_file.rb`
|
|
186
|
+
- Migrations for creating the necessary tables
|
|
187
|
+
|
|
188
|
+
Run the migrations:
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
$ rails db:migrate
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
You can then use these models to store and retrieve conversations:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
# Create a new conversation
|
|
198
|
+
conversation = Deepagents::ChatConversation.create!(title: "My Chat")
|
|
199
|
+
|
|
200
|
+
# Add a system message
|
|
201
|
+
conversation.chat_messages.create!(role: "system", content: "You are a helpful assistant.")
|
|
202
|
+
|
|
203
|
+
# Add a user message
|
|
204
|
+
conversation.chat_messages.create!(role: "user", content: "Hello!")
|
|
205
|
+
|
|
206
|
+
# Run the agent with the conversation context
|
|
207
|
+
result = conversation.run_agent("Tell me about Ruby on Rails")
|
|
208
|
+
|
|
209
|
+
# Access the assistant's response
|
|
210
|
+
puts result[:message].content
|
|
211
|
+
```
|
|
212
|
+
|
|
213
|
+
### Creating API Endpoints
|
|
214
|
+
|
|
215
|
+
Generate API controllers for your agents:
|
|
216
|
+
|
|
217
|
+
```bash
|
|
218
|
+
$ rails generate deepagents:controller chat --api_version=v1
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
This will create:
|
|
222
|
+
- An API controller at `app/controllers/api/v1/chat_controller.rb`
|
|
223
|
+
- Serializers at `app/serializers/chat_serializer.rb`
|
|
224
|
+
- Routes for the API endpoints
|
|
225
|
+
|
|
226
|
+
You can then use these endpoints to interact with your agents:
|
|
227
|
+
|
|
228
|
+
```
|
|
229
|
+
GET /api/v1/chats # List conversations
|
|
230
|
+
GET /api/v1/chats/:id # Get a conversation
|
|
231
|
+
POST /api/v1/chats # Create a conversation
|
|
232
|
+
POST /api/v1/chats/:id/run # Run the agent
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
### Creating UI Components
|
|
236
|
+
|
|
237
|
+
Generate UI views for your agents:
|
|
238
|
+
|
|
239
|
+
```bash
|
|
240
|
+
$ rails generate deepagents:view chat
|
|
241
|
+
```
|
|
242
|
+
|
|
243
|
+
This will create:
|
|
244
|
+
- Views at `app/views/chats/`
|
|
245
|
+
- JavaScript at `app/javascript/chat_chat.js`
|
|
246
|
+
- CSS at `app/assets/stylesheets/chat_chat.css`
|
|
247
|
+
|
|
248
|
+
You can then access the UI at:
|
|
249
|
+
|
|
250
|
+
```
|
|
251
|
+
GET /chats # List conversations
|
|
252
|
+
GET /chats/:id # View a conversation
|
|
253
|
+
GET /chats/new # Create a new conversation
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
## Service Integration
|
|
257
|
+
|
|
258
|
+
You can use the DeepAgents Rails service to interact with your agents:
|
|
259
|
+
|
|
260
|
+
```ruby
|
|
261
|
+
# Get a service instance with the default agent
|
|
262
|
+
service = DeepagentsRails.service
|
|
263
|
+
|
|
264
|
+
# Get a service instance with a specific agent
|
|
265
|
+
service = DeepagentsRails.service(:research)
|
|
266
|
+
|
|
267
|
+
# Run the agent
|
|
268
|
+
result = service.run("Tell me about Ruby on Rails")
|
|
269
|
+
|
|
270
|
+
# Get available tools
|
|
271
|
+
tools = service.available_tools
|
|
272
|
+
|
|
273
|
+
# Get available agents
|
|
274
|
+
agents = service.available_agents
|
|
275
|
+
```
|
|
276
|
+
|
|
277
|
+
## Testing
|
|
278
|
+
|
|
279
|
+
DeepAgents Rails includes a mock provider for testing:
|
|
280
|
+
|
|
281
|
+
```ruby
|
|
282
|
+
# config/environments/test.rb
|
|
283
|
+
config.deepagents.provider = :mock
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
You can then test your agents without making actual API calls:
|
|
287
|
+
|
|
288
|
+
```ruby
|
|
289
|
+
# spec/deepagents/agents/research_agent_spec.rb
|
|
290
|
+
RSpec.describe Deepagents::Agents::ResearchAgent do
|
|
291
|
+
it "returns a response" do
|
|
292
|
+
agent = described_class.new
|
|
293
|
+
result = agent.run("Tell me about Ruby on Rails")
|
|
294
|
+
expect(result[:response]).to include("Ruby on Rails")
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
## Contributing
|
|
300
|
+
|
|
301
|
+
1. Fork it
|
|
302
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
|
303
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
|
304
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
|
305
|
+
5. Create new Pull Request
|
|
306
|
+
|
|
307
|
+
## License
|
|
308
|
+
|
|
309
|
+
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module DeepagentsRails
|
|
4
|
+
# Service class for interacting with DeepAgents in a Rails application
|
|
5
|
+
class Service
|
|
6
|
+
attr_reader :agent, :config
|
|
7
|
+
|
|
8
|
+
# Initialize a new DeepAgents service
|
|
9
|
+
# @param agent_name [Symbol, String] The name of the agent to use
|
|
10
|
+
# @param options [Hash] Additional options for the agent
|
|
11
|
+
def initialize(agent_name = nil, options = {})
|
|
12
|
+
@config = DeepagentsRails::Engine.config.deepagents
|
|
13
|
+
@agent_name = agent_name || :default
|
|
14
|
+
@options = options
|
|
15
|
+
|
|
16
|
+
# Load the agent if specified
|
|
17
|
+
load_agent if @agent_name
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
# Run the agent with the given input
|
|
21
|
+
# @param input [String] The input to send to the agent
|
|
22
|
+
# @param context [Hash] Additional context for the agent
|
|
23
|
+
# @return [Hash] The agent's response
|
|
24
|
+
def run(input, context = {})
|
|
25
|
+
ensure_agent_loaded
|
|
26
|
+
|
|
27
|
+
# Run the agent
|
|
28
|
+
@agent.run(input, context)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
# Get a list of available tools
|
|
32
|
+
# @return [Array<DeepAgents::Tool>] The available tools
|
|
33
|
+
def available_tools
|
|
34
|
+
tools = []
|
|
35
|
+
|
|
36
|
+
# Load tools from the Rails app
|
|
37
|
+
Dir[Rails.root.join('app/deepagents/tools/**/*_tool.rb')].each do |file|
|
|
38
|
+
require file
|
|
39
|
+
|
|
40
|
+
# Extract the tool class name from the file path
|
|
41
|
+
tool_name = File.basename(file, '.rb').gsub('_tool', '')
|
|
42
|
+
tool_class_name = tool_name.camelize
|
|
43
|
+
|
|
44
|
+
# Try to load the tool class
|
|
45
|
+
begin
|
|
46
|
+
tool_class = "Deepagents::Tools::#{tool_class_name}Tool".constantize
|
|
47
|
+
tools << tool_class.build if tool_class.respond_to?(:build)
|
|
48
|
+
rescue NameError => e
|
|
49
|
+
Rails.logger.warn("Could not load tool class for #{tool_name}: #{e.message}")
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
tools
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Get a list of available agents
|
|
57
|
+
# @return [Array<String>] The available agent names
|
|
58
|
+
def available_agents
|
|
59
|
+
agents = []
|
|
60
|
+
|
|
61
|
+
# Load agents from the Rails app
|
|
62
|
+
Dir[Rails.root.join('app/deepagents/agents/**/*_agent.rb')].each do |file|
|
|
63
|
+
# Extract the agent name from the file path
|
|
64
|
+
agent_name = File.basename(file, '.rb').gsub('_agent', '')
|
|
65
|
+
agents << agent_name
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
agents
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# Load the specified agent
|
|
74
|
+
def load_agent
|
|
75
|
+
agent_class_name = @agent_name.to_s.camelize
|
|
76
|
+
|
|
77
|
+
begin
|
|
78
|
+
agent_class = "Deepagents::Agents::#{agent_class_name}Agent".constantize
|
|
79
|
+
@agent = agent_class.new(@options)
|
|
80
|
+
rescue NameError => e
|
|
81
|
+
Rails.logger.error("Could not load agent class for #{@agent_name}: #{e.message}")
|
|
82
|
+
raise "Agent not found: #{@agent_name}"
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
# Ensure that an agent is loaded
|
|
87
|
+
def ensure_agent_loaded
|
|
88
|
+
if @agent.nil?
|
|
89
|
+
raise "No agent loaded. Please specify an agent name when initializing the service."
|
|
90
|
+
end
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
require "deepagents_rails/version"
|
|
2
|
+
require "deepagents_rails/service"
|
|
3
|
+
require "deepagents"
|
|
4
|
+
require "rails"
|
|
5
|
+
|
|
6
|
+
module DeepagentsRails
|
|
7
|
+
class Engine < ::Rails::Engine
|
|
8
|
+
isolate_namespace DeepagentsRails
|
|
9
|
+
|
|
10
|
+
config.deepagents = ActiveSupport::OrderedOptions.new
|
|
11
|
+
config.deepagents.api_key = nil
|
|
12
|
+
config.deepagents.model = "claude-3-sonnet-20240229"
|
|
13
|
+
config.deepagents.provider = :claude
|
|
14
|
+
|
|
15
|
+
initializer "deepagents_rails.configure" do |app|
|
|
16
|
+
# Load configuration from config/initializers/deepagents.rb if it exists
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
config.to_prepare do
|
|
20
|
+
# Load deepagents tools and agents when the Rails app boots
|
|
21
|
+
Dir.glob(Rails.root.join("app/deepagents/**/*.rb")).sort.each do |file|
|
|
22
|
+
require_dependency file
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# Helper method to create a new service instance
|
|
28
|
+
def self.service(agent_name = nil, options = {})
|
|
29
|
+
Service.new(agent_name, options)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
module Deepagents
|
|
2
|
+
module Generators
|
|
3
|
+
class AgentGenerator < Rails::Generators::NamedBase
|
|
4
|
+
source_root File.expand_path('templates', __dir__)
|
|
5
|
+
|
|
6
|
+
desc "Creates a new DeepAgents agent for your Rails application"
|
|
7
|
+
|
|
8
|
+
class_option :tools, type: :array, default: [], desc: "Tools to include with this agent"
|
|
9
|
+
class_option :model, type: :string, desc: "Model to use for this agent (claude, openai, etc.)"
|
|
10
|
+
class_option :subagents, type: :array, default: [], desc: "Subagents to include with this agent"
|
|
11
|
+
|
|
12
|
+
def create_agent_file
|
|
13
|
+
template "agent.rb", "app/deepagents/agents/#{file_name}_agent.rb"
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create_agent_spec_file
|
|
17
|
+
template "agent_spec.rb", "spec/deepagents/agents/#{file_name}_agent_spec.rb"
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def create_agent_controller
|
|
21
|
+
template "controller.rb", "app/controllers/deepagents/#{file_name}_controller.rb"
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def create_agent_views
|
|
25
|
+
template "index.html.erb", "app/views/deepagents/#{file_name}/index.html.erb"
|
|
26
|
+
template "show.html.erb", "app/views/deepagents/#{file_name}/show.html.erb"
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def update_routes
|
|
30
|
+
route "namespace :deepagents do\n resources :#{file_name}, only: [:index, :show, :create]\n end"
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def display_next_steps
|
|
34
|
+
say "\n"
|
|
35
|
+
say "Agent #{file_name} has been created! 🤖", :green
|
|
36
|
+
say "\n"
|
|
37
|
+
say "Next steps:", :yellow
|
|
38
|
+
say " 1. Edit app/deepagents/agents/#{file_name}_agent.rb to customize your agent"
|
|
39
|
+
say " 2. Add any custom tools in app/deepagents/tools/"
|
|
40
|
+
say " 3. Access your agent at /deepagents/#{file_name}"
|
|
41
|
+
say "\n"
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
private
|
|
45
|
+
|
|
46
|
+
def model_name
|
|
47
|
+
options[:model] || "DeepagentsRails::Engine.config.deepagents.provider"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def tools_list
|
|
51
|
+
options[:tools].empty? ? "[]" : options[:tools].map { |t| ":#{t}" }.join(", ")
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deepagents
|
|
4
|
+
module Agents
|
|
5
|
+
class <%= class_name %>Agent
|
|
6
|
+
attr_reader :model, :tools, :subagents
|
|
7
|
+
|
|
8
|
+
def initialize(options = {})
|
|
9
|
+
# Initialize the model based on configuration
|
|
10
|
+
provider = options[:provider] || DeepagentsRails::Engine.config.deepagents.provider
|
|
11
|
+
model_name = options[:model] || DeepagentsRails::Engine.config.deepagents.model
|
|
12
|
+
api_key = options[:api_key] || DeepagentsRails::Engine.config.deepagents.api_key
|
|
13
|
+
|
|
14
|
+
@model = case provider.to_sym
|
|
15
|
+
when :claude
|
|
16
|
+
DeepAgents::Models::Claude.new(api_key: api_key, model: model_name)
|
|
17
|
+
when :openai
|
|
18
|
+
DeepAgents::Models::OpenAI.new(api_key: api_key, model: model_name)
|
|
19
|
+
else
|
|
20
|
+
DeepAgents::Models::MockModel.new(model: model_name)
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# Initialize tools
|
|
24
|
+
@tools = setup_tools(options[:tools] || [])
|
|
25
|
+
|
|
26
|
+
# Initialize subagents
|
|
27
|
+
@subagents = setup_subagents(options[:subagents] || [])
|
|
28
|
+
|
|
29
|
+
# Create the deep agent
|
|
30
|
+
@agent = create_agent
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def run(input, context = {})
|
|
34
|
+
# Run the agent with the given input and context
|
|
35
|
+
result = @agent.invoke({
|
|
36
|
+
messages: [{role: "user", content: input}],
|
|
37
|
+
files: context[:files] || {}
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
# Return the result
|
|
41
|
+
{
|
|
42
|
+
response: result.messages.last[:content],
|
|
43
|
+
files: result.files
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def setup_tools(tool_names)
|
|
50
|
+
tools = []
|
|
51
|
+
|
|
52
|
+
# Add default tools
|
|
53
|
+
tools << DeepAgents::Tool.new(
|
|
54
|
+
"calculator",
|
|
55
|
+
"Perform mathematical calculations"
|
|
56
|
+
) do |expression|
|
|
57
|
+
begin
|
|
58
|
+
eval(expression).to_s
|
|
59
|
+
rescue => e
|
|
60
|
+
"Error: #{e.message}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
# Add custom tools based on tool_names
|
|
65
|
+
# Implement your custom tools here
|
|
66
|
+
|
|
67
|
+
tools
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
def setup_subagents(subagent_configs)
|
|
71
|
+
subagents = []
|
|
72
|
+
|
|
73
|
+
# Add custom subagents based on subagent_configs
|
|
74
|
+
# Implement your custom subagents here
|
|
75
|
+
|
|
76
|
+
subagents
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def create_agent
|
|
80
|
+
# Define the agent's instructions
|
|
81
|
+
instructions = <<~INSTRUCTIONS
|
|
82
|
+
You are a helpful assistant named <%= class_name %>.
|
|
83
|
+
|
|
84
|
+
Your primary goal is to assist users with their questions and tasks.
|
|
85
|
+
|
|
86
|
+
Please be concise, accurate, and helpful in your responses.
|
|
87
|
+
INSTRUCTIONS
|
|
88
|
+
|
|
89
|
+
# Create and return the deep agent
|
|
90
|
+
DeepAgents.create_deep_agent(
|
|
91
|
+
@tools,
|
|
92
|
+
instructions,
|
|
93
|
+
model: @model,
|
|
94
|
+
subagents: @subagents
|
|
95
|
+
)
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'rails_helper'
|
|
4
|
+
|
|
5
|
+
RSpec.describe Deepagents::Agents::<%= class_name %>Agent do
|
|
6
|
+
let(:agent) { described_class.new(provider: :mock) }
|
|
7
|
+
|
|
8
|
+
describe '#initialize' do
|
|
9
|
+
it 'creates an agent with the correct model' do
|
|
10
|
+
expect(agent.model).to be_a(DeepAgents::Models::MockModel)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
it 'sets up the required tools' do
|
|
14
|
+
expect(agent.tools).not_to be_empty
|
|
15
|
+
expect(agent.tools.first).to be_a(DeepAgents::Tool)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
describe '#run' do
|
|
20
|
+
it 'returns a response when given input' do
|
|
21
|
+
result = agent.run('Hello, how are you?')
|
|
22
|
+
expect(result).to be_a(Hash)
|
|
23
|
+
expect(result[:response]).to be_a(String)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
it 'handles file context' do
|
|
27
|
+
result = agent.run('What is in the file?', files: { 'test.txt' => 'This is a test file.' })
|
|
28
|
+
expect(result).to be_a(Hash)
|
|
29
|
+
expect(result[:response]).to be_a(String)
|
|
30
|
+
expect(result[:files]).to be_a(Hash)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Deepagents
|
|
4
|
+
class <%= class_name %>Controller < ApplicationController
|
|
5
|
+
before_action :initialize_agent
|
|
6
|
+
|
|
7
|
+
def index
|
|
8
|
+
# Display the agent interface
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def show
|
|
12
|
+
# Display a specific conversation
|
|
13
|
+
@conversation = Conversation.find(params[:id])
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def create
|
|
17
|
+
# Process user input and get agent response
|
|
18
|
+
@input = params[:input]
|
|
19
|
+
|
|
20
|
+
# Get any file attachments
|
|
21
|
+
files = {}
|
|
22
|
+
if params[:files].present?
|
|
23
|
+
params[:files].each do |file|
|
|
24
|
+
files[file.original_filename] = file.read
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
# Run the agent
|
|
29
|
+
result = @agent.run(@input, files: files)
|
|
30
|
+
|
|
31
|
+
# Return the response
|
|
32
|
+
respond_to do |format|
|
|
33
|
+
format.html { redirect_to deepagents_<%= file_name %>_path, notice: "Response generated" }
|
|
34
|
+
format.json { render json: result }
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def initialize_agent
|
|
41
|
+
@agent = Deepagents::Agents::<%= class_name %>Agent.new
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|