Class: Forem::Concept
- Inherits:
-
APIResource
- Object
- ForemObject
- APIResource
- Forem::Concept
- Extended by:
- APIOperations::List, APIOperations::Update
- Defined in:
- lib/forem/resources/concept.rb
Overview
Represents a Forem concept (a semantic, ML-generated tag).
Concepts are semantic categories derived from article embeddings rather
than from explicit user tags: each concept carries an anchor embedding
generated from its description, and articles whose embeddings fall
within the concept's similarity_threshold are classified under it.
They are used for advanced semantic categorization, automated feeds, and
interest mapping.
The public concepts endpoints are readable by any authenticated user (a
super admin sees every concept, other users see the concepts they have
been granted access to). Creating and deleting concepts is an admin-only
operation exposed separately under /api/admin/concepts.
Available operations (via mixins):
- +List+ — GET /api/concepts
- +Update+ — PUT /api/concepts/:id
Custom class methods:
- +retrieve+ — GET /api/concepts/:id
- +articles+ — GET /api/concepts/:id/articles
- +search+ — GET /api/concepts/search
Concept Fields
id(Integer) — Unique concept IDname(String) — Human readable label for the conceptslug(String) — URL-friendly identifierdescription(String, nullable) — Semantic definition used to generate the concept's anchor embeddingparent_id(Integer, nullable) — Parent concept when using a hierarchyscore(Float) — Concept popularity / curation scoresimilarity_threshold(Float, nullable) — Cosine distance threshold (0.0–1.0) an article embedding must satisfy to be classified under the conceptcreated_at/updated_at(String) — ISO 8601 timestampsdaily_metrics(Array) — Nested per-day activity rollups, newest first. Each entry hasdate,articles_count,comments_count,page_views,reactions_count, andpopularity_scoretop_articles(Array) — Only onretrieve/updateresponses; the three highest-scoring articles for the concept, each withid,title,slug,score, andpublished_at
Results from Concept.search carry two extra fields: distance (cosine distance
from the query embedding) and similarity (+1.0 - distance+).
Constant Summary collapse
- OBJECT_NAME =
"concept"- RESOURCE_PATH =
"/api/concepts"
Instance Attribute Summary
Attributes inherited from ForemObject
Class Method Summary collapse
-
.articles(id, params = {}, opts = {}) ⇒ Forem::ListObject<Forem::Article>
Return the published articles classified under a concept.
-
.retrieve(id, params = {}, opts = {}) ⇒ Forem::Concept
Retrieve a single concept by its numeric ID.
-
.search(params = {}, opts = {}) ⇒ Array<Forem::Concept>
Semantically search the concepts accessible to the caller.
-
.update(id, params = {}, opts = {}) ⇒ Forem::Concept
Update an existing concept.
Methods included from APIOperations::List
Methods included from APIOperations::Update
Methods inherited from APIResource
#refresh, resource_path, #resource_url
Methods inherited from ForemObject
#==, #[], #[]=, construct_from, cursor_list, #initialize, #inspect, #method_missing, paginated_list, #respond_to_missing?, #to_hash
Methods included from APIOperations::Request
Constructor Details
This class inherits a constructor from Forem::ForemObject
Dynamic Method Handling
This class handles dynamic methods through the method_missing method in the class Forem::ForemObject
Class Method Details
.articles(id, params = {}, opts = {}) ⇒ Forem::ListObject<Forem::Article>
Return the published articles classified under a concept.
Sends a GET request to /api/concepts/:id/articles. Articles are
ordered by cosine similarity to the concept (closest first), with the
article score as a tiebreaker, unless sort is "score" in which case
they are ordered by article score alone.
147 148 149 |
# File 'lib/forem/resources/concept.rb', line 147 def self.articles(id, params = {}, opts = {}) Forem::Article.paginated_list("#{resource_path}/#{id}/articles", params, opts) end |
.retrieve(id, params = {}, opts = {}) ⇒ Forem::Concept
Retrieve a single concept by its numeric ID.
Sends a GET request to /api/concepts/:id. Unlike the standard
APIOperations::Retrieve mixin this accepts query params, because the
endpoint takes a days window that controls how many nested
daily_metrics entries are returned.
93 94 95 96 97 |
# File 'lib/forem/resources/concept.rb', line 93 def self.retrieve(id, params = {}, opts = {}) requestor = opts[:requestor] resp = request(:get, "#{resource_path}/#{id}", params, opts) construct_from(resp.parsed_body, requestor: requestor) end |
.search(params = {}, opts = {}) ⇒ Array<Forem::Concept>
Semantically search the concepts accessible to the caller.
Sends a GET request to /api/concepts/search. The query text is
embedded and compared against each concept's anchor embedding; results
are returned closest-first and are not paginated (only the number of
results is configurable). Each returned concept carries distance and
similarity in addition to the usual concept fields.
Requires an API key — unlike the other concept endpoints, this action cannot be called with a session user.
174 175 176 177 178 |
# File 'lib/forem/resources/concept.rb', line 174 def self.search(params = {}, opts = {}) requestor = opts[:requestor] resp = request(:get, "#{resource_path}/search", params, opts) (resp.parsed_body || []).map { |item| construct_from(item, requestor: requestor) } end |
.update(id, params = {}, opts = {}) ⇒ Forem::Concept
Update an existing concept.
Sends a PUT request to /api/concepts/:id. The Forem API expects the
attributes to be nested under a concept key, so flat params are
wrapped automatically; already-wrapped params are passed through
untouched.
Only score, description, and similarity_threshold are permitted
by the API. Changing the description regenerates the concept's anchor
embedding, and changing either the description or the similarity
threshold enqueues a background re-classification of existing articles.
122 123 124 |
# File 'lib/forem/resources/concept.rb', line 122 def self.update(id, params = {}, opts = {}) super(id, wrap_params(params), opts) end |