lex-argument-mapping 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/lib/legion/extensions/argument_mapping/client.rb +15 -0
- data/lib/legion/extensions/argument_mapping/helpers/argument.rb +98 -0
- data/lib/legion/extensions/argument_mapping/helpers/argument_engine.rb +127 -0
- data/lib/legion/extensions/argument_mapping/helpers/constants.rb +40 -0
- data/lib/legion/extensions/argument_mapping/runners/argument_mapping.rb +74 -0
- data/lib/legion/extensions/argument_mapping/version.rb +9 -0
- data/lib/legion/extensions/argument_mapping.rb +16 -0
- metadata +68 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: ee2b8b06421ea9635bf67560d2ed64c9294e13f081ed9d018e0c06234c2bc16d
|
|
4
|
+
data.tar.gz: a1cc040fe37b5da71c9732db6b305b200f5c07aecb0da077bec9aaa37d574c84
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: 6720dd8283e689b26b6039aa75dbc0ecf2a650b054903e5b07021be556dae64bbf79755b2299b4b864b4bd27941f384c937944dd4ca8313c8a1700c5689c5bfc
|
|
7
|
+
data.tar.gz: 4d62f7b556c652ecc930f369c0cae717d9a1091f986531052fdbf33ae766d487fc82d27ae2ecaec077c5a7abf668ad0f8864422b0c3825e738b520afbf0739c5
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module ArgumentMapping
|
|
6
|
+
module Helpers
|
|
7
|
+
class Argument
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :id, :claim, :grounds, :warrant, :backing,
|
|
11
|
+
:qualifier, :rebuttals, :created_at, :domain
|
|
12
|
+
|
|
13
|
+
def initialize(id:, claim:, domain: :general, warrant: nil, qualifier: :presumably)
|
|
14
|
+
@id = id
|
|
15
|
+
@claim = claim
|
|
16
|
+
@domain = domain
|
|
17
|
+
@warrant = warrant
|
|
18
|
+
@qualifier = qualifier
|
|
19
|
+
@grounds = []
|
|
20
|
+
@backing = []
|
|
21
|
+
@rebuttals = []
|
|
22
|
+
@created_at = Time.now.utc
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def add_ground(ground:)
|
|
26
|
+
@grounds << ground
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def add_backing(backing:)
|
|
30
|
+
@backing << backing
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def add_rebuttal(content:, impact: 0.5)
|
|
34
|
+
@rebuttals << { content: content, impact: impact.clamp(0.0, 1.0) }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def strength
|
|
38
|
+
raw = (ground_score * GROUND_WEIGHT) +
|
|
39
|
+
(warrant_score * WARRANT_WEIGHT) +
|
|
40
|
+
(backing_score * BACKING_WEIGHT) -
|
|
41
|
+
(rebuttal_score * REBUTTAL_PENALTY)
|
|
42
|
+
raw.clamp(0.0, 1.0)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def strength_label
|
|
46
|
+
ARGUMENT_STRENGTHS.find { |range, _| range.cover?(strength) }&.last
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def sound?
|
|
50
|
+
strength >= 0.6 && !@warrant.nil? && !@grounds.empty?
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def rebutted?
|
|
54
|
+
@rebuttals.any? { |r| r[:impact] > 0.5 }
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def to_h
|
|
58
|
+
{
|
|
59
|
+
id: @id,
|
|
60
|
+
claim: @claim,
|
|
61
|
+
domain: @domain,
|
|
62
|
+
grounds: @grounds,
|
|
63
|
+
warrant: @warrant,
|
|
64
|
+
backing: @backing,
|
|
65
|
+
qualifier: @qualifier,
|
|
66
|
+
rebuttals: @rebuttals,
|
|
67
|
+
strength: strength,
|
|
68
|
+
strength_label: strength_label,
|
|
69
|
+
sound: sound?,
|
|
70
|
+
rebutted: rebutted?,
|
|
71
|
+
created_at: @created_at
|
|
72
|
+
}
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
private
|
|
76
|
+
|
|
77
|
+
def ground_score
|
|
78
|
+
[@grounds.size / 3.0, 1.0].min
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def warrant_score
|
|
82
|
+
@warrant.nil? ? 0.0 : 0.8
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def backing_score
|
|
86
|
+
[@backing.size / 2.0, 1.0].min
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def rebuttal_score
|
|
90
|
+
return 0.0 if @rebuttals.empty?
|
|
91
|
+
|
|
92
|
+
@rebuttals.sum { |r| r[:impact] } / @rebuttals.size
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module ArgumentMapping
|
|
6
|
+
module Helpers
|
|
7
|
+
class ArgumentEngine
|
|
8
|
+
include Constants
|
|
9
|
+
|
|
10
|
+
attr_reader :arguments, :history
|
|
11
|
+
|
|
12
|
+
def initialize
|
|
13
|
+
@arguments = {}
|
|
14
|
+
@history = []
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def create_argument(claim:, domain: :general, warrant: nil, qualifier: :presumably)
|
|
18
|
+
return { success: false, reason: :max_arguments_reached } if @arguments.size >= MAX_ARGUMENTS
|
|
19
|
+
|
|
20
|
+
id = generate_id('arg')
|
|
21
|
+
argument = Argument.new(id: id, claim: claim, domain: domain,
|
|
22
|
+
warrant: warrant, qualifier: qualifier)
|
|
23
|
+
@arguments[id] = argument
|
|
24
|
+
add_history(type: :created, argument_id: id, claim: claim, domain: domain)
|
|
25
|
+
{ success: true, argument: argument.to_h }
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def add_ground(argument_id:, ground:)
|
|
29
|
+
argument = @arguments[argument_id]
|
|
30
|
+
return { success: false, reason: :not_found } unless argument
|
|
31
|
+
|
|
32
|
+
argument.add_ground(ground: ground)
|
|
33
|
+
add_history(type: :ground_added, argument_id: argument_id)
|
|
34
|
+
{ success: true, argument: argument.to_h }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def add_backing(argument_id:, backing:)
|
|
38
|
+
argument = @arguments[argument_id]
|
|
39
|
+
return { success: false, reason: :not_found } unless argument
|
|
40
|
+
|
|
41
|
+
argument.add_backing(backing: backing)
|
|
42
|
+
add_history(type: :backing_added, argument_id: argument_id)
|
|
43
|
+
{ success: true, argument: argument.to_h }
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def add_rebuttal(argument_id:, content:, impact: 0.5)
|
|
47
|
+
argument = @arguments[argument_id]
|
|
48
|
+
return { success: false, reason: :not_found } unless argument
|
|
49
|
+
|
|
50
|
+
argument.add_rebuttal(content: content, impact: impact)
|
|
51
|
+
add_history(type: :rebuttal_added, argument_id: argument_id, impact: impact)
|
|
52
|
+
{ success: true, argument: argument.to_h }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def assess_argument(argument_id:)
|
|
56
|
+
argument = @arguments[argument_id]
|
|
57
|
+
return { success: false, reason: :not_found } unless argument
|
|
58
|
+
|
|
59
|
+
{
|
|
60
|
+
success: true,
|
|
61
|
+
argument_id: argument_id,
|
|
62
|
+
claim: argument.claim,
|
|
63
|
+
domain: argument.domain,
|
|
64
|
+
strength: argument.strength,
|
|
65
|
+
strength_label: argument.strength_label,
|
|
66
|
+
sound: argument.sound?,
|
|
67
|
+
rebutted: argument.rebutted?,
|
|
68
|
+
ground_count: argument.grounds.size,
|
|
69
|
+
backing_count: argument.backing.size,
|
|
70
|
+
rebuttal_count: argument.rebuttals.size
|
|
71
|
+
}
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def sound_arguments
|
|
75
|
+
@arguments.values.select(&:sound?)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def rebutted_arguments
|
|
79
|
+
@arguments.values.select(&:rebutted?)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def arguments_by_domain(domain:)
|
|
83
|
+
@arguments.values.select { |a| a.domain == domain }
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def strongest_arguments(limit: 5)
|
|
87
|
+
@arguments.values.sort_by { |a| -a.strength }.first(limit)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def weakest_arguments(limit: 5)
|
|
91
|
+
@arguments.values.sort_by(&:strength).first(limit)
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def decay_all
|
|
95
|
+
@arguments.each_value do |argument|
|
|
96
|
+
next unless argument.instance_variable_defined?(:@base_strength)
|
|
97
|
+
|
|
98
|
+
current = argument.instance_variable_get(:@base_strength)
|
|
99
|
+
argument.instance_variable_set(:@base_strength, [current - DECAY_RATE, 0.0].max)
|
|
100
|
+
end
|
|
101
|
+
@arguments.size
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
def to_h
|
|
105
|
+
{
|
|
106
|
+
total_arguments: @arguments.size,
|
|
107
|
+
sound_arguments: sound_arguments.size,
|
|
108
|
+
rebutted_arguments: rebutted_arguments.size,
|
|
109
|
+
history_entries: @history.size
|
|
110
|
+
}
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
private
|
|
114
|
+
|
|
115
|
+
def add_history(entry)
|
|
116
|
+
@history << entry.merge(timestamp: Time.now.utc)
|
|
117
|
+
@history.shift if @history.size > MAX_HISTORY
|
|
118
|
+
end
|
|
119
|
+
|
|
120
|
+
def generate_id(prefix)
|
|
121
|
+
"#{prefix}_#{Time.now.utc.to_f}_#{rand(10_000)}"
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module ArgumentMapping
|
|
6
|
+
module Helpers
|
|
7
|
+
module Constants
|
|
8
|
+
ARGUMENT_STRENGTHS = {
|
|
9
|
+
(0.8..) => :compelling,
|
|
10
|
+
(0.6...0.8) => :strong,
|
|
11
|
+
(0.4...0.6) => :moderate,
|
|
12
|
+
(0.2...0.4) => :weak,
|
|
13
|
+
(..0.2) => :fallacious
|
|
14
|
+
}.freeze
|
|
15
|
+
|
|
16
|
+
QUALIFIER_TYPES = %i[certainly presumably probably possibly apparently].freeze
|
|
17
|
+
|
|
18
|
+
REBUTTAL_IMPACT_LABELS = {
|
|
19
|
+
(0.8..) => :devastating,
|
|
20
|
+
(0.6...0.8) => :significant,
|
|
21
|
+
(0.4...0.6) => :moderate,
|
|
22
|
+
(0.2...0.4) => :minor,
|
|
23
|
+
(..0.2) => :negligible
|
|
24
|
+
}.freeze
|
|
25
|
+
|
|
26
|
+
MAX_ARGUMENTS = 200
|
|
27
|
+
MAX_HISTORY = 500
|
|
28
|
+
|
|
29
|
+
DEFAULT_STRENGTH = 0.5
|
|
30
|
+
GROUND_WEIGHT = 0.3
|
|
31
|
+
WARRANT_WEIGHT = 0.3
|
|
32
|
+
BACKING_WEIGHT = 0.2
|
|
33
|
+
REBUTTAL_PENALTY = 0.2
|
|
34
|
+
|
|
35
|
+
DECAY_RATE = 0.02
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
end
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module ArgumentMapping
|
|
6
|
+
module Runners
|
|
7
|
+
module ArgumentMapping
|
|
8
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
9
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
10
|
+
|
|
11
|
+
def create_argument(claim:, domain: :general, warrant: nil, qualifier: :presumably, **)
|
|
12
|
+
Legion::Logging.info "[argument_mapping] create_argument: claim=#{claim} domain=#{domain}"
|
|
13
|
+
engine.create_argument(claim: claim, domain: domain, warrant: warrant, qualifier: qualifier)
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def add_argument_ground(argument_id:, ground:, **)
|
|
17
|
+
Legion::Logging.debug "[argument_mapping] add_ground: id=#{argument_id}"
|
|
18
|
+
engine.add_ground(argument_id: argument_id, ground: ground)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def add_argument_backing(argument_id:, backing:, **)
|
|
22
|
+
Legion::Logging.debug "[argument_mapping] add_backing: id=#{argument_id}"
|
|
23
|
+
engine.add_backing(argument_id: argument_id, backing: backing)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def add_argument_rebuttal(argument_id:, content:, impact: 0.5, **)
|
|
27
|
+
Legion::Logging.info "[argument_mapping] add_rebuttal: id=#{argument_id} impact=#{impact}"
|
|
28
|
+
engine.add_rebuttal(argument_id: argument_id, content: content, impact: impact)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def assess_argument_strength(argument_id:, **)
|
|
32
|
+
Legion::Logging.debug "[argument_mapping] assess: id=#{argument_id}"
|
|
33
|
+
engine.assess_argument(argument_id: argument_id)
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def sound_arguments_report(**)
|
|
37
|
+
Legion::Logging.debug '[argument_mapping] sound_arguments_report'
|
|
38
|
+
arguments = engine.sound_arguments
|
|
39
|
+
{ success: true, arguments: arguments.map(&:to_h), count: arguments.size }
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def rebutted_arguments_report(**)
|
|
43
|
+
Legion::Logging.debug '[argument_mapping] rebutted_arguments_report'
|
|
44
|
+
arguments = engine.rebutted_arguments
|
|
45
|
+
{ success: true, arguments: arguments.map(&:to_h), count: arguments.size }
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def strongest_arguments_report(limit: 5, **)
|
|
49
|
+
Legion::Logging.debug "[argument_mapping] strongest_arguments: limit=#{limit}"
|
|
50
|
+
arguments = engine.strongest_arguments(limit: limit)
|
|
51
|
+
{ success: true, arguments: arguments.map(&:to_h), count: arguments.size }
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def update_argument_mapping(**)
|
|
55
|
+
Legion::Logging.debug '[argument_mapping] decay_all'
|
|
56
|
+
decayed = engine.decay_all
|
|
57
|
+
{ success: true, arguments_processed: decayed }
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def argument_mapping_stats(**)
|
|
61
|
+
Legion::Logging.debug '[argument_mapping] stats'
|
|
62
|
+
{ success: true }.merge(engine.to_h)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
private
|
|
66
|
+
|
|
67
|
+
def engine
|
|
68
|
+
@engine ||= Helpers::ArgumentEngine.new
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'argument_mapping/version'
|
|
4
|
+
require_relative 'argument_mapping/helpers/constants'
|
|
5
|
+
require_relative 'argument_mapping/helpers/argument'
|
|
6
|
+
require_relative 'argument_mapping/helpers/argument_engine'
|
|
7
|
+
require_relative 'argument_mapping/runners/argument_mapping'
|
|
8
|
+
require_relative 'argument_mapping/client'
|
|
9
|
+
|
|
10
|
+
module Legion
|
|
11
|
+
module Extensions
|
|
12
|
+
module ArgumentMapping
|
|
13
|
+
extend Legion::Extensions::Core if defined?(Legion::Extensions::Core)
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-argument-mapping
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-gaia
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '0'
|
|
19
|
+
type: :development
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '0'
|
|
26
|
+
description: Toulmin-model argument mapping for LegionIO — claim/grounds/warrant/backing/qualifier/rebuttal
|
|
27
|
+
argument construction, strength assessment, and soundness evaluation
|
|
28
|
+
email:
|
|
29
|
+
- matthewdiverson@gmail.com
|
|
30
|
+
executables: []
|
|
31
|
+
extensions: []
|
|
32
|
+
extra_rdoc_files: []
|
|
33
|
+
files:
|
|
34
|
+
- lib/legion/extensions/argument_mapping.rb
|
|
35
|
+
- lib/legion/extensions/argument_mapping/client.rb
|
|
36
|
+
- lib/legion/extensions/argument_mapping/helpers/argument.rb
|
|
37
|
+
- lib/legion/extensions/argument_mapping/helpers/argument_engine.rb
|
|
38
|
+
- lib/legion/extensions/argument_mapping/helpers/constants.rb
|
|
39
|
+
- lib/legion/extensions/argument_mapping/runners/argument_mapping.rb
|
|
40
|
+
- lib/legion/extensions/argument_mapping/version.rb
|
|
41
|
+
homepage: https://github.com/LegionIO/lex-argument-mapping
|
|
42
|
+
licenses:
|
|
43
|
+
- MIT
|
|
44
|
+
metadata:
|
|
45
|
+
homepage_uri: https://github.com/LegionIO/lex-argument-mapping
|
|
46
|
+
source_code_uri: https://github.com/LegionIO/lex-argument-mapping
|
|
47
|
+
documentation_uri: https://github.com/LegionIO/lex-argument-mapping
|
|
48
|
+
changelog_uri: https://github.com/LegionIO/lex-argument-mapping
|
|
49
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-argument-mapping/issues
|
|
50
|
+
rubygems_mfa_required: 'true'
|
|
51
|
+
rdoc_options: []
|
|
52
|
+
require_paths:
|
|
53
|
+
- lib
|
|
54
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
55
|
+
requirements:
|
|
56
|
+
- - ">="
|
|
57
|
+
- !ruby/object:Gem::Version
|
|
58
|
+
version: '3.4'
|
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
|
+
requirements:
|
|
61
|
+
- - ">="
|
|
62
|
+
- !ruby/object:Gem::Version
|
|
63
|
+
version: '0'
|
|
64
|
+
requirements: []
|
|
65
|
+
rubygems_version: 3.6.9
|
|
66
|
+
specification_version: 4
|
|
67
|
+
summary: LegionIO argument mapping extension
|
|
68
|
+
test_files: []
|