Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
62 commits
Select commit Hold shift + click to select a range
7ec22e3
Fixed default value for FieldValueFeature
aruggero May 14, 2025
70ecde1
Fixed remaining tests
aruggero May 14, 2025
0786577
Removed default from schema
aruggero May 15, 2025
193908d
Added rerankingFeatureVectorCache and loggingFeatureVectorCache
aruggero Jun 10, 2025
f4e7ba7
Fixed default value for FieldValueFeature
aruggero May 14, 2025
8330a9d
Fixed remaining tests
aruggero May 14, 2025
3ac57b2
Removed default from schema
aruggero May 15, 2025
996ecdb
Implemented first cache lookup without ltr
aruggero Jun 25, 2025
c14d4ee
Starting integrating cache for logging
aruggero Jun 27, 2025
cac0ce2
Implemented caching for both logging and reranking. Still to be check…
aruggero Jun 27, 2025
5f5c0f1
Fixed efi when doing both reranking and logging
aruggero Jul 11, 2025
fa5ce79
Fixed efi when doing both reranking and logging. First implementation…
aruggero Jul 11, 2025
ac4507d
WORKING VERSION WITH 2 CACHES
aruggero Jul 14, 2025
abf6706
Unique cache for feature vector
aruggero Jul 14, 2025
0ba0664
Added first tests
aruggero Jul 14, 2025
5606e75
Fixed some tests
aruggero Jul 14, 2025
ec3b99a
Added tests and condition to LTRScoringQuery for considering logAll p…
aruggero Jul 15, 2025
b0f29d3
Tested score
aruggero Jul 15, 2025
d38b351
Gradlew tidy
aruggero Jul 23, 2025
c1bc8f4
Changed documentation with new cache configuration
aruggero Jul 24, 2025
6b1ae55
Removed changed idendation
aruggero Jul 28, 2025
ccca6d4
Small refactors for variable and methods names
aruggero Jul 31, 2025
672e514
First attempt to create a dedicated FeatureExtractor class
aruggero Jul 31, 2025
e883ef4
Changed implementation for getting DocID for feature vectore cache an…
aruggero Aug 5, 2025
318d2b0
Second version of code refactoring to move extraction part in the Fea…
aruggero Aug 5, 2025
0088ca9
Refactoring of the code
aruggero Aug 5, 2025
eaa4190
Gradlew tidy
aruggero Aug 5, 2025
b2b19bf
Added missing dependency
aruggero Aug 5, 2025
3bb752b
Updated sample_techproducts_configs solrconfig
aruggero Aug 11, 2025
62a51fa
Small changes after merge with Lucene 10
aruggero Aug 11, 2025
46877f6
Gradlew tidy and small typos
aruggero Sep 15, 2025
1b590ce
Refactored LTRScoringQuery to create feature extractors within scorer…
aruggero Sep 15, 2025
2eb15fe
Inserted docs into a list for tests
aruggero Sep 15, 2025
8cb6cb6
Removed unuseful comment
aruggero Sep 15, 2025
bfd2f7e
Typos
aruggero Sep 15, 2025
dd8042d
Better test names
aruggero Sep 15, 2025
a4c7431
Gradlew tidy
aruggero Sep 15, 2025
074ef41
Moved feature extraction into a dedicated package
aruggero Sep 17, 2025
0a432f1
First attempt to move scorer outside LTRScoringQuery
aruggero Sep 17, 2025
e6c50a5
Moved scorer outside ltrscoringquery
aruggero Sep 22, 2025
1857b26
Gradlew widy
aruggero Sep 22, 2025
0d8f3e7
Added package-info and did gradle tidy
aruggero Sep 22, 2025
c1458b7
Changed package info
aruggero Sep 23, 2025
03aeabb
Attempt to fix docID with dedicated targetDoc
aruggero Oct 3, 2025
4d35329
Trying to set the correct doc id
aruggero Oct 3, 2025
af1990b
added missing solrDocID set
aruggero Oct 3, 2025
6b62ba7
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 14, 2025
2a46745
Moved docId for cache key to DocInfo
aruggero Oct 14, 2025
b1c8c98
Changed name variable in Interleaving
aruggero Oct 15, 2025
7d33e2d
Added disclaimer about Lucene doc IDs to the LTR reference page
aruggero Oct 15, 2025
4b4b07e
Gradlew tidy
aruggero Oct 15, 2025
ba4b4be
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 15, 2025
802c3ff
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 15, 2025
df09ef1
Added element to ltr gradle for metrics testing
aruggero Oct 15, 2025
d73f0c7
Fixed CHANGES.txt and adjust reference guide
aruggero Oct 15, 2025
7607357
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 17, 2025
f8bf5a8
Adapted to new cache metrics access + tidy
aruggero Oct 17, 2025
0ae7470
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 17, 2025
142b7f9
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 20, 2025
89279bb
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 20, 2025
7fd7590
Merge remote-tracking branch 'refs/remotes/upstream/main' into featur…
aruggero Oct 21, 2025
11075ce
Fixed typo
aruggero Oct 21, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion solr/CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ New Features

* SOLR-17813: Add support for SeededKnnVectorQuery (Ilaria Petreti via Alessandro Benedetti)

* SOLR-16667: LTR Add feature vector caching for ranking. (Anna Ruggero, Alessandro Benedetti)

Improvements
---------------------

Expand Down Expand Up @@ -572,7 +574,7 @@ Bug Fixes

* SOLR-17726: MoreLikeThis to support copy-fields (Ilaria Petreti via Alessandro Benedetti)

* SOLR-16667: Fixed dense/sparse representation in LTR module. (Anna Ruggero, Alessandro Benedetti)
* SOLR-17760: Fixed dense/sparse representation in LTR module. (Anna Ruggero, Alessandro Benedetti)

* SOLR-17800: Security Manager should handle symlink on /tmp (Kevin Risden)

Expand Down
11 changes: 10 additions & 1 deletion solr/core/src/java/org/apache/solr/core/SolrConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -301,6 +301,9 @@ private SolrConfig(SolrResourceLoader loader, String name, Properties substituta
queryResultCacheConfig =
CacheConfig.getConfig(
this, get("query").get("queryResultCache"), "query/queryResultCache");
featureVectorCacheConfig =
CacheConfig.getConfig(
this, get("query").get("featureVectorCache"), "query/featureVectorCache");
documentCacheConfig =
CacheConfig.getConfig(this, get("query").get("documentCache"), "query/documentCache");
CacheConfig conf =
Expand Down Expand Up @@ -662,6 +665,7 @@ public SolrRequestParsers getRequestParsers() {
public final CacheConfig queryResultCacheConfig;
public final CacheConfig documentCacheConfig;
public final CacheConfig fieldValueCacheConfig;
public final CacheConfig featureVectorCacheConfig;
public final Map<String, CacheConfig> userCacheConfigs;
// SolrIndexSearcher - more...
public final boolean useFilterForSortedQuery;
Expand Down Expand Up @@ -998,7 +1002,12 @@ public Map<String, Object> toMap(Map<String, Object> result) {
}

addCacheConfig(
m, filterCacheConfig, queryResultCacheConfig, documentCacheConfig, fieldValueCacheConfig);
m,
filterCacheConfig,
queryResultCacheConfig,
documentCacheConfig,
fieldValueCacheConfig,
featureVectorCacheConfig);
m = new LinkedHashMap<>();
result.put("requestDispatcher", m);
if (httpCachingConfig != null) m.put("httpCaching", httpCachingConfig);
Expand Down
11 changes: 11 additions & 0 deletions solr/core/src/java/org/apache/solr/search/SolrIndexSearcher.java
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@ public class SolrIndexSearcher extends IndexSearcher implements Closeable, SolrI
private final SolrCache<Query, DocSet> filterCache;
private final SolrCache<QueryResultKey, DocList> queryResultCache;
private final SolrCache<String, UnInvertedField> fieldValueCache;
private final SolrCache<Integer, float[]> featureVectorCache;
private final LongAdder fullSortCount = new LongAdder();
private final LongAdder skipSortCount = new LongAdder();
private final LongAdder liveDocsNaiveCacheHitCount = new LongAdder();
Expand Down Expand Up @@ -448,6 +449,11 @@ public SolrIndexSearcher(
? null
: solrConfig.queryResultCacheConfig.newInstance();
if (queryResultCache != null) clist.add(queryResultCache);
featureVectorCache =
solrConfig.featureVectorCacheConfig == null
? null
: solrConfig.featureVectorCacheConfig.newInstance();
if (featureVectorCache != null) clist.add(featureVectorCache);
SolrCache<Integer, Document> documentCache = docFetcher.getDocumentCache();
if (documentCache != null) clist.add(documentCache);

Expand All @@ -469,6 +475,7 @@ public SolrIndexSearcher(
this.filterCache = null;
this.queryResultCache = null;
this.fieldValueCache = null;
this.featureVectorCache = null;
this.cacheMap = NO_GENERIC_CACHES;
this.cacheList = NO_CACHES;
}
Expand Down Expand Up @@ -689,6 +696,10 @@ public SolrCache<Query, DocSet> getFilterCache() {
return filterCache;
}

public SolrCache<Integer, float[]> getFeatureVectorCache() {
return featureVectorCache;
}

//
// Set default regenerators on filter and query caches if they don't have any
//
Expand Down
2 changes: 2 additions & 0 deletions solr/modules/ltr/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,8 @@ dependencies {
testImplementation libs.junit.junit
testImplementation libs.hamcrest.hamcrest

testImplementation libs.prometheus.metrics.model

testImplementation libs.commonsio.commonsio
}

Expand Down
2 changes: 1 addition & 1 deletion solr/modules/ltr/gradle.lockfile
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ io.opentelemetry:opentelemetry-sdk-metrics:1.53.0=jarValidation,runtimeClasspath
io.opentelemetry:opentelemetry-sdk-trace:1.53.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
io.opentelemetry:opentelemetry-sdk:1.53.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
io.prometheus:prometheus-metrics-exposition-formats:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
io.prometheus:prometheus-metrics-model:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
io.prometheus:prometheus-metrics-model:1.1.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
io.sgr:s2-geometry-library-java:1.0.0=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
io.swagger.core.v3:swagger-annotations-jakarta:2.2.22=compileClasspath,jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testCompileClasspath,testRuntimeClasspath
jakarta.annotation:jakarta.annotation-api:2.1.1=jarValidation,runtimeClasspath,runtimeLibs,solrPlatformLibs,testRuntimeClasspath
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,21 +23,20 @@ public class CSVFeatureLogger extends FeatureLogger {
private final char keyValueSep;
private final char featureSep;

public CSVFeatureLogger(String fvCacheName, FeatureFormat f, Boolean logAll) {
super(fvCacheName, f, logAll);
public CSVFeatureLogger(FeatureFormat f, Boolean logAll) {
super(f, logAll);
this.keyValueSep = DEFAULT_KEY_VALUE_SEPARATOR;
this.featureSep = DEFAULT_FEATURE_SEPARATOR;
}

public CSVFeatureLogger(
String fvCacheName, FeatureFormat f, Boolean logAll, char keyValueSep, char featureSep) {
super(fvCacheName, f, logAll);
public CSVFeatureLogger(FeatureFormat f, Boolean logAll, char keyValueSep, char featureSep) {
super(f, logAll);
this.keyValueSep = keyValueSep;
this.featureSep = featureSep;
}

@Override
public String makeFeatureVector(LTRScoringQuery.FeatureInfo[] featuresInfo) {
public String printFeatureVector(LTRScoringQuery.FeatureInfo[] featuresInfo) {
// Allocate the buffer to a size based on the number of features instead of the
// default 16. You need space for the name, value, and two separators per feature,
// but not all the features are expected to fire, so this is just a naive estimate.
Expand Down
10 changes: 10 additions & 0 deletions solr/modules/ltr/src/java/org/apache/solr/ltr/DocInfo.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public class DocInfo extends HashMap<String, Object> {

// Name of key used to store the original score of a doc
private static final String ORIGINAL_DOC_SCORE = "ORIGINAL_DOC_SCORE";
// Name of key used to store the original id of a doc
private static final String ORIGINAL_DOC_ID = "ORIGINAL_DOC_ID";

public DocInfo() {
super();
Expand All @@ -38,4 +40,12 @@ public Float getOriginalDocScore() {
public boolean hasOriginalDocScore() {
return containsKey(ORIGINAL_DOC_SCORE);
}

public void setOriginalDocId(int docId) {
put(ORIGINAL_DOC_ID, docId);
}

public int getOriginalDocId() {
return (int) get(ORIGINAL_DOC_ID);
}
}
63 changes: 13 additions & 50 deletions solr/modules/ltr/src/java/org/apache/solr/ltr/FeatureLogger.java
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,10 @@
*/
package org.apache.solr.ltr;

import org.apache.solr.search.SolrIndexSearcher;

/**
* FeatureLogger can be registered in a model and provide a strategy for logging the feature values.
*/
public abstract class FeatureLogger {

/** the name of the cache using for storing the feature value */
private final String fvCacheName;

public enum FeatureFormat {
DENSE,
SPARSE
Expand All @@ -35,54 +29,15 @@ public enum FeatureFormat {

protected Boolean logAll;

protected FeatureLogger(String fvCacheName, FeatureFormat f, Boolean logAll) {
this.fvCacheName = fvCacheName;
protected boolean logFeatures;

protected FeatureLogger(FeatureFormat f, Boolean logAll) {
this.featureFormat = f;
this.logAll = logAll;
this.logFeatures = false;
}

/**
* Log will be called every time that the model generates the feature values for a document and a
* query.
*
* @param docid Solr document id whose features we are saving
* @param featuresInfo List of all the {@link LTRScoringQuery.FeatureInfo} objects which contain
* name and value for all the features triggered by the result set
* @return true if the logger successfully logged the features, false otherwise.
*/
public boolean log(
int docid,
LTRScoringQuery scoringQuery,
SolrIndexSearcher searcher,
LTRScoringQuery.FeatureInfo[] featuresInfo) {
final String featureVector = makeFeatureVector(featuresInfo);
if (featureVector == null) {
return false;
}

if (null == searcher.cacheInsert(fvCacheName, fvCacheKey(scoringQuery, docid), featureVector)) {
return false;
}

return true;
}

public abstract String makeFeatureVector(LTRScoringQuery.FeatureInfo[] featuresInfo);

private static int fvCacheKey(LTRScoringQuery scoringQuery, int docid) {
return scoringQuery.hashCode() + (31 * docid);
}

/**
* populate the document with its feature vector
*
* @param docid Solr document id
* @return String representation of the list of features calculated for docid
*/
public String getFeatureVector(
int docid, LTRScoringQuery scoringQuery, SolrIndexSearcher searcher) {
return (String) searcher.cacheLookup(fvCacheName, fvCacheKey(scoringQuery, docid));
}
public abstract String printFeatureVector(LTRScoringQuery.FeatureInfo[] featuresInfo);

public Boolean isLoggingAll() {
return logAll;
Expand All @@ -91,4 +46,12 @@ public Boolean isLoggingAll() {
public void setLogAll(Boolean logAll) {
this.logAll = logAll;
}

public void setLogFeatures(boolean logFeatures) {
this.logFeatures = logFeatures;
}

public boolean isLogFeatures() {
return logFeatures;
}
}
Loading
Loading