ad-agent_architecture 0.0.4 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddf07e6fca1337e7800b3c85b1c48f44524aa14660827eb81ffe541bce122c49
4
- data.tar.gz: be8299cec2e18b52eebeb1af83fc243b172685b490cd581241d1d471b7de68ee
3
+ metadata.gz: daa2d7eacfdb1c2650cf23106d3f001040d765d7aa3ccf44081a989361e9ad48
4
+ data.tar.gz: b3fe1ef5e9d26a809d13ddb6200d125a17549b6af88b5995ba05e35788fcb608
5
5
  SHA512:
6
- metadata.gz: 92afeb1cb3bc9315da02dc33dbe280fa6ab1c43404886852c5e4b542345e00f8f0b48b504a5f45dce205dde146e6dc3f7cebc35b8d2cee777aee6f81ed7a6c9f
7
- data.tar.gz: 0167d391cb38acb70bd39dd0e454c21570531b86bb411b9b473869437f70a33374992f266c7cd10daa8f9ffd17697ffbd5784bb46056ffb4c71d3e34966926a2
6
+ metadata.gz: b09d423f903b09b704e958627b4a2cc4d1dbae248aee623e0750623e366f13247ab943043742702f8e0353ce4fe8a22ea7303f0f267a2ccce90c365239970947
7
+ data.tar.gz: be77db10d9e1fc55d9d18464714b57a8039b194a5c53ec963d7becdc743533ef60b06af6d18cf9ba13048446d09031d679fe239c3c5c3352870a8b3cbeac706f
data/.rubocop.yml CHANGED
@@ -14,6 +14,7 @@ AllCops:
14
14
  Exclude:
15
15
  - ".builders/**/*"
16
16
  - "spec/samples/**/*"
17
+ - "lib/ad/agent_architecture/db/*"
17
18
 
18
19
  Metrics/BlockLength:
19
20
  Exclude:
data/CHANGELOG.md CHANGED
@@ -1,3 +1,18 @@
1
+ ## [0.0.5](https://github.com/appydave/ad-agent_architecture/compare/v0.0.4...v0.0.5) (2024-06-28)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * add sqlite3, sequal and setup a schema ([a8fa9c9](https://github.com/appydave/ad-agent_architecture/commit/a8fa9c9ff29ed223644d3622bd46ca5d626af9a9))
7
+ * add sqlite3, sequal and setup a schema ([87ded1e](https://github.com/appydave/ad-agent_architecture/commit/87ded1e6886d3190fc83ecaa4e215bacf044378f))
8
+
9
+ ## [0.0.4](https://github.com/appydave/ad-agent_architecture/compare/v0.0.3...v0.0.4) (2024-06-26)
10
+
11
+
12
+ ### Bug Fixes
13
+
14
+ * update schema ([dd2d6fb](https://github.com/appydave/ad-agent_architecture/commit/dd2d6fbd1eb477da5e44f3d5417aa05ec291fb25))
15
+
1
16
  ## [0.0.3](https://github.com/appydave/ad-agent_architecture/compare/v0.0.2...v0.0.3) (2024-06-26)
2
17
 
3
18
 
Binary file
data/docs/requirements.md CHANGED
@@ -1,3 +1,65 @@
1
+ # AppyDave - Agent Architecture Schema
2
+
3
+ ## Purpose
4
+
5
+ The application is designed to handle structured workflows for building documents or text-based assets using LLMs from OpenAi, Anthropic and others. It should be adaptable to any workflow that follows a structured concept or a series of steps.
6
+
7
+ ## Sample Workflows
8
+ - YouTube titles
9
+ - YouTube scripts
10
+ - YouTube transcription to Medium, LinkedIn, etc.
11
+
12
+ ## Key Components
13
+
14
+ ### Static Workflow Definition
15
+ - **Workflows**: Define a series of tasks to achieve a specific goal.
16
+ - **Sections**: Subdivisions within workflows to organize steps logically.
17
+ - **Steps**: Individual tasks within a section, each associated with an AI prompt and various input/output attributes.
18
+ - **Attributes**: Parameters used in steps, which can be simple values or arrays.
19
+ - **Input/Output Attributes**: Map attributes to steps as either inputs or outputs.
20
+
21
+ ### Dynamic Workflow Execution
22
+ - **Workflow Runs**: Instances of workflow executions.
23
+ - **Section Runs**: Instances of section executions within a workflow run.
24
+ - **Step Runs**: Instances of step executions within a section run, supporting multiple branches.
25
+ - **Attribute Values**: Store the values of attributes during step executions.
26
+
27
+ ## Features
28
+
29
+ ### Schema Creation and Models
30
+ - Use Sequel and SQLite to define and manage the database schema.
31
+ - Models are defined for workflows, sections, steps, attributes, and their relationships.
32
+
33
+ ### Testing and Validation
34
+ - Unit tests to verify the schema and associations using RSpec.
35
+ - Guard setup to automatically run tests when certain files are modified.
36
+
37
+ ### Data Management
38
+ - Methods to export the database schema and data to JSON files for backup.
39
+ - Methods to restore the database from JSON files for easy editing and re-importing.
40
+
41
+ ## Initial Workflows
42
+ - These include YouTube video scripts, YouTube title creation, and transcription to articles.
43
+ - These workflows serve as examples and validation for the broader concept.
44
+
45
+ ## Implementation Details
46
+ - **Database**: Use SQLite with Sequel for ORM.
47
+ - **Code Structure**: Organize code into modules and classes for database schema creation and model definitions.
48
+ - **Testing**: Ensure models and associations are correctly implemented and tested.
49
+
50
+ ## Next Steps
51
+
52
+ ### Refine DSL for Static Workflows
53
+ - Enhance the DSL to create and update static workflows.
54
+ - Ensure it updates the database and exports workflows in JSON/YAML format.
55
+ - Implement rendering of the workflow structure as HTML.
56
+
57
+ ### Plan Dynamic Execution
58
+ - Determine the approach for executing workflows dynamically.
59
+ - Decide on using a DSL or a web application for this purpose.
60
+
61
+ This summary should help guide the development and focus on the core objectives and future directions.
62
+
1
63
 
2
64
  ## Schema for AI Agents
3
65
 
@@ -7,7 +69,16 @@
7
69
 
8
70
  ### Static Workflow Definition
9
71
 
72
+ Static workflow definition defines the structure of a workflow, including its sections, steps, attributes, and their relationships.
73
+
74
+ ![Static Workflow Definition](./images/sample-workflow.png)
75
+
76
+ ### Static Workflow Entities
77
+
10
78
  #### Table: workflows
79
+
80
+ This table stores the basic information about each workflow, including its unique identifier, name, and description.
81
+
11
82
  | Field | Type | Description |
12
83
  |-------------|--------|-------------------------------------|
13
84
  | id | string | Unique identifier for the workflow |
@@ -15,40 +86,60 @@
15
86
  | description | string | A brief description of the workflow |
16
87
 
17
88
  #### Table: sections
89
+ This table stores the sections that belong to a workflow. Each section has an order within its workflow.
90
+
18
91
  | Field | Type | Description |
19
92
  |-------------|---------|----------------------------------------|
20
93
  | id | string | Unique identifier for the section |
94
+ | workflow_id | string | Foreign key referencing workflows |
21
95
  | name | string | The name of the section |
22
96
  | description | string | A brief description of the section |
23
97
  | order | integer | The order of the section in the workflow|
24
- | workflow_id | string | Foreign key referencing workflows |
25
98
 
26
99
  #### Table: steps
100
+
101
+ This table stores the steps that belong to a section. Each step has an order within its section and an associated prompt.
102
+
103
+ Example workflows include "YouTube Video Script", "YouTube Title Creator" and "YouTube Transcription to Medium Article".
104
+
27
105
  | Field | Type | Description |
28
106
  |-------------|---------|-------------------------------------|
29
107
  | id | string | Unique identifier for the step |
108
+ | section_id | string | Foreign key referencing sections |
30
109
  | name | string | The name of the step |
110
+ | action | string | The action to be performed by the step, default ('gpt') |
31
111
  | description | string | A brief description of the step |
32
112
  | order | integer | The order of the step in the section|
33
- | section_id | string | Foreign key referencing sections |
34
113
  | prompt | string | The template string for the prompt |
35
114
 
36
115
  #### Table: attributes
116
+
117
+ This table stores the attributes associated with a workflow. Each attribute can be a simple value or an array.
118
+
119
+ Example attributes include "simple_title", "basic_factsheet" and "working_title".
120
+
37
121
  | Field | Type | Description |
38
122
  |-------------|---------|---------------------------------------------|
39
123
  | id | string | Unique identifier for the attribute |
124
+ | workflow_id | string | Foreign key referencing workflows |
40
125
  | name | string | The name of the attribute |
41
126
  | type | string | The type of the attribute (e.g., string) |
42
127
  | is_array | boolean | Indicates whether the attribute is an array |
43
- | workflow_id | string | Foreign key referencing workflows |
44
128
 
45
129
  #### Table: input_attributes
130
+
131
+ This table maps input attributes to steps. This becomes the input parameters for the AI agent.
132
+
46
133
  | Field | Type | Description |
47
134
  |-------------|---------|------------------------------------|
48
135
  | step_id | string | Foreign key referencing steps |
49
136
  | attribute_id| string | Foreign key referencing attributes |
137
+ | required | boolean | Indicates whether the attribute is required |
50
138
 
51
139
  #### Table: output_attributes
140
+
141
+ This table maps output attributes to steps. This becomes a result of the AI agent.
142
+
52
143
  | Field | Type | Description |
53
144
  |-------------|---------|------------------------------------|
54
145
  | step_id | string | Foreign key referencing steps |
@@ -56,20 +147,31 @@
56
147
 
57
148
  ### Dynamic Workflow Execution
58
149
 
150
+ Dynamic workflow execution captures the actual execution of a workflow, including the workflow runs, section runs, step runs, and attribute values.
151
+
152
+ ### Dynamic Workflow Entities
153
+
59
154
  #### Table: workflow_runs
155
+
156
+ This table stores instances of workflow executions.
157
+
60
158
  | Field | Type | Description |
61
159
  |-------------|--------|---------------------------------------|
62
160
  | id | string | Unique identifier for the workflow run|
63
161
  | workflow_id | string | Foreign key referencing workflows |
64
162
 
65
163
  #### Table: section_runs
164
+ This table stores instances of section executions within a workflow run.
165
+
66
166
  | Field | Type | Description |
67
167
  |-----------------|--------|----------------------------------------|
68
168
  | id | string | Unique identifier for the section run |
69
- | workflow_run_id | string | Foreign key referencing workflow_runs |
70
169
  | section_id | string | Foreign key referencing sections |
170
+ | workflow_run_id | string | Foreign key referencing workflow_runs |
71
171
 
72
172
  #### Table: step_runs
173
+ This table stores instances of step executions within a section run. Each step run can have multiple branches.
174
+
73
175
  | Field | Type | Description |
74
176
  |------------------|---------|---------------------------------------------------------------------|
75
177
  | id | string | Unique identifier for the step run |
@@ -78,9 +180,526 @@
78
180
  | branch_number | integer | Branch number to distinguish different instances (branches) of the same step |
79
181
 
80
182
  #### Table: attribute_values
183
+ This table stores the values of attributes during step executions.
184
+
81
185
  | Field | Type | Description |
82
186
  |---------------|--------|-----------------------------------------|
83
187
  | id | string | Unique identifier for the attribute value|
84
188
  | attribute_id | string | Foreign key referencing attributes |
85
189
  | step_run_id | string | Foreign key referencing step_runs |
86
190
  | value | text | The actual value of the attribute during the step execution |
191
+
192
+ ## Gemfile
193
+
194
+ ```ruby
195
+
196
+ # Gemfile
197
+
198
+ source 'https://rubygems.org'
199
+
200
+ gem 'sequel'
201
+ gem 'sqlite3'
202
+ ```
203
+
204
+ ## Database Setup
205
+
206
+
207
+ ```ruby
208
+ # db_setup.rb
209
+
210
+ require 'sequel'
211
+
212
+ DB = Sequel.sqlite('workflow.db') # Creates an SQLite database called workflow.db
213
+
214
+ # Create the tables for static workflow definition
215
+ DB.create_table :workflows do
216
+ primary_key :id
217
+ String :name, null: false
218
+ String :description
219
+ end
220
+
221
+ DB.create_table :sections do
222
+ primary_key :id
223
+ String :name, null: false
224
+ String :description
225
+ Integer :order
226
+ foreign_key :workflow_id, :workflows
227
+ end
228
+
229
+ DB.create_table :steps do
230
+ primary_key :id
231
+ String :name, null: false
232
+ String :description
233
+ Integer :order
234
+ foreign_key :section_id, :sections
235
+ String :prompt
236
+ end
237
+
238
+ DB.create_table :attributes do
239
+ primary_key :id
240
+ String :name, null: false
241
+ String :type
242
+ Boolean :is_array
243
+ foreign_key :workflow_id, :workflows
244
+ end
245
+
246
+ DB.create_table :input_attributes do
247
+ foreign_key :step_id, :steps
248
+ foreign_key :attribute_id, :attributes
249
+ end
250
+
251
+ DB.create_table :output_attributes do
252
+ foreign_key :step_id, :steps
253
+ foreign_key :attribute_id, :attributes
254
+ end
255
+
256
+ # Create the tables for dynamic workflow execution
257
+ DB.create_table :workflow_runs do
258
+ primary_key :id
259
+ foreign_key :workflow_id, :workflows
260
+ end
261
+
262
+ DB.create_table :section_runs do
263
+ primary_key :id
264
+ foreign_key :workflow_run_id, :workflow_runs
265
+ foreign_key :section_id, :sections
266
+ end
267
+
268
+ DB.create_table :step_runs do
269
+ primary_key :id
270
+ foreign_key :section_run_id, :section_runs
271
+ foreign_key :step_id, :steps
272
+ Integer :branch_number
273
+ end
274
+
275
+ DB.create_table :attribute_values do
276
+ primary_key :id
277
+ foreign_key :attribute_id, :attributes
278
+ foreign_key :step_run_id, :step_runs
279
+ String :value
280
+ end
281
+ ```
282
+
283
+ ## Models
284
+
285
+ ```ruby
286
+ # models.rb
287
+
288
+ require 'sequel'
289
+
290
+ DB = Sequel.sqlite('workflow.db') # Connect to the SQLite database
291
+
292
+ # Static Workflow Definition
293
+
294
+ class Workflow < Sequel::Model
295
+ one_to_many :sections
296
+ one_to_many :attributes
297
+ one_to_many :workflow_runs
298
+ end
299
+
300
+ class Section < Sequel::Model
301
+ many_to_one :workflow
302
+ one_to_many :steps
303
+ one_to_many :section_runs
304
+ end
305
+
306
+ class Step < Sequel::Model
307
+ many_to_one :section
308
+ one_to_many :input_attributes, class: :StepInputAttribute
309
+ one_to_many :output_attributes, class: :StepOutputAttribute
310
+ one_to_many :step_runs
311
+ end
312
+
313
+ class Attribute < Sequel::Model
314
+ many_to_one :workflow
315
+ one_to_many :input_attributes, class: :StepInputAttribute
316
+ one_to_many :output_attributes, class: :StepOutputAttribute
317
+ end
318
+
319
+ class StepInputAttribute < Sequel::Model
320
+ many_to_one :step
321
+ many_to_one :attribute
322
+ end
323
+
324
+ class StepOutputAttribute < Sequel::Model
325
+ many_to_one :step
326
+ many_to_one :attribute
327
+ end
328
+
329
+ # Dynamic Workflow Execution
330
+
331
+ class WorkflowRun < Sequel::Model
332
+ many_to_one :workflow
333
+ one_to_many :section_runs
334
+ end
335
+
336
+ class SectionRun < Sequel::Model
337
+ many_to_one :workflow_run
338
+ many_to_one :section
339
+ one_to_many :step_runs
340
+ end
341
+
342
+ class StepRun < Sequel::Model
343
+ many_to_one :section_run
344
+ many_to_one :step
345
+ one_to_many :attribute_values
346
+ end
347
+
348
+ class AttributeValue < Sequel::Model
349
+ many_to_one :attribute
350
+ many_to_one :step_run
351
+ end
352
+
353
+ ```
354
+
355
+ ## Usage via Models
356
+
357
+ ```ruby
358
+ # example_usage.rb
359
+
360
+ require_relative 'models'
361
+
362
+ # Create a new workflow
363
+ workflow = Workflow.create(name: "YouTube Video Script", description: "Workflow for creating a YouTube video script")
364
+
365
+ # Create sections for the workflow
366
+ section1 = Section.create(name: "Research", description: "Research phase", order: 1, workflow: workflow)
367
+ section2 = Section.create(name: "Script Writing", description: "Script writing phase", order: 2, workflow: workflow)
368
+
369
+ # Create steps for the sections
370
+ step1 = Step.create(name: "01-1-basic-meta", description: "Basic metadata for Fotor AI tool", order: 1, section: section1, prompt: "Generate 5 titles to get started")
371
+ step2 = Step.create(name: "01-2-basic-factsheet", description: "Detailed factsheet about Fotor AI Tool", order: 2, section: section1, prompt: "Generate detailed factsheet")
372
+
373
+ # Create attributes
374
+ attribute1 = Attribute.create(name: "simple_title", type: "string", is_array: false, workflow: workflow)
375
+ attribute2 = Attribute.create(name: "basic_factsheet", type: "string", is_array: false, workflow: workflow)
376
+
377
+ # Associate input and output attributes with steps
378
+ StepInputAttribute.create(step: step1, attribute: attribute1)
379
+ StepOutputAttribute.create(step: step1, attribute: attribute2)
380
+
381
+ # Create a workflow run
382
+ workflow_run = WorkflowRun.create(workflow: workflow)
383
+
384
+ # Create section runs
385
+ section_run1 = SectionRun.create(workflow_run: workflow_run, section: section1)
386
+ section_run2 = SectionRun.create(workflow_run: workflow_run, section: section2)
387
+
388
+ # Create step runs
389
+ step_run1 = StepRun.create(section_run: section_run1, step: step1, branch_number: 1)
390
+ step_run2 = StepRun.create(section_run: section_run1, step: step2, branch_number: 1)
391
+
392
+ # Add attribute values to step runs
393
+ AttributeValue.create(attribute: attribute1, step_run: step_run1, value: "Fotor AI tool")
394
+ AttributeValue.create(attribute: attribute2, step_run: step_run2, value: "Detailed factsheet about Fotor AI Tool")
395
+ ```
396
+
397
+ ## Exporting to JSON
398
+
399
+ ```ruby
400
+ # export_to_json.rb
401
+
402
+ require 'json'
403
+ require_relative 'models'
404
+
405
+ # Export all workflows to JSON files
406
+ Workflow.all.each do |workflow|
407
+ workflow_data = {
408
+ id: workflow.id,
409
+ name: workflow.name,
410
+ description: workflow.description,
411
+ sections: workflow.sections.map do |section|
412
+ {
413
+ id: section.id,
414
+ name: section.name,
415
+ description: section.description,
416
+ order: section.order,
417
+ steps: section.steps.map do |step|
418
+ {
419
+ id: step.id,
420
+ name: step.name,
421
+ description: step.description,
422
+ order: step.order,
423
+ prompt: step.prompt,
424
+ input_attributes: step.input_attributes.map { |ia| { id: ia.attribute.id, name: ia.attribute.name } },
425
+ output_attributes: step.output_attributes.map { |oa| { id: oa.attribute.id, name: oa.attribute.name } }
426
+ }
427
+ end
428
+ }
429
+ end,
430
+ attributes: workflow.attributes.map { |attr| { id: attr.id, name: attr.name, type: attr.type, is_array: attr.is_array } }
431
+ }
432
+
433
+ File.write("workflow_#{workflow.id}.json", JSON.pretty_generate(workflow_data))
434
+ end
435
+
436
+ # Export all workflow runs to JSON files
437
+ WorkflowRun.all.each do |workflow_run|
438
+ workflow_run_data = {
439
+ id: workflow_run.id,
440
+ workflow_id: workflow_run.workflow_id,
441
+ section_runs: workflow_run.section_runs.map do |section_run|
442
+ {
443
+ id: section_run.id,
444
+ section_id: section_run.section_id,
445
+ step_runs: section_run.step_runs.map do |step_run|
446
+ {
447
+ id: step_run.id,
448
+ step_id: step_run.step_id,
449
+ branch_number: step_run.branch_number,
450
+ attribute_values: step_run.attribute_values.map { |av| { id: av.attribute.id, name: av.attribute.name, value: av.value } }
451
+ }
452
+ end
453
+ }
454
+ end
455
+ }
456
+
457
+ File.write("workflow_run_#{workflow_run.id}.json", JSON.pretty_generate(workflow_run_data))
458
+ end
459
+ ```
460
+
461
+ ## Importing from JSON
462
+
463
+ ```ruby
464
+ # import_from_json.rb
465
+
466
+ require 'json'
467
+ require_relative 'models'
468
+
469
+ # Helper function to find or create an attribute
470
+ def find_or_create_attribute(attr_data, workflow)
471
+ Attribute.find_or_create(name: attr_data['name'], workflow: workflow) do |attribute|
472
+ attribute.type = attr_data['type']
473
+ attribute.is_array = attr_data['is_array']
474
+ end
475
+ end
476
+
477
+ # Restore workflows from JSON files
478
+ Dir.glob('workflow_*.json').each do |file|
479
+ data = JSON.parse(File.read(file))
480
+
481
+ workflow = Workflow.find_or_create(id: data['id']) do |w|
482
+ w.name = data['name']
483
+ w.description = data['description']
484
+ end
485
+
486
+ data['sections'].each do |section_data|
487
+ section = Section.find_or_create(id: section_data['id'], workflow: workflow) do |s|
488
+ s.name = section_data['name']
489
+ s.description = section_data['description']
490
+ s.order = section_data['order']
491
+ end
492
+
493
+ section_data['steps'].each do |step_data|
494
+ step = Step.find_or_create(id: step_data['id'], section: section) do |s|
495
+ s.name = step_data['name']
496
+ s.description = step_data['description']
497
+ s.order = step_data['order']
498
+ s.prompt = step_data['prompt']
499
+ end
500
+
501
+ step_data['input_attributes'].each do |attr_data|
502
+ attribute = find_or_create_attribute(attr_data, workflow)
503
+ StepInputAttribute.find_or_create(step: step, attribute: attribute)
504
+ end
505
+
506
+ step_data['output_attributes'].each do |attr_data|
507
+ attribute = find_or_create_attribute(attr_data, workflow)
508
+ StepOutputAttribute.find_or_create(step: step, attribute: attribute)
509
+ end
510
+ end
511
+ end
512
+
513
+ data['attributes'].each do |attr_data|
514
+ find_or_create_attribute(attr_data, workflow)
515
+ end
516
+ end
517
+
518
+ # Restore workflow runs from JSON files
519
+ Dir.glob('workflow_run_*.json').each do |file|
520
+ data = JSON.parse(File.read(file))
521
+
522
+ workflow_run = WorkflowRun.find_or_create(id: data['id'], workflow_id: data['workflow_id'])
523
+
524
+ data['section_runs'].each do |section_run_data|
525
+ section_run = SectionRun.find_or_create(id: section_run_data['id'], workflow_run: workflow_run, section_id: section_run_data['section_id'])
526
+
527
+ section_run_data['step_runs'].each do |step_run_data|
528
+ step_run = StepRun.find_or_create(id: step_run_data['id'], section_run: section_run, step_id: step_run_data['step_id'], branch_number: step_run_data['branch_number'])
529
+
530
+ step_run_data['attribute_values'].each do |attr_value_data|
531
+ attribute = Attribute.find(id: attr_value_data['id'])
532
+ AttributeValue.find_or_create(attribute: attribute, step_run: step_run) do |av|
533
+ av.value = attr_value_data['value']
534
+ end
535
+ end
536
+ end
537
+ end
538
+ end
539
+ ```
540
+
541
+ ## Sample Implementation of Workflow Builder (DSL)
542
+
543
+ ```ruby
544
+ require 'yaml'
545
+ require 'sequel'
546
+
547
+ # Assuming the database and models are already set up
548
+ DB = Sequel.sqlite('workflow.db')
549
+
550
+ # Models
551
+ class Workflow < Sequel::Model
552
+ one_to_many :sections
553
+ one_to_many :attributes
554
+ one_to_many :workflow_runs
555
+ end
556
+
557
+ class Section < Sequel::Model
558
+ many_to_one :workflow
559
+ one_to_many :steps
560
+ one_to_many :section_runs
561
+ end
562
+
563
+ class Step < Sequel::Model
564
+ many_to_one :section
565
+ one_to_many :input_attributes, class: :StepInputAttribute
566
+ one_to_many :output_attributes, class: :StepOutputAttribute
567
+ one_to_many :step_runs
568
+ end
569
+
570
+ class Attribute < Sequel::Model
571
+ many_to_one :workflow
572
+ one_to_many :input_attributes, class: :StepInputAttribute
573
+ one_to_many :output_attributes, class: :StepOutputAttribute
574
+ end
575
+
576
+ class StepInputAttribute < Sequel::Model
577
+ many_to_one :step
578
+ many_to_one :attribute
579
+ end
580
+
581
+ class StepOutputAttribute < Sequel::Model
582
+ many_to_one :step
583
+ many_to_one :attribute
584
+ end
585
+
586
+ # WorkflowBuilder
587
+ class WorkflowBuilder
588
+ def initialize(name:, description: nil)
589
+ @workflow = Workflow.new(name: name, description: description)
590
+ @current_section_order = 1
591
+ end
592
+
593
+ def description(desc)
594
+ @workflow.description = desc
595
+ end
596
+
597
+ def section(name:, &block)
598
+ @current_step_order = 1
599
+ @current_section = Section.new(name: name, order: @current_section_order)
600
+ @current_section_order += 1
601
+ instance_eval(&block) if block_given?
602
+ @workflow.add_section(@current_section)
603
+ end
604
+
605
+ def step(name:, &block)
606
+ step = Step.new(name: name, order: @current_step_order)
607
+ @current_step_order += 1
608
+ instance_eval(&block) if block_given?
609
+ @current_section.add_step(step)
610
+ end
611
+
612
+ def prompt(prompt)
613
+ @current_section.steps.last.prompt = prompt
614
+ end
615
+
616
+ def save
617
+ @workflow.save
618
+ end
619
+
620
+ def to_yaml
621
+ workflow_data = {
622
+ id: @workflow.id,
623
+ name: @workflow.name,
624
+ description: @workflow.description,
625
+ sections: @workflow.sections.map do |section|
626
+ {
627
+ id: section.id,
628
+ name: section.name,
629
+ description: section.description,
630
+ order: section.order,
631
+ steps: section.steps.map do |step|
632
+ {
633
+ id: step.id,
634
+ name: step.name,
635
+ description: step.description,
636
+ order: step.order,
637
+ prompt: step.prompt
638
+ }
639
+ end
640
+ }
641
+ end
642
+ }
643
+ workflow_data.to_yaml
644
+ end
645
+ end
646
+
647
+ ```
648
+
649
+ ## Usage via DSL
650
+
651
+ ```ruby
652
+ builder = WorkflowBuilder.new(name: 'YouTube Video Script')
653
+
654
+ builder.section(name: 'Research') do
655
+ step(name: '01-1-basic-meta') do
656
+ prompt 'Generate 5 titles to get started'
657
+ end
658
+
659
+ step(name: '01-2-basic-factsheet') do
660
+ prompt 'Generate detailed factsheet'
661
+ end
662
+ end
663
+
664
+ builder.section(name: 'Script Writing') do
665
+ step(name: '02-1-create-script') do
666
+ prompt 'Generate basic script'
667
+ end
668
+ end
669
+
670
+ puts builder.to_yaml
671
+
672
+ # Save to the database
673
+ builder.save
674
+
675
+
676
+ builder = WorkflowBuilder.new(name: 'YouTube Title Creator')
677
+
678
+ builder.section(name: 'Research') do
679
+ step(name: '01-1-working-title') do
680
+ prompt 'Come up with a simple working title for the YouTube video.'
681
+ end
682
+
683
+ step(name: '01-2-keyword-research') do
684
+ prompt 'Perform basic keyword research to identify relevant keywords.'
685
+ end
686
+
687
+ step(name: '01-3-topic-research') do
688
+ prompt 'Conduct basic topic research to gather information on the subject.'
689
+ end
690
+
691
+ step(name: '01-4-powerful-titles') do
692
+ prompt 'Ask GPT for 10 powerful titles based on the research.'
693
+ end
694
+
695
+ step(name: '01-5-title-rules') do
696
+ prompt 'Follow specific rules for title creation to ensure effectiveness.'
697
+ end
698
+ end
699
+
700
+ puts builder.to_yaml
701
+
702
+ # Save to the database
703
+ builder.save
704
+
705
+ ```
@@ -0,0 +1,177 @@
1
+ workflows:
2
+ - id: 1
3
+ name: "YouTube Video Script"
4
+ description: "Workflow for creating a YouTube video script"
5
+
6
+ sections:
7
+ - id: 1
8
+ name: "Research"
9
+ description: "Research phase of the workflow"
10
+ order: 1
11
+ workflow_id: 1
12
+ - id: 2
13
+ name: "Script Writing"
14
+ description: "Script writing phase of the workflow"
15
+ order: 2
16
+ workflow_id: 1
17
+
18
+ steps:
19
+ - id: 1
20
+ name: "01-1-basic-meta"
21
+ description: "Basic metadata for Fotor AI tool"
22
+ order: 1
23
+ section_id: 1
24
+ prompt: "Generate 5 titles to get started"
25
+ - id: 2
26
+ name: "01-2-basic-factsheet"
27
+ description: "Detailed factsheet about Fotor AI Tool"
28
+ order: 2
29
+ section_id: 1
30
+ prompt: "Generate detailed factsheet"
31
+ - id: 3
32
+ name: "01-3-video-type"
33
+ description: "Identify video types"
34
+ order: 3
35
+ section_id: 1
36
+ prompt: "Identify video types based on basic factsheet"
37
+ - id: 4
38
+ name: "01-4-expanded-factsheet"
39
+ description: "Expanded factsheet about Fotor AI Tool"
40
+ order: 4
41
+ section_id: 1
42
+ prompt: "Generate expanded factsheet"
43
+ - id: 5
44
+ name: "01-5-expanded-meta"
45
+ description: "Expanded metadata for Fotor AI Tool"
46
+ order: 5
47
+ section_id: 1
48
+ prompt: "Generate engaging titles, keywords, and topics"
49
+ - id: 6
50
+ name: "02-1-create-script"
51
+ description: "Create basic script"
52
+ order: 1
53
+ section_id: 2
54
+ prompt: "Generate basic script"
55
+ - id: 7
56
+ name: "02-2-clean-transcript"
57
+ description: "Clean and revise transcript"
58
+ order: 2
59
+ section_id: 2
60
+ prompt: "Generate basic transcript"
61
+ - id: 8
62
+ name: "02-3-transcript-factchecked"
63
+ description: "Fact-check and revise transcript"
64
+ order: 3
65
+ section_id: 2
66
+ prompt: "Generate fact-checked transcript"
67
+
68
+ attributes:
69
+ - id: 1
70
+ name: "simple_title"
71
+ type: "string"
72
+ is_array: false
73
+ workflow_id: 1
74
+ - id: 2
75
+ name: "basic_factsheet"
76
+ type: "string"
77
+ is_array: false
78
+ workflow_id: 1
79
+ - id: 3
80
+ name: "focus_video_type"
81
+ type: "string"
82
+ is_array: false
83
+ workflow_id: 1
84
+ - id: 4
85
+ name: "expanded_factsheet"
86
+ type: "string"
87
+ is_array: false
88
+ workflow_id: 1
89
+ - id: 5
90
+ name: "video_types"
91
+ type: "string"
92
+ is_array: true
93
+ workflow_id: 1
94
+ - id: 6
95
+ name: "engaging_titles"
96
+ type: "string"
97
+ is_array: true
98
+ workflow_id: 1
99
+ - id: 7
100
+ name: "keywords"
101
+ type: "string"
102
+ is_array: true
103
+ workflow_id: 1
104
+ - id: 8
105
+ name: "topics"
106
+ type: "string"
107
+ is_array: true
108
+ workflow_id: 1
109
+ - id: 9
110
+ name: "basic_script"
111
+ type: "string"
112
+ is_array: false
113
+ workflow_id: 1
114
+ - id: 10
115
+ name: "basic_transcript"
116
+ type: "string"
117
+ is_array: false
118
+ workflow_id: 1
119
+ - id: 11
120
+ name: "transcript_qa"
121
+ type: "string"
122
+ is_array: false
123
+ workflow_id: 1
124
+
125
+ input_attributes:
126
+ - step_id: 1
127
+ attribute_id: 1
128
+ - step_id: 2
129
+ attribute_id: 1
130
+ - step_id: 3
131
+ attribute_id: 1
132
+ - step_id: 3
133
+ attribute_id: 2
134
+ - step_id: 4
135
+ attribute_id: 1
136
+ - step_id: 4
137
+ attribute_id: 2
138
+ - step_id: 4
139
+ attribute_id: 3
140
+ - step_id: 5
141
+ attribute_id: 1
142
+ - step_id: 5
143
+ attribute_id: 3
144
+ - step_id: 5
145
+ attribute_id: 4
146
+ - step_id: 6
147
+ attribute_id: 1
148
+ - step_id: 6
149
+ attribute_id: 3
150
+ - step_id: 6
151
+ attribute_id: 4
152
+ - step_id: 7
153
+ attribute_id: 9
154
+ - step_id: 8
155
+ attribute_id: 10
156
+
157
+ output_attributes:
158
+ - step_id: 1
159
+ attribute_id: 6
160
+ - step_id: 2
161
+ attribute_id: 2
162
+ - step_id: 3
163
+ attribute_id: 5
164
+ - step_id: 4
165
+ attribute_id: 4
166
+ - step_id: 5
167
+ attribute_id: 6
168
+ - step_id: 5
169
+ attribute_id: 7
170
+ - step_id: 5
171
+ attribute_id: 8
172
+ - step_id: 6
173
+ attribute_id: 9
174
+ - step_id: 7
175
+ attribute_id: 10
176
+ - step_id: 8
177
+ attribute_id: 11
@@ -0,0 +1,159 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Usage
4
+ # DB = Sequel.sqlite # In-memory database
5
+
6
+ # schema_creator = Ad::AgentArchitecture::Database::CreateSchema.new(DB)
7
+ # schema_creator.execute
8
+ module Ad
9
+ module AgentArchitecture
10
+ module Database
11
+ # Create the database schema
12
+ class CreateSchema
13
+ attr_reader :db
14
+
15
+ def initialize(db)
16
+ @db = db
17
+ end
18
+
19
+ def execute
20
+ create_tables
21
+ define_models
22
+ end
23
+
24
+ private
25
+
26
+ def create_tables
27
+ db.create_table :workflows do
28
+ primary_key :id
29
+ String :name, null: false
30
+ String :description
31
+ end
32
+
33
+ db.create_table :sections do
34
+ primary_key :id
35
+ foreign_key :workflow_id, :workflows
36
+ String :name, null: false
37
+ String :description
38
+ Integer :order
39
+ end
40
+
41
+ db.create_table :steps do
42
+ primary_key :id
43
+ foreign_key :section_id, :sections
44
+ String :name, null: false
45
+ String :action, default: 'gpt'
46
+ String :description
47
+ Integer :order
48
+ String :prompt
49
+ end
50
+
51
+ db.create_table :attributes do
52
+ primary_key :id
53
+ foreign_key :workflow_id, :workflows
54
+ String :name, null: false
55
+ String :type
56
+ Boolean :is_array
57
+ end
58
+
59
+ db.create_table :input_attributes do
60
+ primary_key :id
61
+ foreign_key :step_id, :steps
62
+ foreign_key :attribute_id, :attributes
63
+ Boolean :required
64
+ end
65
+
66
+ db.create_table :output_attributes do
67
+ primary_key :id
68
+ foreign_key :step_id, :steps
69
+ foreign_key :attribute_id, :attributes
70
+ end
71
+
72
+ db.create_table :workflow_runs do
73
+ primary_key :id
74
+ foreign_key :workflow_id, :workflows
75
+ end
76
+
77
+ db.create_table :section_runs do
78
+ primary_key :id
79
+ foreign_key :workflow_run_id, :workflow_runs
80
+ foreign_key :section_id, :sections
81
+ end
82
+
83
+ db.create_table :step_runs do
84
+ primary_key :id
85
+ foreign_key :section_run_id, :section_runs
86
+ foreign_key :step_id, :steps
87
+ Integer :branch_number
88
+ end
89
+
90
+ db.create_table :attribute_values do
91
+ primary_key :id
92
+ foreign_key :attribute_id, :attributes
93
+ foreign_key :step_run_id, :step_runs
94
+ String :value
95
+ end
96
+ end
97
+
98
+ def define_models
99
+ Class.new(Sequel::Model(:workflows)) do
100
+ one_to_many :sections
101
+ one_to_many :attributes
102
+ one_to_many :workflow_runs
103
+ end
104
+
105
+ Class.new(Sequel::Model(:sections)) do
106
+ many_to_one :workflow
107
+ one_to_many :steps
108
+ one_to_many :section_runs
109
+ end
110
+
111
+ Class.new(Sequel::Model(:steps)) do
112
+ many_to_one :section
113
+ one_to_many :input_attributes, class: :InputAttribute
114
+ one_to_many :output_attributes, class: :OutputAttribute
115
+ one_to_many :step_runs
116
+ end
117
+
118
+ Class.new(Sequel::Model(:attributes)) do
119
+ many_to_one :workflow
120
+ one_to_many :input_attributes, class: :InputAttribute
121
+ one_to_many :output_attributes, class: :OutputAttribute
122
+ end
123
+
124
+ Class.new(Sequel::Model(:input_attributes)) do
125
+ many_to_one :step
126
+ many_to_one :attribute
127
+ end
128
+
129
+ Class.new(Sequel::Model(:output_attributes)) do
130
+ many_to_one :step
131
+ many_to_one :attribute
132
+ end
133
+
134
+ Class.new(Sequel::Model(:workflow_runs)) do
135
+ many_to_one :workflow
136
+ one_to_many :section_runs
137
+ end
138
+
139
+ Class.new(Sequel::Model(:section_runs)) do
140
+ many_to_one :workflow_run
141
+ many_to_one :section
142
+ one_to_many :step_runs
143
+ end
144
+
145
+ Class.new(Sequel::Model(:step_runs)) do
146
+ many_to_one :section_run
147
+ many_to_one :step
148
+ one_to_many :attribute_values
149
+ end
150
+
151
+ Class.new(Sequel::Model(:attribute_values)) do
152
+ many_to_one :attribute
153
+ many_to_one :step_run
154
+ end
155
+ end
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,76 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'sequel'
4
+
5
+ module Ad
6
+ module AgentArchitecture
7
+ module Database
8
+ # Workflow model represents a workflow entity in the database.
9
+ class Workflow < Sequel::Model
10
+ one_to_many :sections, class: 'Ad::AgentArchitecture::Database::Section'
11
+ one_to_many :attributes, class: 'Ad::AgentArchitecture::Database::Attribute'
12
+ one_to_many :workflow_runs, class: 'Ad::AgentArchitecture::Database::WorkflowRun'
13
+ end
14
+
15
+ # Section model represents a section entity in the database.
16
+ class Section < Sequel::Model
17
+ many_to_one :workflow, class: 'Ad::AgentArchitecture::Database::Workflow'
18
+ one_to_many :steps, class: 'Ad::AgentArchitecture::Database::Step'
19
+ one_to_many :section_runs, class: 'Ad::AgentArchitecture::Database::SectionRun'
20
+ end
21
+
22
+ # Step model represents a step entity in the database.
23
+ class Step < Sequel::Model
24
+ many_to_one :section, class: 'Ad::AgentArchitecture::Database::Section'
25
+ one_to_many :input_attributes, class: 'Ad::AgentArchitecture::Database::InputAttribute'
26
+ one_to_many :output_attributes, class: 'Ad::AgentArchitecture::Database::OutputAttribute'
27
+ one_to_many :step_runs, class: 'Ad::AgentArchitecture::Database::StepRun'
28
+ end
29
+
30
+ # Attribute model represents an attribute entity in the database.
31
+ class Attribute < Sequel::Model
32
+ many_to_one :workflow, class: 'Ad::AgentArchitecture::Database::Workflow'
33
+ one_to_many :input_attributes, class: 'Ad::AgentArchitecture::Database::InputAttribute'
34
+ one_to_many :output_attributes, class: 'Ad::AgentArchitecture::Database::OutputAttribute'
35
+ end
36
+
37
+ # InputAttribute model represents an input attribute entity in the database.
38
+ class InputAttribute < Sequel::Model
39
+ many_to_one :step, class: 'Ad::AgentArchitecture::Database::Step'
40
+ many_to_one :attribute, class: 'Ad::AgentArchitecture::Database::Attribute'
41
+ end
42
+
43
+ # OutputAttribute model represents an output attribute entity in the database.
44
+ class OutputAttribute < Sequel::Model
45
+ many_to_one :step, class: 'Ad::AgentArchitecture::Database::Step'
46
+ many_to_one :attribute, class: 'Ad::AgentArchitecture::Database::Attribute'
47
+ end
48
+
49
+ # WorkflowRun model represents a workflow run entity in the database.
50
+ class WorkflowRun < Sequel::Model
51
+ many_to_one :workflow, class: 'Ad::AgentArchitecture::Database::Workflow'
52
+ one_to_many :section_runs, class: 'Ad::AgentArchitecture::Database::SectionRun'
53
+ end
54
+
55
+ # SectionRun model represents a section run entity in the database.
56
+ class SectionRun < Sequel::Model
57
+ many_to_one :workflow_run, class: 'Ad::AgentArchitecture::Database::WorkflowRun'
58
+ many_to_one :section, class: 'Ad::AgentArchitecture::Database::Section'
59
+ one_to_many :step_runs, class: 'Ad::AgentArchitecture::Database::StepRun'
60
+ end
61
+
62
+ # StepRun model represents a step run entity in the database.
63
+ class StepRun < Sequel::Model
64
+ many_to_one :section_run, class: 'Ad::AgentArchitecture::Database::SectionRun'
65
+ many_to_one :step, class: 'Ad::AgentArchitecture::Database::Step'
66
+ one_to_many :attribute_values, class: 'Ad::AgentArchitecture::Database::AttributeValue'
67
+ end
68
+
69
+ # AttributeValue model represents an attribute value entity in the database.
70
+ class AttributeValue < Sequel::Model
71
+ many_to_one :attribute, class: 'Ad::AgentArchitecture::Database::Attribute'
72
+ many_to_one :step_run, class: 'Ad::AgentArchitecture::Database::StepRun'
73
+ end
74
+ end
75
+ end
76
+ end
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Ad
4
4
  module AgentArchitecture
5
- VERSION = '0.0.4'
5
+ VERSION = '0.0.6'
6
6
  end
7
7
  end
@@ -1,6 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'sequel'
4
+ require 'sqlite3'
5
+
3
6
  require 'ad/agent_architecture/version'
7
+ require 'ad/agent_architecture/db/create_schema'
8
+
9
+ DB = Sequel.sqlite
10
+
11
+ Ad::AgentArchitecture::Database::CreateSchema.new(DB).execute
12
+
13
+ require 'ad/agent_architecture/db/models'
4
14
 
5
15
  module Ad
6
16
  module AgentArchitecture
data/package-lock.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "ad-agent_architecture",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "lockfileVersion": 3,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "ad-agent_architecture",
9
- "version": "0.0.4",
9
+ "version": "0.0.6",
10
10
  "devDependencies": {
11
11
  "@klueless-js/semantic-release-rubygem": "github:klueless-js/semantic-release-rubygem",
12
12
  "@semantic-release/changelog": "^6.0.3",
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ad-agent_architecture",
3
- "version": "0.0.4",
3
+ "version": "0.0.6",
4
4
  "description": "Architecture/Schema for AI Agents",
5
5
  "scripts": {
6
6
  "release": "semantic-release"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ad-agent_architecture
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.6
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Cruwys
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-06-26 00:00:00.000000000 Z
11
+ date: 2024-06-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: k_log
@@ -24,6 +24,34 @@ dependencies:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: sequel
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '2'
27
55
  description: " Architecture/Schema for AI Agents\n"
28
56
  email:
29
57
  - david@ideasmen.com.au
@@ -48,8 +76,12 @@ files:
48
76
  - bin/console
49
77
  - bin/setup
50
78
  - docs/erd.svg
79
+ - docs/images/sample-workflow.png
51
80
  - docs/requirements.md
81
+ - docs/structure-youtube-script.yaml
52
82
  - lib/ad/agent_architecture.rb
83
+ - lib/ad/agent_architecture/db/create_schema.rb
84
+ - lib/ad/agent_architecture/db/models.rb
53
85
  - lib/ad/agent_architecture/version.rb
54
86
  - package-lock.json
55
87
  - package.json