Class: Engram::UseCases::Recall
- Inherits:
-
Object
- Object
- Engram::UseCases::Recall
- Defined in:
- lib/engram/use_cases/recall.rb
Overview
Embed a query and fetch the most relevant memories for a scope.
By default this is pure vector similarity (the store's own ordering). When importance_weight or recency_weight are non-zero, it fetches a larger candidate pool and re-ranks by a composite score: similarity + importance + recency. With both weights at zero (the default) behaviour is identical to plain similarity search.
Constant Summary collapse
- DEFAULT_HALFLIFE =
30 days, in seconds
30 * 24 * 60 * 60
- DEFAULT_POOL_FACTOR =
4
Instance Method Summary collapse
-
#call(query, scope:, limit: Engram.config.default_limit, kinds: nil) ⇒ Object
Returns Array
, most relevant first. -
#initialize(store:, embedder:, importance_weight: 0.0, recency_weight: 0.0, recency_halflife: DEFAULT_HALFLIFE, pool_factor: DEFAULT_POOL_FACTOR, touch: false) ⇒ Recall
constructor
A new instance of Recall.
Constructor Details
#initialize(store:, embedder:, importance_weight: 0.0, recency_weight: 0.0, recency_halflife: DEFAULT_HALFLIFE, pool_factor: DEFAULT_POOL_FACTOR, touch: false) ⇒ Recall
Returns a new instance of Recall.
15 16 17 18 19 20 21 22 23 24 |
# File 'lib/engram/use_cases/recall.rb', line 15 def initialize(store:, embedder:, importance_weight: 0.0, recency_weight: 0.0, recency_halflife: DEFAULT_HALFLIFE, pool_factor: DEFAULT_POOL_FACTOR, touch: false) @store = store @embedder = @importance_weight = importance_weight.to_f @recency_weight = recency_weight.to_f @recency_halflife = recency_halflife.to_f @pool_factor = pool_factor @touch = touch end |
Instance Method Details
#call(query, scope:, limit: Engram.config.default_limit, kinds: nil) ⇒ Object
Returns Array
27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/engram/use_cases/recall.rb', line 27 def call(query, scope:, limit: Engram.config.default_limit, kinds: nil) raise ArgumentError, "query must be a non-empty string" if query.to_s.strip.empty? payload = Engram::Instrumentation.payload( scope: scope, store: @store, limit: limit, kinds: Array(kinds).map(&:to_s), reranking: reranking? ) Engram::Instrumentation.instrument("recall", payload) do = @embedder.(query) = Engram::EmbeddingMetadata.(@embedder, embedding: ) pool_limit = reranking? ? limit * @pool_factor : limit pool = Engram::EmbeddingMetadata.search( @store, embedding: , embedding_metadata: , scope: scope, limit: pool_limit, kinds: kinds ) results = (reranking? ? rerank(pool, ) : pool).first(limit) touch(results, scope) if @touch payload[:result_count] = results.size payload[:candidate_count] = pool.size results end end |