ad-agent_architecture 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ddf07e6fca1337e7800b3c85b1c48f44524aa14660827eb81ffe541bce122c49
4
- data.tar.gz: be8299cec2e18b52eebeb1af83fc243b172685b490cd581241d1d471b7de68ee
3
+ metadata.gz: 48e72bffc8e25721cc39304860dac54bdde2cbe3828fd9bf39ea5a93d2ae40d8
4
+ data.tar.gz: 6579e5af918b96e8eb9960ea2e672cf1b2315fad054f794ca5789cec1779624c
5
5
  SHA512:
6
- metadata.gz: 92afeb1cb3bc9315da02dc33dbe280fa6ab1c43404886852c5e4b542345e00f8f0b48b504a5f45dce205dde146e6dc3f7cebc35b8d2cee777aee6f81ed7a6c9f
7
- data.tar.gz: 0167d391cb38acb70bd39dd0e454c21570531b86bb411b9b473869437f70a33374992f266c7cd10daa8f9ffd17697ffbd5784bb46056ffb4c71d3e34966926a2
6
+ metadata.gz: a3ac5432296309961a50273fbb71cdf0fd681ab5d1a40cf7054a9b1a044001d1262d0eefc91f08f579a887294104dc3e22e2fbe3717e3c32b98fe0eae7ff54de
7
+ data.tar.gz: 93c048683f119fa32427bf57422bf1217bb689870162cb733a3eda10bdba6d92c0f8b7606e3550630b747ad2000a7bd48ec7c83beaa4ab2c67593a67c7b5b5ef
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,10 @@
1
+ ## [0.0.4](https://github.com/appydave/ad-agent_architecture/compare/v0.0.3...v0.0.4) (2024-06-26)
2
+
3
+
4
+ ### Bug Fixes
5
+
6
+ * update schema ([dd2d6fb](https://github.com/appydave/ad-agent_architecture/commit/dd2d6fbd1eb477da5e44f3d5417aa05ec291fb25))
7
+
1
8
  ## [0.0.3](https://github.com/appydave/ad-agent_architecture/compare/v0.0.2...v0.0.3) (2024-06-26)
2
9
 
3
10
 
Binary file
data/docs/requirements.md CHANGED
@@ -7,7 +7,16 @@
7
7
 
8
8
  ### Static Workflow Definition
9
9
 
10
+ Static workflow definition defines the structure of a workflow, including its sections, steps, attributes, and their relationships.
11
+
12
+ ![Static Workflow Definition](./images/sample-workflow.png)
13
+
14
+ ### Static Workflow Entities
15
+
10
16
  #### Table: workflows
17
+
18
+ This table stores the basic information about each workflow, including its unique identifier, name, and description.
19
+
11
20
  | Field | Type | Description |
12
21
  |-------------|--------|-------------------------------------|
13
22
  | id | string | Unique identifier for the workflow |
@@ -15,40 +24,60 @@
15
24
  | description | string | A brief description of the workflow |
16
25
 
17
26
  #### Table: sections
27
+ This table stores the sections that belong to a workflow. Each section has an order within its workflow.
28
+
18
29
  | Field | Type | Description |
19
30
  |-------------|---------|----------------------------------------|
20
31
  | id | string | Unique identifier for the section |
32
+ | workflow_id | string | Foreign key referencing workflows |
21
33
  | name | string | The name of the section |
22
34
  | description | string | A brief description of the section |
23
35
  | order | integer | The order of the section in the workflow|
24
- | workflow_id | string | Foreign key referencing workflows |
25
36
 
26
37
  #### Table: steps
38
+
39
+ This table stores the steps that belong to a section. Each step has an order within its section and an associated prompt.
40
+
41
+ Example workflows include "YouTube Video Script", "YouTube Title Creator" and "YouTube Transcription to Medium Article".
42
+
27
43
  | Field | Type | Description |
28
44
  |-------------|---------|-------------------------------------|
29
45
  | id | string | Unique identifier for the step |
46
+ | section_id | string | Foreign key referencing sections |
30
47
  | name | string | The name of the step |
48
+ | action | string | The action to be performed by the step, default ('gpt') |
31
49
  | description | string | A brief description of the step |
32
50
  | order | integer | The order of the step in the section|
33
- | section_id | string | Foreign key referencing sections |
34
51
  | prompt | string | The template string for the prompt |
35
52
 
36
53
  #### Table: attributes
54
+
55
+ This table stores the attributes associated with a workflow. Each attribute can be a simple value or an array.
56
+
57
+ Example attributes include "simple_title", "basic_factsheet" and "working_title".
58
+
37
59
  | Field | Type | Description |
38
60
  |-------------|---------|---------------------------------------------|
39
61
  | id | string | Unique identifier for the attribute |
62
+ | workflow_id | string | Foreign key referencing workflows |
40
63
  | name | string | The name of the attribute |
41
64
  | type | string | The type of the attribute (e.g., string) |
42
65
  | is_array | boolean | Indicates whether the attribute is an array |
43
- | workflow_id | string | Foreign key referencing workflows |
44
66
 
45
67
  #### Table: input_attributes
68
+
69
+ This table maps input attributes to steps. This becomes the input parameters for the AI agent.
70
+
46
71
  | Field | Type | Description |
47
72
  |-------------|---------|------------------------------------|
48
73
  | step_id | string | Foreign key referencing steps |
49
74
  | attribute_id| string | Foreign key referencing attributes |
75
+ | required | boolean | Indicates whether the attribute is required |
50
76
 
51
77
  #### Table: output_attributes
78
+
79
+ This table maps output attributes to steps. This becomes a result of the AI agent.
80
+
52
81
  | Field | Type | Description |
53
82
  |-------------|---------|------------------------------------|
54
83
  | step_id | string | Foreign key referencing steps |
@@ -56,20 +85,31 @@
56
85
 
57
86
  ### Dynamic Workflow Execution
58
87
 
88
+ Dynamic workflow execution captures the actual execution of a workflow, including the workflow runs, section runs, step runs, and attribute values.
89
+
90
+ ### Dynamic Workflow Entities
91
+
59
92
  #### Table: workflow_runs
93
+
94
+ This table stores instances of workflow executions.
95
+
60
96
  | Field | Type | Description |
61
97
  |-------------|--------|---------------------------------------|
62
98
  | id | string | Unique identifier for the workflow run|
63
99
  | workflow_id | string | Foreign key referencing workflows |
64
100
 
65
101
  #### Table: section_runs
102
+ This table stores instances of section executions within a workflow run.
103
+
66
104
  | Field | Type | Description |
67
105
  |-----------------|--------|----------------------------------------|
68
106
  | id | string | Unique identifier for the section run |
69
- | workflow_run_id | string | Foreign key referencing workflow_runs |
70
107
  | section_id | string | Foreign key referencing sections |
108
+ | workflow_run_id | string | Foreign key referencing workflow_runs |
71
109
 
72
110
  #### Table: step_runs
111
+ This table stores instances of step executions within a section run. Each step run can have multiple branches.
112
+
73
113
  | Field | Type | Description |
74
114
  |------------------|---------|---------------------------------------------------------------------|
75
115
  | id | string | Unique identifier for the step run |
@@ -78,9 +118,526 @@
78
118
  | branch_number | integer | Branch number to distinguish different instances (branches) of the same step |
79
119
 
80
120
  #### Table: attribute_values
121
+ This table stores the values of attributes during step executions.
122
+
81
123
  | Field | Type | Description |
82
124
  |---------------|--------|-----------------------------------------|
83
125
  | id | string | Unique identifier for the attribute value|
84
126
  | attribute_id | string | Foreign key referencing attributes |
85
127
  | step_run_id | string | Foreign key referencing step_runs |
86
128
  | value | text | The actual value of the attribute during the step execution |
129
+
130
+ ## Gemfile
131
+
132
+ ```ruby
133
+
134
+ # Gemfile
135
+
136
+ source 'https://rubygems.org'
137
+
138
+ gem 'sequel'
139
+ gem 'sqlite3'
140
+ ```
141
+
142
+ ## Database Setup
143
+
144
+
145
+ ```ruby
146
+ # db_setup.rb
147
+
148
+ require 'sequel'
149
+
150
+ DB = Sequel.sqlite('workflow.db') # Creates an SQLite database called workflow.db
151
+
152
+ # Create the tables for static workflow definition
153
+ DB.create_table :workflows do
154
+ primary_key :id
155
+ String :name, null: false
156
+ String :description
157
+ end
158
+
159
+ DB.create_table :sections do
160
+ primary_key :id
161
+ String :name, null: false
162
+ String :description
163
+ Integer :order
164
+ foreign_key :workflow_id, :workflows
165
+ end
166
+
167
+ DB.create_table :steps do
168
+ primary_key :id
169
+ String :name, null: false
170
+ String :description
171
+ Integer :order
172
+ foreign_key :section_id, :sections
173
+ String :prompt
174
+ end
175
+
176
+ DB.create_table :attributes do
177
+ primary_key :id
178
+ String :name, null: false
179
+ String :type
180
+ Boolean :is_array
181
+ foreign_key :workflow_id, :workflows
182
+ end
183
+
184
+ DB.create_table :input_attributes do
185
+ foreign_key :step_id, :steps
186
+ foreign_key :attribute_id, :attributes
187
+ end
188
+
189
+ DB.create_table :output_attributes do
190
+ foreign_key :step_id, :steps
191
+ foreign_key :attribute_id, :attributes
192
+ end
193
+
194
+ # Create the tables for dynamic workflow execution
195
+ DB.create_table :workflow_runs do
196
+ primary_key :id
197
+ foreign_key :workflow_id, :workflows
198
+ end
199
+
200
+ DB.create_table :section_runs do
201
+ primary_key :id
202
+ foreign_key :workflow_run_id, :workflow_runs
203
+ foreign_key :section_id, :sections
204
+ end
205
+
206
+ DB.create_table :step_runs do
207
+ primary_key :id
208
+ foreign_key :section_run_id, :section_runs
209
+ foreign_key :step_id, :steps
210
+ Integer :branch_number
211
+ end
212
+
213
+ DB.create_table :attribute_values do
214
+ primary_key :id
215
+ foreign_key :attribute_id, :attributes
216
+ foreign_key :step_run_id, :step_runs
217
+ String :value
218
+ end
219
+ ```
220
+
221
+ ## Models
222
+
223
+ ```ruby
224
+ # models.rb
225
+
226
+ require 'sequel'
227
+
228
+ DB = Sequel.sqlite('workflow.db') # Connect to the SQLite database
229
+
230
+ # Static Workflow Definition
231
+
232
+ class Workflow < Sequel::Model
233
+ one_to_many :sections
234
+ one_to_many :attributes
235
+ one_to_many :workflow_runs
236
+ end
237
+
238
+ class Section < Sequel::Model
239
+ many_to_one :workflow
240
+ one_to_many :steps
241
+ one_to_many :section_runs
242
+ end
243
+
244
+ class Step < Sequel::Model
245
+ many_to_one :section
246
+ one_to_many :input_attributes, class: :StepInputAttribute
247
+ one_to_many :output_attributes, class: :StepOutputAttribute
248
+ one_to_many :step_runs
249
+ end
250
+
251
+ class Attribute < Sequel::Model
252
+ many_to_one :workflow
253
+ one_to_many :input_attributes, class: :StepInputAttribute
254
+ one_to_many :output_attributes, class: :StepOutputAttribute
255
+ end
256
+
257
+ class StepInputAttribute < Sequel::Model
258
+ many_to_one :step
259
+ many_to_one :attribute
260
+ end
261
+
262
+ class StepOutputAttribute < Sequel::Model
263
+ many_to_one :step
264
+ many_to_one :attribute
265
+ end
266
+
267
+ # Dynamic Workflow Execution
268
+
269
+ class WorkflowRun < Sequel::Model
270
+ many_to_one :workflow
271
+ one_to_many :section_runs
272
+ end
273
+
274
+ class SectionRun < Sequel::Model
275
+ many_to_one :workflow_run
276
+ many_to_one :section
277
+ one_to_many :step_runs
278
+ end
279
+
280
+ class StepRun < Sequel::Model
281
+ many_to_one :section_run
282
+ many_to_one :step
283
+ one_to_many :attribute_values
284
+ end
285
+
286
+ class AttributeValue < Sequel::Model
287
+ many_to_one :attribute
288
+ many_to_one :step_run
289
+ end
290
+
291
+ ```
292
+
293
+ ## Usage via Models
294
+
295
+ ```ruby
296
+ # example_usage.rb
297
+
298
+ require_relative 'models'
299
+
300
+ # Create a new workflow
301
+ workflow = Workflow.create(name: "YouTube Video Script", description: "Workflow for creating a YouTube video script")
302
+
303
+ # Create sections for the workflow
304
+ section1 = Section.create(name: "Research", description: "Research phase", order: 1, workflow: workflow)
305
+ section2 = Section.create(name: "Script Writing", description: "Script writing phase", order: 2, workflow: workflow)
306
+
307
+ # Create steps for the sections
308
+ 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")
309
+ step2 = Step.create(name: "01-2-basic-factsheet", description: "Detailed factsheet about Fotor AI Tool", order: 2, section: section1, prompt: "Generate detailed factsheet")
310
+
311
+ # Create attributes
312
+ attribute1 = Attribute.create(name: "simple_title", type: "string", is_array: false, workflow: workflow)
313
+ attribute2 = Attribute.create(name: "basic_factsheet", type: "string", is_array: false, workflow: workflow)
314
+
315
+ # Associate input and output attributes with steps
316
+ StepInputAttribute.create(step: step1, attribute: attribute1)
317
+ StepOutputAttribute.create(step: step1, attribute: attribute2)
318
+
319
+ # Create a workflow run
320
+ workflow_run = WorkflowRun.create(workflow: workflow)
321
+
322
+ # Create section runs
323
+ section_run1 = SectionRun.create(workflow_run: workflow_run, section: section1)
324
+ section_run2 = SectionRun.create(workflow_run: workflow_run, section: section2)
325
+
326
+ # Create step runs
327
+ step_run1 = StepRun.create(section_run: section_run1, step: step1, branch_number: 1)
328
+ step_run2 = StepRun.create(section_run: section_run1, step: step2, branch_number: 1)
329
+
330
+ # Add attribute values to step runs
331
+ AttributeValue.create(attribute: attribute1, step_run: step_run1, value: "Fotor AI tool")
332
+ AttributeValue.create(attribute: attribute2, step_run: step_run2, value: "Detailed factsheet about Fotor AI Tool")
333
+ ```
334
+
335
+ ## Exporting to JSON
336
+
337
+ ```ruby
338
+ # export_to_json.rb
339
+
340
+ require 'json'
341
+ require_relative 'models'
342
+
343
+ # Export all workflows to JSON files
344
+ Workflow.all.each do |workflow|
345
+ workflow_data = {
346
+ id: workflow.id,
347
+ name: workflow.name,
348
+ description: workflow.description,
349
+ sections: workflow.sections.map do |section|
350
+ {
351
+ id: section.id,
352
+ name: section.name,
353
+ description: section.description,
354
+ order: section.order,
355
+ steps: section.steps.map do |step|
356
+ {
357
+ id: step.id,
358
+ name: step.name,
359
+ description: step.description,
360
+ order: step.order,
361
+ prompt: step.prompt,
362
+ input_attributes: step.input_attributes.map { |ia| { id: ia.attribute.id, name: ia.attribute.name } },
363
+ output_attributes: step.output_attributes.map { |oa| { id: oa.attribute.id, name: oa.attribute.name } }
364
+ }
365
+ end
366
+ }
367
+ end,
368
+ attributes: workflow.attributes.map { |attr| { id: attr.id, name: attr.name, type: attr.type, is_array: attr.is_array } }
369
+ }
370
+
371
+ File.write("workflow_#{workflow.id}.json", JSON.pretty_generate(workflow_data))
372
+ end
373
+
374
+ # Export all workflow runs to JSON files
375
+ WorkflowRun.all.each do |workflow_run|
376
+ workflow_run_data = {
377
+ id: workflow_run.id,
378
+ workflow_id: workflow_run.workflow_id,
379
+ section_runs: workflow_run.section_runs.map do |section_run|
380
+ {
381
+ id: section_run.id,
382
+ section_id: section_run.section_id,
383
+ step_runs: section_run.step_runs.map do |step_run|
384
+ {
385
+ id: step_run.id,
386
+ step_id: step_run.step_id,
387
+ branch_number: step_run.branch_number,
388
+ attribute_values: step_run.attribute_values.map { |av| { id: av.attribute.id, name: av.attribute.name, value: av.value } }
389
+ }
390
+ end
391
+ }
392
+ end
393
+ }
394
+
395
+ File.write("workflow_run_#{workflow_run.id}.json", JSON.pretty_generate(workflow_run_data))
396
+ end
397
+ ```
398
+
399
+ ## Importing from JSON
400
+
401
+ ```ruby
402
+ # import_from_json.rb
403
+
404
+ require 'json'
405
+ require_relative 'models'
406
+
407
+ # Helper function to find or create an attribute
408
+ def find_or_create_attribute(attr_data, workflow)
409
+ Attribute.find_or_create(name: attr_data['name'], workflow: workflow) do |attribute|
410
+ attribute.type = attr_data['type']
411
+ attribute.is_array = attr_data['is_array']
412
+ end
413
+ end
414
+
415
+ # Restore workflows from JSON files
416
+ Dir.glob('workflow_*.json').each do |file|
417
+ data = JSON.parse(File.read(file))
418
+
419
+ workflow = Workflow.find_or_create(id: data['id']) do |w|
420
+ w.name = data['name']
421
+ w.description = data['description']
422
+ end
423
+
424
+ data['sections'].each do |section_data|
425
+ section = Section.find_or_create(id: section_data['id'], workflow: workflow) do |s|
426
+ s.name = section_data['name']
427
+ s.description = section_data['description']
428
+ s.order = section_data['order']
429
+ end
430
+
431
+ section_data['steps'].each do |step_data|
432
+ step = Step.find_or_create(id: step_data['id'], section: section) do |s|
433
+ s.name = step_data['name']
434
+ s.description = step_data['description']
435
+ s.order = step_data['order']
436
+ s.prompt = step_data['prompt']
437
+ end
438
+
439
+ step_data['input_attributes'].each do |attr_data|
440
+ attribute = find_or_create_attribute(attr_data, workflow)
441
+ StepInputAttribute.find_or_create(step: step, attribute: attribute)
442
+ end
443
+
444
+ step_data['output_attributes'].each do |attr_data|
445
+ attribute = find_or_create_attribute(attr_data, workflow)
446
+ StepOutputAttribute.find_or_create(step: step, attribute: attribute)
447
+ end
448
+ end
449
+ end
450
+
451
+ data['attributes'].each do |attr_data|
452
+ find_or_create_attribute(attr_data, workflow)
453
+ end
454
+ end
455
+
456
+ # Restore workflow runs from JSON files
457
+ Dir.glob('workflow_run_*.json').each do |file|
458
+ data = JSON.parse(File.read(file))
459
+
460
+ workflow_run = WorkflowRun.find_or_create(id: data['id'], workflow_id: data['workflow_id'])
461
+
462
+ data['section_runs'].each do |section_run_data|
463
+ section_run = SectionRun.find_or_create(id: section_run_data['id'], workflow_run: workflow_run, section_id: section_run_data['section_id'])
464
+
465
+ section_run_data['step_runs'].each do |step_run_data|
466
+ 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'])
467
+
468
+ step_run_data['attribute_values'].each do |attr_value_data|
469
+ attribute = Attribute.find(id: attr_value_data['id'])
470
+ AttributeValue.find_or_create(attribute: attribute, step_run: step_run) do |av|
471
+ av.value = attr_value_data['value']
472
+ end
473
+ end
474
+ end
475
+ end
476
+ end
477
+ ```
478
+
479
+ ## Sample Implementation of Workflow Builder (DSL)
480
+
481
+ ```ruby
482
+ require 'yaml'
483
+ require 'sequel'
484
+
485
+ # Assuming the database and models are already set up
486
+ DB = Sequel.sqlite('workflow.db')
487
+
488
+ # Models
489
+ class Workflow < Sequel::Model
490
+ one_to_many :sections
491
+ one_to_many :attributes
492
+ one_to_many :workflow_runs
493
+ end
494
+
495
+ class Section < Sequel::Model
496
+ many_to_one :workflow
497
+ one_to_many :steps
498
+ one_to_many :section_runs
499
+ end
500
+
501
+ class Step < Sequel::Model
502
+ many_to_one :section
503
+ one_to_many :input_attributes, class: :StepInputAttribute
504
+ one_to_many :output_attributes, class: :StepOutputAttribute
505
+ one_to_many :step_runs
506
+ end
507
+
508
+ class Attribute < Sequel::Model
509
+ many_to_one :workflow
510
+ one_to_many :input_attributes, class: :StepInputAttribute
511
+ one_to_many :output_attributes, class: :StepOutputAttribute
512
+ end
513
+
514
+ class StepInputAttribute < Sequel::Model
515
+ many_to_one :step
516
+ many_to_one :attribute
517
+ end
518
+
519
+ class StepOutputAttribute < Sequel::Model
520
+ many_to_one :step
521
+ many_to_one :attribute
522
+ end
523
+
524
+ # WorkflowBuilder
525
+ class WorkflowBuilder
526
+ def initialize(name:, description: nil)
527
+ @workflow = Workflow.new(name: name, description: description)
528
+ @current_section_order = 1
529
+ end
530
+
531
+ def description(desc)
532
+ @workflow.description = desc
533
+ end
534
+
535
+ def section(name:, &block)
536
+ @current_step_order = 1
537
+ @current_section = Section.new(name: name, order: @current_section_order)
538
+ @current_section_order += 1
539
+ instance_eval(&block) if block_given?
540
+ @workflow.add_section(@current_section)
541
+ end
542
+
543
+ def step(name:, &block)
544
+ step = Step.new(name: name, order: @current_step_order)
545
+ @current_step_order += 1
546
+ instance_eval(&block) if block_given?
547
+ @current_section.add_step(step)
548
+ end
549
+
550
+ def prompt(prompt)
551
+ @current_section.steps.last.prompt = prompt
552
+ end
553
+
554
+ def save
555
+ @workflow.save
556
+ end
557
+
558
+ def to_yaml
559
+ workflow_data = {
560
+ id: @workflow.id,
561
+ name: @workflow.name,
562
+ description: @workflow.description,
563
+ sections: @workflow.sections.map do |section|
564
+ {
565
+ id: section.id,
566
+ name: section.name,
567
+ description: section.description,
568
+ order: section.order,
569
+ steps: section.steps.map do |step|
570
+ {
571
+ id: step.id,
572
+ name: step.name,
573
+ description: step.description,
574
+ order: step.order,
575
+ prompt: step.prompt
576
+ }
577
+ end
578
+ }
579
+ end
580
+ }
581
+ workflow_data.to_yaml
582
+ end
583
+ end
584
+
585
+ ```
586
+
587
+ ## Usage via DSL
588
+
589
+ ```ruby
590
+ builder = WorkflowBuilder.new(name: 'YouTube Video Script')
591
+
592
+ builder.section(name: 'Research') do
593
+ step(name: '01-1-basic-meta') do
594
+ prompt 'Generate 5 titles to get started'
595
+ end
596
+
597
+ step(name: '01-2-basic-factsheet') do
598
+ prompt 'Generate detailed factsheet'
599
+ end
600
+ end
601
+
602
+ builder.section(name: 'Script Writing') do
603
+ step(name: '02-1-create-script') do
604
+ prompt 'Generate basic script'
605
+ end
606
+ end
607
+
608
+ puts builder.to_yaml
609
+
610
+ # Save to the database
611
+ builder.save
612
+
613
+
614
+ builder = WorkflowBuilder.new(name: 'YouTube Title Creator')
615
+
616
+ builder.section(name: 'Research') do
617
+ step(name: '01-1-working-title') do
618
+ prompt 'Come up with a simple working title for the YouTube video.'
619
+ end
620
+
621
+ step(name: '01-2-keyword-research') do
622
+ prompt 'Perform basic keyword research to identify relevant keywords.'
623
+ end
624
+
625
+ step(name: '01-3-topic-research') do
626
+ prompt 'Conduct basic topic research to gather information on the subject.'
627
+ end
628
+
629
+ step(name: '01-4-powerful-titles') do
630
+ prompt 'Ask GPT for 10 powerful titles based on the research.'
631
+ end
632
+
633
+ step(name: '01-5-title-rules') do
634
+ prompt 'Follow specific rules for title creation to ensure effectiveness.'
635
+ end
636
+ end
637
+
638
+ puts builder.to_yaml
639
+
640
+ # Save to the database
641
+ builder.save
642
+
643
+ ```
@@ -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.5'
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.5",
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.5",
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.5",
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.5
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