Skip to content
This repository was archived by the owner on Jul 22, 2025. It is now read-only.

Commit 90bcb8b

Browse files
authored
DEV: Build sentiment clients outside of promises (#1117)
1 parent e52045e commit 90bcb8b

File tree

2 files changed

+39
-38
lines changed

2 files changed

+39
-38
lines changed

lib/inference/hugging_face_text_embeddings.rb

Lines changed: 12 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,6 @@ def initialize(endpoint, key, referer = Discourse.base_url)
1212
attr_reader :endpoint, :key, :referer
1313

1414
class << self
15-
def configured?
16-
SiteSetting.ai_hugging_face_tei_endpoint.present? ||
17-
SiteSetting.ai_hugging_face_tei_endpoint_srv.present?
18-
end
19-
2015
def reranker_configured?
2116
SiteSetting.ai_hugging_face_tei_reranker_endpoint.present? ||
2217
SiteSetting.ai_hugging_face_tei_reranker_endpoint_srv.present?
@@ -50,32 +45,23 @@ def rerank(content, candidates)
5045

5146
JSON.parse(response.body, symbolize_names: true)
5247
end
48+
end
5349

54-
def classify(content, model_config, base_url = Discourse.base_url)
55-
headers = { "Referer" => base_url, "Content-Type" => "application/json" }
56-
headers["X-API-KEY"] = model_config.api_key
57-
headers["Authorization"] = "Bearer #{model_config.api_key}"
58-
59-
body = { inputs: content, truncate: true }.to_json
60-
61-
api_endpoint = model_config.endpoint
62-
if api_endpoint.present? && api_endpoint.start_with?("srv://")
63-
service = DiscourseAi::Utils::DnsSrv.lookup(api_endpoint.delete_prefix("srv://"))
64-
api_endpoint = "https://#{service.target}:#{service.port}"
65-
end
50+
def classify_by_sentiment!(content)
51+
response = do_request!(content)
6652

67-
conn = Faraday.new { |f| f.adapter FinalDestination::FaradayAdapter }
68-
response = conn.post(api_endpoint, body, headers)
53+
JSON.parse(response.body, symbolize_names: true)
54+
end
6955

70-
if response.status != 200
71-
raise Net::HTTPBadResponse.new("Status: #{response.status}\n\n#{response.body}")
72-
end
56+
def perform!(content)
57+
response = do_request!(content)
7358

74-
JSON.parse(response.body, symbolize_names: true)
75-
end
59+
JSON.parse(response.body, symbolize_names: true).first
7660
end
7761

78-
def perform!(content)
62+
private
63+
64+
def do_request!(content)
7965
headers = { "Referer" => referer, "Content-Type" => "application/json" }
8066
body = { inputs: content, truncate: true }.to_json
8167

@@ -89,7 +75,7 @@ def perform!(content)
8975

9076
raise Net::HTTPBadResponse.new(response.body.to_s) if ![200].include?(response.status)
9177

92-
JSON.parse(response.body, symbolize_names: true).first
78+
response
9379
end
9480
end
9581
end

lib/sentiment/post_classification.rb

Lines changed: 27 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,6 @@ def bulk_classify!(relation)
5555

5656
available_classifiers = classifiers
5757
return if available_classifiers.blank?
58-
base_url = Discourse.base_url
5958

6059
promised_classifications =
6160
relation
@@ -70,12 +69,14 @@ def bulk_classify!(relation)
7069
already_classified = w_text[:target].sentiment_classifications.map(&:model_used)
7170

7271
classifiers_for_target =
73-
available_classifiers.reject { |ac| already_classified.include?(ac.model_name) }
72+
available_classifiers.reject do |ac|
73+
already_classified.include?(ac[:model_name])
74+
end
7475

7576
promised_target_results =
76-
classifiers_for_target.map do |c|
77+
classifiers_for_target.map do |cft|
7778
Concurrent::Promises.future_on(pool) do
78-
results[c.model_name] = request_with(w_text[:text], c, base_url)
79+
results[cft[:model_name]] = request_with(cft[:client], w_text[:text])
7980
end
8081
end
8182

@@ -98,26 +99,40 @@ def bulk_classify!(relation)
9899

99100
def classify!(target)
100101
return if target.blank?
101-
return if classifiers.blank?
102+
available_classifiers = classifiers
103+
return if available_classifiers.blank?
102104

103105
to_classify = prepare_text(target)
104106
return if to_classify.blank?
105107

106108
already_classified = target.sentiment_classifications.map(&:model_used)
107109
classifiers_for_target =
108-
classifiers.reject { |ac| already_classified.include?(ac.model_name) }
110+
available_classifiers.reject { |ac| already_classified.include?(ac[:model_name]) }
109111

110112
results =
111-
classifiers_for_target.reduce({}) do |memo, model|
112-
memo[model.model_name] = request_with(to_classify, model)
113+
classifiers_for_target.reduce({}) do |memo, cft|
114+
memo[cft[:model_name]] = request_with(cft[:client], to_classify)
113115
memo
114116
end
115117

116118
store_classification(target, results)
117119
end
118120

119121
def classifiers
120-
DiscourseAi::Sentiment::SentimentSiteSettingJsonSchema.values
122+
DiscourseAi::Sentiment::SentimentSiteSettingJsonSchema.values.map do |config|
123+
api_endpoint = config.endpoint
124+
125+
if api_endpoint.present? && api_endpoint.start_with?("srv://")
126+
service = DiscourseAi::Utils::DnsSrv.lookup(api_endpoint.delete_prefix("srv://"))
127+
api_endpoint = "https://#{service.target}:#{service.port}"
128+
end
129+
130+
{
131+
model_name: config.model_name,
132+
client:
133+
DiscourseAi::Inference::HuggingFaceTextEmbeddings.new(api_endpoint, config.api_key),
134+
}
135+
end
121136
end
122137

123138
def has_classifiers?
@@ -137,9 +152,9 @@ def prepare_text(target)
137152
Tokenizer::BertTokenizer.truncate(content, 512)
138153
end
139154

140-
def request_with(content, config, base_url = Discourse.base_url)
141-
result =
142-
DiscourseAi::Inference::HuggingFaceTextEmbeddings.classify(content, config, base_url)
155+
def request_with(client, content)
156+
result = client.classify_by_sentiment!(content)
157+
143158
transform_result(result)
144159
end
145160

0 commit comments

Comments
 (0)