Class: Legion::Extensions::Creativity::Helpers::CreativeEngine

Inherits:
Object
  • Object
show all
Defined in:
lib/legion/extensions/creativity/helpers/creative_engine.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(idea_store: nil) ⇒ CreativeEngine

Returns a new instance of CreativeEngine.



10
11
12
13
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 10

def initialize(idea_store: nil)
  @idea_store         = idea_store || IdeaStore.new
  @creative_potential = 0.0
end

Instance Attribute Details

#creative_potentialObject (readonly)

Returns the value of attribute creative_potential.



8
9
10
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 8

def creative_potential
  @creative_potential
end

#idea_storeObject (readonly)

Returns the value of attribute idea_store.



8
9
10
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 8

def idea_store
  @idea_store
end

Instance Method Details

#blend(concept_a:, concept_b:) ⇒ Object



53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 53

def blend(concept_a:, concept_b:)
  set_a    = Set.new(Array(concept_a).map(&:to_sym))
  set_b    = Set.new(Array(concept_b).map(&:to_sym))
  distance = jaccard_distance(set_a, set_b)

  return too_similar_result(distance) if distance < Constants::BLEND_DISTANCE_MIN

  idea = build_blended_idea(set_a, set_b, distance, concept_a, concept_b)
  @idea_store.add(idea)
  update_potential([idea])
  { status: :ok, idea: idea }
end

#compute_novelty(idea, existing = nil) ⇒ Object



71
72
73
74
75
76
77
78
79
80
81
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 71

def compute_novelty(idea, existing = nil)
  if existing
    set_a = idea.seed_concepts.to_set
    return 1.0 if existing.empty?

    distances = existing.map { |e| jaccard_distance(set_a, e.seed_concepts.to_set) }
    distances.sum / distances.size.to_f
  else
    @idea_store.compute_novelty(idea)
  end
end

#converge(ideas:) ⇒ Object



43
44
45
46
47
48
49
50
51
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 43

def converge(ideas:)
  return [] if ideas.nil? || ideas.empty?

  ranked = ideas
           .select { |i| %i[emerged evaluated].include?(i.state) }
           .sort_by { |i| -i.composite_quality }
  ranked.each { |i| i.evaluate!(quality_scores: i.quality_scores) if i.state == :emerged }
  ranked
end

#diverge(prompt:, count: 5) ⇒ Object



15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 15

def diverge(prompt:, count: 5)
  count = [count.to_i, 1].max
  seeds = extract_seeds(prompt)
  ideas = []

  count.times do |i|
    quality = diverge_quality_scores(i, count)
    idea    = Idea.new(
      mode:           :divergent,
      seed_concepts:  seeds + [@idea_store.seed_buffer.sample].compact,
      description:    "#{prompt} — variant #{i + 1}",
      quality_scores: quality
    )
    novelty        = @idea_store.compute_novelty(idea)
    idea_with_nov  = Idea.new(
      mode:           :divergent,
      seed_concepts:  idea.seed_concepts,
      description:    idea.description,
      quality_scores: quality.merge(originality: novelty)
    )
    @idea_store.add(idea_with_nov)
    ideas << idea_with_nov
  end

  update_potential(ideas)
  ideas
end

#incubateObject



66
67
68
69
# File 'lib/legion/extensions/creativity/helpers/creative_engine.rb', line 66

def incubate
  @idea_store.tick
  @idea_store.emerge_ready
end