Class: Forem::Services::ConceptService

Inherits:
BaseService show all
Defined in:
lib/forem/services/concept_service.rb

Overview

Service for interacting with the Forem Concepts API.

Concepts are semantic, ML-generated categories: articles are classified under a concept when their embedding is close enough to the concept's anchor embedding. This service covers the public concept endpoints (+/api/concepts+); creating and deleting concepts is an admin-only operation exposed by AdminConceptService.

Access via Client#concepts. All methods inject the client's requestor automatically so no additional configuration is required.

Examples:

client = Forem::Client.new("your-api-key")
concepts = client.concepts.list(days: 30)
concept  = client.concepts.retrieve(concepts.first.id)
concept.daily_metrics.first.articles_count

See Also:

Instance Method Summary collapse

Methods inherited from BaseService

#initialize

Constructor Details

This class inherits a constructor from Forem::Services::BaseService

Instance Method Details

#articles(id, params = {}, opts = {}) ⇒ Forem::ListObject<Forem::Article>

List the published articles classified under a concept.

Articles are ordered by semantic distance (closest first) with the article score as a tiebreaker, unless sort is "score".

Examples:

client.concepts.articles(7, sort: "score", per_page: 25)

Parameters:

  • id (Integer, String)

    the concept ID

  • params (Hash) (defaults to: {})

    query parameters

  • opts (Hash) (defaults to: {})

    per-request options

Options Hash (params):

  • :sort (String)

    "score" to sort by article score; otherwise sorted by semantic distance

  • :page (Integer)

    page number (default: 1)

  • :per_page (Integer)

    number of results per page (default: 10)

Returns:

See Also:



114
115
116
# File 'lib/forem/services/concept_service.rb', line 114

def articles(id, params = {}, opts = {})
  Concept.articles(id, params, opts_with_requestor(opts))
end

#list(params = {}, opts = {}) ⇒ Forem::ListObject<Concept>

List the concepts accessible to the authenticated user.

Super admins see every concept; other users see only the concepts they have been granted access to. Each concept includes nested daily_metrics covering the last days days, newest first.

Examples:

client.concepts.list(per_page: 20, days: 30)

Parameters:

  • params (Hash) (defaults to: {})

    query parameters

  • opts (Hash) (defaults to: {})

    per-request options

Options Hash (params):

  • :page (Integer)

    page number (default: 1)

  • :per_page (Integer)

    number of results per page (default: 50, max: 100)

  • :days (Integer)

    number of days of activity to include in daily_metrics (default: 7, minimum: 1)

Returns:

See Also:



42
43
44
# File 'lib/forem/services/concept_service.rb', line 42

def list(params = {}, opts = {})
  Concept.list(params, opts_with_requestor(opts))
end

#retrieve(id, params = {}, opts = {}) ⇒ Concept

Retrieve a single concept by its numeric ID.

The response includes nested daily_metrics for the last days days and a top_articles array with the concept's three highest-scoring articles.

Examples:

concept = client.concepts.retrieve(7)
concept.daily_metrics.map(&:popularity_score)

Parameters:

  • id (Integer, String)

    the concept ID

  • params (Hash) (defaults to: {})

    query parameters

  • opts (Hash) (defaults to: {})

    per-request options

Options Hash (params):

  • :days (Integer)

    number of days of activity to include in daily_metrics (default: 7, minimum: 1)

Returns:

  • (Concept)

    the concept with the given ID

See Also:



64
65
66
# File 'lib/forem/services/concept_service.rb', line 64

def retrieve(id, params = {}, opts = {})
  Concept.retrieve(id, params, opts_with_requestor(opts))
end

#search(params = {}, opts = {}) ⇒ Array<Concept>

Semantically search the concepts accessible to the caller.

The query is embedded and compared against each concept's anchor embedding. Results come back closest-first, each with distance and similarity alongside the usual concept fields. This endpoint requires an API key and is not paginated.

Examples:

client.concepts.search(q: "vector databases", per_page: 5)

Parameters:

  • params (Hash) (defaults to: {})

    query parameters

  • opts (Hash) (defaults to: {})

    per-request options

Options Hash (params):

  • :q (String) — default: required

    the search text

  • :per_page (Integer)

    number of concepts to return (default: 10, max: 50)

  • :threshold (Float)

    optional maximum cosine distance (0.0–2.0) for a concept to be included

Returns:

  • (Array<Concept>)

    matching concepts, closest first

See Also:



138
139
140
# File 'lib/forem/services/concept_service.rb', line 138

def search(params = {}, opts = {})
  Concept.search(params, opts_with_requestor(opts))
end

#update(id, params = {}, opts = {}) ⇒ Concept

Update an existing concept.

Params are wrapped in the concept key expected by the API, so they can be passed flat. Only score, description, and similarity_threshold are permitted. Updating the description regenerates the concept's anchor embedding; updating the description or the similarity threshold re-classifies existing articles in the background.

Examples:

client.concepts.update(7, description: "Storage engines", score: 4.5)

Parameters:

  • id (Integer, String)

    the concept ID to update

  • params (Hash) (defaults to: {})

    concept attributes to change

  • opts (Hash) (defaults to: {})

    per-request options

Options Hash (params):

  • :score (Float)

    new curation score

  • :description (String)

    new semantic description used to regenerate the anchor embedding

  • :similarity_threshold (Float)

    new cosine distance threshold (0.0–1.0)

Returns:

  • (Concept)

    the updated concept

See Also:



91
92
93
# File 'lib/forem/services/concept_service.rb', line 91

def update(id, params = {}, opts = {})
  Concept.update(id, params, opts_with_requestor(opts))
end