lex-apollo 0.4.22 → 0.4.23
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 +4 -4
- data/CHANGELOG.md +8 -0
- data/lib/legion/extensions/apollo/actors/corroboration_checker.rb +3 -1
- data/lib/legion/extensions/apollo/actors/decay.rb +3 -1
- data/lib/legion/extensions/apollo/actors/entity_watchdog.rb +10 -21
- data/lib/legion/extensions/apollo/actors/expertise_aggregator.rb +3 -1
- data/lib/legion/extensions/apollo/actors/gas_subscriber.rb +1 -1
- data/lib/legion/extensions/apollo/actors/ingest.rb +1 -1
- data/lib/legion/extensions/apollo/actors/query_responder.rb +1 -1
- data/lib/legion/extensions/apollo/actors/writeback_store.rb +1 -1
- data/lib/legion/extensions/apollo/actors/writeback_vectorize.rb +2 -2
- data/lib/legion/extensions/apollo/api.rb +28 -22
- data/lib/legion/extensions/apollo/gaia_integration.rb +13 -11
- data/lib/legion/extensions/apollo/helpers/capability.rb +12 -13
- data/lib/legion/extensions/apollo/helpers/confidence.rb +5 -8
- data/lib/legion/extensions/apollo/helpers/data_models.rb +61 -0
- data/lib/legion/extensions/apollo/helpers/entity_watchdog.rb +8 -15
- data/lib/legion/extensions/apollo/helpers/similarity.rb +5 -6
- data/lib/legion/extensions/apollo/helpers/writeback.rb +13 -14
- data/lib/legion/extensions/apollo/runners/expertise.rb +10 -8
- data/lib/legion/extensions/apollo/runners/gas.rb +18 -14
- data/lib/legion/extensions/apollo/runners/knowledge.rb +77 -62
- data/lib/legion/extensions/apollo/runners/maintenance.rb +5 -4
- data/lib/legion/extensions/apollo/runners/request.rb +7 -1
- data/lib/legion/extensions/apollo/version.rb +1 -1
- data/lib/legion/extensions/apollo.rb +96 -0
- data/spec/legion/extensions/apollo/actors/writeback_vectorize_spec.rb +3 -3
- data/spec/legion/extensions/apollo/api_spec.rb +20 -0
- data/spec/legion/extensions/apollo/helpers/capability_spec.rb +4 -4
- data/spec/legion/extensions/apollo/runners/gas_anticipate_spec.rb +0 -3
- data/spec/legion/extensions/apollo/runners/gas_relate_spec.rb +0 -4
- data/spec/legion/extensions/apollo/runners/gas_synthesize_spec.rb +0 -11
- data/spec/legion/extensions/apollo/runners/knowledge_spec.rb +19 -9
- data/spec/legion/extensions/apollo/runners/request_spec.rb +4 -4
- data/spec/spec_helper.rb +4 -0
- metadata +2 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: af5cbbe35e69f28430c0c4d2862294024e465b79a7fdba279bb50562bc0d81d4
|
|
4
|
+
data.tar.gz: d2cf12984c06eb60752f7202935649a411377ca141e20d719d2faa2ec4c05b3b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: a2bf398b3f6df58ec0e84f810f7ba4e48e68991c88f95ae8e5614ba4510ae7ab9be3994dc757f34138073797cb2af99c795d532f4e24dc9fb2f09ffa0b18d13f
|
|
7
|
+
data.tar.gz: fad944b5457ef0574bb53b1d88251d5d4dce1a70b3cbe8ffadb25b3938877a0170cd36adbf41705d066d84f7036043914efa6b7473db5999daf24badde8a7f5d
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,13 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.4.23] - 2026-05-06
|
|
4
|
+
|
|
5
|
+
### Fixed
|
|
6
|
+
- Apollo data model access now prefers the namespaced `Legion::Data::Model::Apollo::*` classes introduced by the legion-data schema cleanup while retaining fallback compatibility with the legacy `ApolloEntry`, `ApolloRelation`, `ApolloAccessLog`, and `ApolloExpertise` constants.
|
|
7
|
+
|
|
8
|
+
### Changed
|
|
9
|
+
- Apollo defaults are now declared directly in `Apollo.default_settings`, and Apollo helpers, runners, actors, and API paths use `Legion::Logging::Helper`, `Legion::Settings::Helper`, and `Legion::JSON` helper methods instead of direct logging/settings/JSON calls.
|
|
10
|
+
|
|
3
11
|
## [0.4.22] - 2026-04-28
|
|
4
12
|
|
|
5
13
|
### Fixed
|
|
@@ -8,9 +8,11 @@ module Legion
|
|
|
8
8
|
module Apollo
|
|
9
9
|
module Actor
|
|
10
10
|
class CorroborationChecker < Legion::Extensions::Actors::Every
|
|
11
|
+
include Legion::Settings::Helper
|
|
12
|
+
|
|
11
13
|
def runner_class = Legion::Extensions::Apollo::Runners::Maintenance
|
|
12
14
|
def runner_function = 'check_corroboration'
|
|
13
|
-
def time =
|
|
15
|
+
def time = settings[:actors][:corroboration_interval]
|
|
14
16
|
def run_now? = false
|
|
15
17
|
def use_runner? = false
|
|
16
18
|
def check_subtask? = false
|
|
@@ -8,9 +8,11 @@ module Legion
|
|
|
8
8
|
module Apollo
|
|
9
9
|
module Actor
|
|
10
10
|
class Decay < Legion::Extensions::Actors::Every
|
|
11
|
+
include Legion::Settings::Helper
|
|
12
|
+
|
|
11
13
|
def runner_class = Legion::Extensions::Apollo::Runners::Maintenance
|
|
12
14
|
def runner_function = 'run_decay_cycle'
|
|
13
|
-
def time =
|
|
15
|
+
def time = settings[:actors][:decay_interval]
|
|
14
16
|
def run_now? = false
|
|
15
17
|
def use_runner? = false
|
|
16
18
|
def check_subtask? = false
|
|
@@ -11,6 +11,7 @@ module Legion
|
|
|
11
11
|
class EntityWatchdog < Legion::Extensions::Actors::Every
|
|
12
12
|
include Legion::Extensions::Apollo::Runners::Knowledge
|
|
13
13
|
include Legion::Extensions::Apollo::Runners::EntityExtractor
|
|
14
|
+
include Legion::Settings::Helper
|
|
14
15
|
|
|
15
16
|
DEDUP_THRESHOLD_DEFAULT = 0.92
|
|
16
17
|
TASK_LOG_LOOKBACK_SECONDS = 300
|
|
@@ -18,7 +19,7 @@ module Legion
|
|
|
18
19
|
|
|
19
20
|
def runner_class = self.class
|
|
20
21
|
def runner_function = 'scan_and_ingest'
|
|
21
|
-
def time =
|
|
22
|
+
def time = settings[:actors][:entity_watchdog_interval]
|
|
22
23
|
def run_now? = false
|
|
23
24
|
def use_runner? = false
|
|
24
25
|
def check_subtask? = false
|
|
@@ -28,7 +29,7 @@ module Legion
|
|
|
28
29
|
defined?(Legion::Extensions::Apollo::Runners::EntityExtractor) &&
|
|
29
30
|
Legion.const_defined?(:Transport, false)
|
|
30
31
|
rescue StandardError => e
|
|
31
|
-
|
|
32
|
+
handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.enabled')
|
|
32
33
|
false
|
|
33
34
|
end
|
|
34
35
|
|
|
@@ -64,8 +65,8 @@ module Legion
|
|
|
64
65
|
def recent_task_log_texts
|
|
65
66
|
return [] unless defined?(Legion::Data) && defined?(Legion::Data::Model::TaskLog)
|
|
66
67
|
|
|
67
|
-
lookback =
|
|
68
|
-
log_limit =
|
|
68
|
+
lookback = settings[:entity_watchdog][:lookback_seconds]
|
|
69
|
+
log_limit = settings[:entity_watchdog][:log_limit]
|
|
69
70
|
cutoff = Time.now - lookback
|
|
70
71
|
logs = Legion::Data::Model::TaskLog
|
|
71
72
|
.where { created_at >= cutoff }
|
|
@@ -76,7 +77,7 @@ module Legion
|
|
|
76
77
|
log.debug("EntityWatchdog recent_task_log_texts lookback=#{lookback} limit=#{log_limit} raw=#{logs.size} unique=#{texts.size}")
|
|
77
78
|
texts
|
|
78
79
|
rescue StandardError => e
|
|
79
|
-
|
|
80
|
+
handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.recent_task_log_texts')
|
|
80
81
|
[]
|
|
81
82
|
end
|
|
82
83
|
|
|
@@ -93,7 +94,7 @@ module Legion
|
|
|
93
94
|
distance = closest[:distance].to_f
|
|
94
95
|
distance <= (1.0 - dedup_similarity_threshold)
|
|
95
96
|
rescue StandardError => e
|
|
96
|
-
|
|
97
|
+
handle_exception(e, level: :warn, operation: 'apollo.entity_watchdog.entity_exists_in_apollo')
|
|
97
98
|
false
|
|
98
99
|
end
|
|
99
100
|
|
|
@@ -113,27 +114,15 @@ module Legion
|
|
|
113
114
|
end
|
|
114
115
|
|
|
115
116
|
def entity_types
|
|
116
|
-
|
|
117
|
-
types = Legion::Settings.dig(:apollo, :entity_watchdog, :types)
|
|
118
|
-
return Array(types).map(&:to_s) if types
|
|
119
|
-
end
|
|
120
|
-
%w[person service repository concept]
|
|
117
|
+
Array(settings[:entity_watchdog][:types]).map(&:to_s)
|
|
121
118
|
end
|
|
122
119
|
|
|
123
120
|
def min_entity_confidence
|
|
124
|
-
|
|
125
|
-
val = Legion::Settings.dig(:apollo, :entity_watchdog, :min_confidence)
|
|
126
|
-
return val.to_f if val
|
|
127
|
-
end
|
|
128
|
-
0.7
|
|
121
|
+
settings[:entity_watchdog][:min_confidence].to_f
|
|
129
122
|
end
|
|
130
123
|
|
|
131
124
|
def dedup_similarity_threshold
|
|
132
|
-
|
|
133
|
-
val = Legion::Settings.dig(:apollo, :entity_watchdog, :dedup_threshold)
|
|
134
|
-
return val.to_f if val
|
|
135
|
-
end
|
|
136
|
-
DEDUP_THRESHOLD_DEFAULT
|
|
125
|
+
settings[:entity_watchdog][:dedup_threshold].to_f
|
|
137
126
|
end
|
|
138
127
|
end
|
|
139
128
|
end
|
|
@@ -8,9 +8,11 @@ module Legion
|
|
|
8
8
|
module Apollo
|
|
9
9
|
module Actor
|
|
10
10
|
class ExpertiseAggregator < Legion::Extensions::Actors::Every
|
|
11
|
+
include Legion::Settings::Helper
|
|
12
|
+
|
|
11
13
|
def runner_class = Legion::Extensions::Apollo::Runners::Expertise
|
|
12
14
|
def runner_function = 'aggregate'
|
|
13
|
-
def time =
|
|
15
|
+
def time = settings[:actors][:expertise_interval]
|
|
14
16
|
def run_now? = false
|
|
15
17
|
def use_runner? = false
|
|
16
18
|
def check_subtask? = false
|
|
@@ -17,7 +17,7 @@ module Legion
|
|
|
17
17
|
defined?(Legion::Extensions::Apollo::Runners::Gas) &&
|
|
18
18
|
Legion.const_defined?(:Transport, false)
|
|
19
19
|
rescue StandardError => e
|
|
20
|
-
|
|
20
|
+
handle_exception(e, level: :warn, operation: 'apollo.gas_subscriber.enabled')
|
|
21
21
|
false
|
|
22
22
|
end
|
|
23
23
|
|
|
@@ -16,7 +16,7 @@ module Legion
|
|
|
16
16
|
defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
|
|
17
17
|
Legion.const_defined?(:Transport, false)
|
|
18
18
|
rescue StandardError => e
|
|
19
|
-
|
|
19
|
+
handle_exception(e, level: :warn, operation: 'apollo.ingest.enabled')
|
|
20
20
|
false
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -16,7 +16,7 @@ module Legion
|
|
|
16
16
|
defined?(Legion::Extensions::Apollo::Runners::Knowledge) &&
|
|
17
17
|
Legion.const_defined?(:Transport, false)
|
|
18
18
|
rescue StandardError => e
|
|
19
|
-
|
|
19
|
+
handle_exception(e, level: :warn, operation: 'apollo.query_responder.enabled')
|
|
20
20
|
false
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -17,7 +17,7 @@ module Legion
|
|
|
17
17
|
Legion.const_defined?(:Transport, false) &&
|
|
18
18
|
Helpers::Capability.apollo_write_enabled?
|
|
19
19
|
rescue StandardError => e
|
|
20
|
-
|
|
20
|
+
handle_exception(e, level: :warn, operation: 'apollo.writeback_store.enabled')
|
|
21
21
|
false
|
|
22
22
|
end
|
|
23
23
|
end
|
|
@@ -15,7 +15,7 @@ module Legion
|
|
|
15
15
|
def handle_vectorize(payload)
|
|
16
16
|
payload = symbolize(payload)
|
|
17
17
|
log.debug("WritebackVectorize handle_vectorize content_length=#{payload[:content].to_s.length} content_type=#{payload[:content_type] || 'nil'}")
|
|
18
|
-
result = Legion::LLM::Embeddings.generate(text: payload[:content])
|
|
18
|
+
result = Legion::LLM::Call::Embeddings.generate(text: payload[:content])
|
|
19
19
|
vector = result.is_a?(Hash) ? result[:vector] : result
|
|
20
20
|
embedding = vector.is_a?(Array) && vector.any? ? vector : Array.new(1024, 0.0)
|
|
21
21
|
log.debug("WritebackVectorize embedding_dimensions=#{embedding.length} vector_generated=#{vector.is_a?(Array) && vector.any?}")
|
|
@@ -41,7 +41,7 @@ module Legion
|
|
|
41
41
|
def enabled? # rubocop:disable Legion/Extension/ActorEnabledSideEffects
|
|
42
42
|
Legion.const_defined?(:Transport, false) && Helpers::Capability.can_embed?
|
|
43
43
|
rescue StandardError => e
|
|
44
|
-
|
|
44
|
+
handle_exception(e, level: :warn, operation: 'apollo.writeback_vectorize.enabled')
|
|
45
45
|
false
|
|
46
46
|
end
|
|
47
47
|
|
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
3
|
require 'sinatra/base' unless defined?(Sinatra)
|
|
4
|
-
require '
|
|
4
|
+
require 'legion/logging'
|
|
5
|
+
require 'legion/json'
|
|
6
|
+
require 'legion/extensions/apollo/helpers/data_models'
|
|
5
7
|
|
|
6
8
|
module Legion
|
|
7
9
|
module Extensions
|
|
@@ -11,9 +13,9 @@ module Legion
|
|
|
11
13
|
|
|
12
14
|
class << self
|
|
13
15
|
def stats_payload(now: Time.now)
|
|
14
|
-
return { error: 'apollo_data_not_available' } unless
|
|
16
|
+
return { error: 'apollo_data_not_available' } unless Helpers::DataModels.apollo_entry_available?
|
|
15
17
|
|
|
16
|
-
entries =
|
|
18
|
+
entries = Helpers::DataModels.apollo_entry
|
|
17
19
|
by_status = grouped_counts(entries, :status)
|
|
18
20
|
by_status['active'] = entries.exclude(status: 'archived').count
|
|
19
21
|
|
|
@@ -24,7 +26,7 @@ module Legion
|
|
|
24
26
|
by_status: by_status,
|
|
25
27
|
by_content_type: grouped_counts(entries, :content_type)
|
|
26
28
|
}
|
|
27
|
-
stats[:total_relations] =
|
|
29
|
+
stats[:total_relations] = Helpers::DataModels.apollo_relation.count if Helpers::DataModels.apollo_relation_available?
|
|
28
30
|
stats
|
|
29
31
|
end
|
|
30
32
|
|
|
@@ -45,13 +47,17 @@ module Legion
|
|
|
45
47
|
end
|
|
46
48
|
|
|
47
49
|
helpers do
|
|
50
|
+
include Legion::Logging::Helper
|
|
51
|
+
include Legion::JSON::Helper
|
|
52
|
+
|
|
48
53
|
def json_body
|
|
49
54
|
body = request.body.read
|
|
50
55
|
return {} if body.empty?
|
|
51
56
|
|
|
52
|
-
|
|
53
|
-
rescue ::JSON::
|
|
54
|
-
|
|
57
|
+
json_parse(body)
|
|
58
|
+
rescue Legion::JSON::ParseError => e
|
|
59
|
+
handle_exception(e, level: :warn, operation: 'apollo.api.json_body')
|
|
60
|
+
halt 400, json_dump(error: "invalid JSON: #{e.message}")
|
|
55
61
|
end
|
|
56
62
|
|
|
57
63
|
def runner
|
|
@@ -73,14 +79,14 @@ module Legion
|
|
|
73
79
|
|
|
74
80
|
# Health check
|
|
75
81
|
get '/api/apollo/health' do
|
|
76
|
-
available =
|
|
77
|
-
|
|
82
|
+
available = Helpers::DataModels.apollo_entry_available?
|
|
83
|
+
json_dump(status: available ? 'ok' : 'degraded', data_available: available)
|
|
78
84
|
end
|
|
79
85
|
|
|
80
86
|
# Query knowledge (semantic search)
|
|
81
87
|
post '/api/apollo/query' do
|
|
82
88
|
req = json_body
|
|
83
|
-
halt 400,
|
|
89
|
+
halt 400, json_dump(error: 'query is required') unless req[:query]
|
|
84
90
|
|
|
85
91
|
query_options = {
|
|
86
92
|
query: req[:query],
|
|
@@ -94,14 +100,14 @@ module Legion
|
|
|
94
100
|
|
|
95
101
|
result = runner.handle_query(**query_options)
|
|
96
102
|
status result[:success] ? 200 : 500
|
|
97
|
-
result
|
|
103
|
+
json_dump(result)
|
|
98
104
|
end
|
|
99
105
|
|
|
100
106
|
# Ingest knowledge
|
|
101
107
|
post '/api/apollo/ingest' do
|
|
102
108
|
req = json_body
|
|
103
|
-
halt 400,
|
|
104
|
-
halt 400,
|
|
109
|
+
halt 400, json_dump(error: 'content is required') unless req[:content]
|
|
110
|
+
halt 400, json_dump(error: 'content_type is required') unless req[:content_type]
|
|
105
111
|
|
|
106
112
|
result = runner.handle_ingest(
|
|
107
113
|
content: req[:content],
|
|
@@ -114,13 +120,13 @@ module Legion
|
|
|
114
120
|
context: req[:context] || {}
|
|
115
121
|
)
|
|
116
122
|
status result[:success] ? 201 : 500
|
|
117
|
-
result
|
|
123
|
+
json_dump(result)
|
|
118
124
|
end
|
|
119
125
|
|
|
120
126
|
# Graph traversal
|
|
121
127
|
post '/api/apollo/traverse' do
|
|
122
128
|
req = json_body
|
|
123
|
-
halt 400,
|
|
129
|
+
halt 400, json_dump(error: 'entry_id is required') unless req[:entry_id]
|
|
124
130
|
|
|
125
131
|
result = runner.handle_traverse(
|
|
126
132
|
entry_id: req[:entry_id],
|
|
@@ -129,13 +135,13 @@ module Legion
|
|
|
129
135
|
agent_id: req[:agent_id] || 'api'
|
|
130
136
|
)
|
|
131
137
|
status result[:success] ? 200 : 500
|
|
132
|
-
result
|
|
138
|
+
json_dump(result)
|
|
133
139
|
end
|
|
134
140
|
|
|
135
141
|
# Retrieve relevant (GAIA-compatible)
|
|
136
142
|
post '/api/apollo/retrieve' do
|
|
137
143
|
req = json_body
|
|
138
|
-
halt 400,
|
|
144
|
+
halt 400, json_dump(error: 'query is required') unless req[:query]
|
|
139
145
|
|
|
140
146
|
result = runner.retrieve_relevant(
|
|
141
147
|
query: req[:query],
|
|
@@ -145,7 +151,7 @@ module Legion
|
|
|
145
151
|
domain: req[:domain]
|
|
146
152
|
)
|
|
147
153
|
status result[:success] ? 200 : 500
|
|
148
|
-
result
|
|
154
|
+
json_dump(result)
|
|
149
155
|
end
|
|
150
156
|
|
|
151
157
|
# Deprecate entry
|
|
@@ -154,24 +160,24 @@ module Legion
|
|
|
154
160
|
entry_id: params[:id],
|
|
155
161
|
reason: json_body[:reason] || 'deprecated via API'
|
|
156
162
|
)
|
|
157
|
-
result
|
|
163
|
+
json_dump(result)
|
|
158
164
|
end
|
|
159
165
|
|
|
160
166
|
# Domains at risk — must be declared before /:agent_id to avoid routing conflict
|
|
161
167
|
get '/api/apollo/expertise/at-risk' do
|
|
162
168
|
result = expertise_runner.domains_at_risk
|
|
163
|
-
result
|
|
169
|
+
json_dump(result)
|
|
164
170
|
end
|
|
165
171
|
|
|
166
172
|
# Expertise for an agent
|
|
167
173
|
get '/api/apollo/expertise/:agent_id' do
|
|
168
174
|
result = expertise_runner.agent_profile(agent_id: params[:agent_id])
|
|
169
|
-
result
|
|
175
|
+
json_dump(result)
|
|
170
176
|
end
|
|
171
177
|
|
|
172
178
|
# Statistics
|
|
173
179
|
get '/api/apollo/stats' do
|
|
174
|
-
self.class.stats_payload
|
|
180
|
+
json_dump(self.class.stats_payload)
|
|
175
181
|
end
|
|
176
182
|
end
|
|
177
183
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require_relative 'helpers/data_models'
|
|
4
|
+
|
|
3
5
|
module Legion
|
|
4
6
|
module Extensions
|
|
5
7
|
module Apollo
|
|
@@ -27,13 +29,13 @@ module Legion
|
|
|
27
29
|
end
|
|
28
30
|
|
|
29
31
|
def handle_mesh_departure(agent_id:)
|
|
30
|
-
return nil unless
|
|
32
|
+
return nil unless Helpers::DataModels.apollo_expertise_available?
|
|
31
33
|
|
|
32
|
-
sole_expert_domains =
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
34
|
+
sole_expert_domains = Helpers::DataModels.apollo_expertise
|
|
35
|
+
.where(agent_id: agent_id)
|
|
36
|
+
.all
|
|
37
|
+
.select { |e| sole_expert?(e.domain, agent_id) }
|
|
38
|
+
.map(&:domain)
|
|
37
39
|
|
|
38
40
|
return nil if sole_expert_domains.empty?
|
|
39
41
|
|
|
@@ -48,12 +50,12 @@ module Legion
|
|
|
48
50
|
private
|
|
49
51
|
|
|
50
52
|
def sole_expert?(domain, agent_id)
|
|
51
|
-
return false unless
|
|
53
|
+
return false unless Helpers::DataModels.apollo_expertise_available?
|
|
52
54
|
|
|
53
|
-
count =
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
count = Helpers::DataModels.apollo_expertise
|
|
56
|
+
.where(domain: domain)
|
|
57
|
+
.exclude(agent_id: agent_id)
|
|
58
|
+
.count
|
|
57
59
|
count.zero?
|
|
58
60
|
end
|
|
59
61
|
end
|
|
@@ -5,20 +5,19 @@ module Legion
|
|
|
5
5
|
module Apollo
|
|
6
6
|
module Helpers
|
|
7
7
|
module Capability
|
|
8
|
+
extend Legion::Logging::Helper
|
|
9
|
+
extend Legion::Settings::Helper
|
|
10
|
+
|
|
8
11
|
EMBEDDING_MODELS = %w[mxbai-embed-large bge-large snowflake-arctic-embed].freeze
|
|
9
12
|
|
|
10
13
|
module_function
|
|
11
14
|
|
|
12
|
-
def log
|
|
13
|
-
Legion::Logging
|
|
14
|
-
end
|
|
15
|
-
|
|
16
15
|
def can_embed?
|
|
17
16
|
return false unless defined?(Legion::LLM) && Legion::LLM.started?
|
|
18
17
|
|
|
19
18
|
ollama_embedding_available? || cloud_embedding_configured?
|
|
20
19
|
rescue StandardError => e
|
|
21
|
-
|
|
20
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.can_embed')
|
|
22
21
|
false
|
|
23
22
|
end
|
|
24
23
|
|
|
@@ -28,14 +27,14 @@ module Legion
|
|
|
28
27
|
|
|
29
28
|
check_db_write_privilege
|
|
30
29
|
rescue StandardError => e
|
|
31
|
-
|
|
30
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.can_write')
|
|
32
31
|
false
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
def apollo_write_enabled?
|
|
36
|
-
|
|
35
|
+
settings[:data][:apollo_write] == true
|
|
37
36
|
rescue StandardError => e
|
|
38
|
-
|
|
37
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.apollo_write_enabled')
|
|
39
38
|
false
|
|
40
39
|
end
|
|
41
40
|
|
|
@@ -44,16 +43,16 @@ module Legion
|
|
|
44
43
|
|
|
45
44
|
EMBEDDING_MODELS.any? { |m| Legion::LLM::Discovery::Ollama.model_available?(m) }
|
|
46
45
|
rescue StandardError => e
|
|
47
|
-
|
|
46
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.ollama_embedding_available')
|
|
48
47
|
false
|
|
49
48
|
end
|
|
50
49
|
|
|
51
50
|
def cloud_embedding_configured?
|
|
52
|
-
provider =
|
|
53
|
-
model =
|
|
51
|
+
provider = settings[:embedding][:provider]
|
|
52
|
+
model = settings[:embedding][:model]
|
|
54
53
|
!provider.nil? && !model.nil?
|
|
55
54
|
rescue StandardError => e
|
|
56
|
-
|
|
55
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.cloud_embedding_configured')
|
|
57
56
|
false
|
|
58
57
|
end
|
|
59
58
|
|
|
@@ -64,7 +63,7 @@ module Legion
|
|
|
64
63
|
.fetch("SELECT has_table_privilege(current_user, 'apollo_entries', 'INSERT') AS can_insert")
|
|
65
64
|
.first[:can_insert] == true
|
|
66
65
|
rescue StandardError => e
|
|
67
|
-
|
|
66
|
+
handle_exception(e, level: :warn, operation: 'apollo.capability.check_db_write_privilege')
|
|
68
67
|
@apollo_write_privilege = false
|
|
69
68
|
end
|
|
70
69
|
|
|
@@ -5,6 +5,9 @@ module Legion
|
|
|
5
5
|
module Apollo
|
|
6
6
|
module Helpers
|
|
7
7
|
module Confidence
|
|
8
|
+
extend Legion::Logging::Helper
|
|
9
|
+
extend Legion::Settings::Helper
|
|
10
|
+
|
|
8
11
|
INITIAL_CONFIDENCE = 0.5
|
|
9
12
|
CORROBORATION_BOOST = 0.3
|
|
10
13
|
RETRIEVAL_BOOST = 0.02
|
|
@@ -21,16 +24,10 @@ module Legion
|
|
|
21
24
|
|
|
22
25
|
module_function
|
|
23
26
|
|
|
24
|
-
def log
|
|
25
|
-
Legion::Logging
|
|
26
|
-
end
|
|
27
|
-
|
|
28
27
|
def apollo_setting(*keys, default:)
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
Legion::Settings[:apollo].dig(*keys) || default
|
|
28
|
+
settings.dig(*keys)
|
|
32
29
|
rescue StandardError => e
|
|
33
|
-
|
|
30
|
+
handle_exception(e, level: :warn, operation: 'apollo.confidence.apollo_setting', keys: keys)
|
|
34
31
|
default
|
|
35
32
|
end
|
|
36
33
|
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Apollo
|
|
6
|
+
module Helpers
|
|
7
|
+
module DataModels
|
|
8
|
+
class << self
|
|
9
|
+
def apollo_entry
|
|
10
|
+
namespaced_apollo_model(:Entry) || legacy_model(:ApolloEntry)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def apollo_relation
|
|
14
|
+
namespaced_apollo_model(:Relation) || legacy_model(:ApolloRelation)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def apollo_access_log
|
|
18
|
+
namespaced_apollo_model(:AccessLog) || legacy_model(:ApolloAccessLog)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def apollo_expertise
|
|
22
|
+
namespaced_apollo_model(:Expertise) || legacy_model(:ApolloExpertise)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def apollo_entry_available?
|
|
26
|
+
!apollo_entry.nil?
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def apollo_relation_available?
|
|
30
|
+
!apollo_relation.nil?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def apollo_access_log_available?
|
|
34
|
+
!apollo_access_log.nil?
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def apollo_expertise_available?
|
|
38
|
+
!apollo_expertise.nil?
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def namespaced_apollo_model(name)
|
|
44
|
+
return nil unless defined?(Legion::Data::Model::Apollo)
|
|
45
|
+
return nil unless Legion::Data::Model::Apollo.const_defined?(name, false)
|
|
46
|
+
|
|
47
|
+
Legion::Data::Model::Apollo.const_get(name, false)
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def legacy_model(name)
|
|
51
|
+
return nil unless defined?(Legion::Data::Model)
|
|
52
|
+
return nil unless Legion::Data::Model.const_defined?(name, false)
|
|
53
|
+
|
|
54
|
+
Legion::Data::Model.const_get(name, false)
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -12,9 +12,8 @@ module Legion
|
|
|
12
12
|
}.freeze
|
|
13
13
|
|
|
14
14
|
class << self
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
end
|
|
15
|
+
include Legion::Logging::Helper
|
|
16
|
+
include Legion::Settings::Helper
|
|
18
17
|
|
|
19
18
|
def detect_entities(text:, types: nil)
|
|
20
19
|
return [] if text.nil? || text.empty?
|
|
@@ -23,11 +22,13 @@ module Legion
|
|
|
23
22
|
entities = []
|
|
24
23
|
|
|
25
24
|
types.each do |type_sym|
|
|
26
|
-
|
|
25
|
+
entity_type = type_sym == :repository ? :repo : type_sym
|
|
26
|
+
pattern = entity_type == :concept ? concept_pattern : ENTITY_PATTERNS[entity_type]
|
|
27
27
|
next unless pattern
|
|
28
28
|
|
|
29
29
|
text.scan(pattern).each do |match|
|
|
30
|
-
entities << { type:
|
|
30
|
+
entities << { type: entity_type, value: match.strip,
|
|
31
|
+
confidence: Confidence.apollo_setting(:entity_watchdog, :detect_confidence, default: 0.5) }
|
|
31
32
|
end
|
|
32
33
|
end
|
|
33
34
|
|
|
@@ -55,11 +56,7 @@ module Legion
|
|
|
55
56
|
end
|
|
56
57
|
|
|
57
58
|
def concept_pattern
|
|
58
|
-
keywords =
|
|
59
|
-
Legion::Settings.dig(:apollo, :entity_watchdog, :concept_keywords) || []
|
|
60
|
-
else
|
|
61
|
-
[]
|
|
62
|
-
end
|
|
59
|
+
keywords = settings[:entity_watchdog][:concept_keywords]
|
|
63
60
|
return nil if keywords.empty?
|
|
64
61
|
|
|
65
62
|
Regexp.new("\\b(?:#{keywords.map { |k| Regexp.escape(k) }.join('|')})\\b", Regexp::IGNORECASE)
|
|
@@ -68,11 +65,7 @@ module Legion
|
|
|
68
65
|
private
|
|
69
66
|
|
|
70
67
|
def default_types
|
|
71
|
-
|
|
72
|
-
Legion::Settings.dig(:apollo, :entity_watchdog, :types) || %w[person service repo concept]
|
|
73
|
-
else
|
|
74
|
-
%w[person service repo concept]
|
|
75
|
-
end
|
|
68
|
+
settings[:entity_watchdog][:types]
|
|
76
69
|
end
|
|
77
70
|
|
|
78
71
|
def find_existing(_entity)
|