Skip to content

add query-time pooling for flexMF - #1201

Merged
mdekstrand merged 4 commits into
lenskit:mainfrom
samiravaez:flexmf/pooling
Sep 4, 2026
Merged

mdekstrand merged 4 commits into
lenskit:mainfrom
samiravaez:flexmf/pooling

Conversation

@samiravaez

Copy link
Copy Markdown
Contributor

This PR resolves #934 by adding responsive recommendations to FlexMF.
FlexMF can now build a temporary user representation at scoring time by mean-pooling the embeddings of the items in RecQuery.query_items. This allows recommendations to be generated from query context even when there is no trained user embedding available.
Unknown query items are ignored, and if pooling cannot produce a usable vector, the model falls back to the trained user embedding when allowed. Explicit model scoring also preserves the global bias when using the pooled-user path

Comment thread src/lenskit/flexmf/_base.py Outdated
and (u_row is None or self.config.user_embeddings != "prefer")
)

pooled_user = None

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can just reuse the u_tensor, can't we? That will also enable making the if on line 172 simpler.

Comment thread src/lenskit/flexmf/_base.py Outdated
pooled_user = q_vectors.mean(dim=0)

# if pooling was not possible, fall back to the trained user embedding
if pooled_user is None and (u_tensor is None or not self.config.user_embeddings):

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we reuse u_tensor above, then this can just be if u_tensor is None. I.e., the logic becomes "there are several ways to get u_tensor, if we've tried all of them and not gotten a u_tensor, then we can't score".

It is possible that this will also fix the test failure — I'm not sure if all of the if logic in this method is correct yet, partly because it seems more complicated than it needs to be.

Comment thread src/lenskit/flexmf/_base.py Outdated
"""
Score items against a user embedding.
"""
return self.model.score_user_vector(user, items)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure why we need a new function here - isn't the final result of pooling just a user embedding, like any other? That was the intention with the issue. (Whether it is a good user embedding is another question.)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what the user bias should be for the pooled embedding if I use the same scoring function?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User bias is an important and subtle question here, and it might actually be different for explicit and implicit feedback models.

For implicit-feedback models, using 0 as the fresh user bias is probably fine. It might miscalibrate probabilities, but won't affect ranking.

For explicit-feedback models, I think we have 3 choices:

  • use 0
  • use saved user bias, even if we aren't using saved user embedding
  • estimate user bias from rating values before computing the pooled embedding

@codecov

codecov Bot commented Sep 2, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.67442% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 90.42%. Comparing base (34c81c5) to head (b038f74).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
src/lenskit/flexmf/_model.py 91.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #1201      +/-   ##
==========================================
+ Coverage   90.40%   90.42%   +0.01%     
==========================================
  Files         263      263              
  Lines       17516    17558      +42     
==========================================
+ Hits        15836    15877      +41     
- Misses       1680     1681       +1     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@mdekstrand
mdekstrand merged commit 396c743 into lenskit:main Sep 4, 2026
43 checks passed
@mdekstrand mdekstrand added this to the 2026.4 milestone Sep 4, 2026
@mdekstrand mdekstrand added the flexmf Issues and changes for the FlexMF recommendation component. label Sep 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flexmf Issues and changes for the FlexMF recommendation component.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support pooling-based implicit FlexMF

2 participants