opensolr-haystack 0.2.8__tar.gz → 0.3.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/PKG-INFO +28 -1
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/README.md +27 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/haystack_integrations/components/retrievers/opensolr/retriever.py +17 -1
- opensolr_haystack-0.3.0/haystack_integrations/document_stores/opensolr/client.py +895 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/haystack_integrations/document_stores/opensolr/store.py +43 -3
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/opensolr_haystack.egg-info/PKG-INFO +28 -1
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/pyproject.toml +1 -1
- opensolr_haystack-0.2.8/haystack_integrations/document_stores/opensolr/client.py +0 -469
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/LICENSE +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/haystack_integrations/components/retrievers/opensolr/__init__.py +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/haystack_integrations/document_stores/opensolr/__init__.py +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/opensolr_haystack.egg-info/SOURCES.txt +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/opensolr_haystack.egg-info/dependency_links.txt +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/opensolr_haystack.egg-info/requires.txt +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/opensolr_haystack.egg-info/top_level.txt +0 -0
- {opensolr_haystack-0.2.8 → opensolr_haystack-0.3.0}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensolr-haystack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.3.0
|
|
4
4
|
Summary: Haystack integration for Opensolr — managed Apache Solr DocumentStore with server-side embeddings and hybrid BM25+kNN retrieval
|
|
5
5
|
Author-email: Opensolr <support@opensolr.com>
|
|
6
6
|
License: MIT
|
|
@@ -157,6 +157,33 @@ tuning={"search_mode": "keywords_required", "fw_title": 0.2,
|
|
|
157
157
|
Defaults match the platform's PHP configuration exactly — customize in the
|
|
158
158
|
Control Panel once, or per call from code.
|
|
159
159
|
|
|
160
|
+
#### Fresh Results Bias
|
|
161
|
+
|
|
162
|
+
Rank newer documents higher without hiding anything older. Every score is
|
|
163
|
+
multiplied by a recency curve on `creation_date` — full weight for a document
|
|
164
|
+
published today, about half after a year:
|
|
165
|
+
|
|
166
|
+
```python
|
|
167
|
+
store.similarity_search_with_score("solar inverter warranty", fresh_bias=True)
|
|
168
|
+
client.hybrid_search(index, query, fresh_bias=True)
|
|
169
|
+
client.ai_answer(index, question, tuning={"fresh_bias": 1})
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
It **re-orders and never filters**: the hit count is identical either way,
|
|
173
|
+
nothing old becomes unreachable, and a document with no `creation_date` simply
|
|
174
|
+
keeps its place instead of being pushed to the bottom. It applies to all three
|
|
175
|
+
retrieval shapes — vector-only, keyword-only and the fused hybrid ranking —
|
|
176
|
+
because the boost wraps the final score rather than one half of it. Off by
|
|
177
|
+
default.
|
|
178
|
+
|
|
179
|
+
This is the same control visitors get as the **Fresh** toggle beside the sort
|
|
180
|
+
options on the hosted Opensolr search page, so a query behaves identically here
|
|
181
|
+
and there.
|
|
182
|
+
|
|
183
|
+
> `fresh_bias` and `freshness_boost` are two different knobs and the names
|
|
184
|
+
> invite confusion. `freshness_boost` is a hard window in **days** — anything
|
|
185
|
+
> older is filtered out and the hit count drops. `fresh_bias` filters nothing.
|
|
186
|
+
|
|
160
187
|
## How it's tested
|
|
161
188
|
|
|
162
189
|
Every release is validated against **live Opensolr infrastructure** — no mocks:
|
|
@@ -139,6 +139,33 @@ tuning={"search_mode": "keywords_required", "fw_title": 0.2,
|
|
|
139
139
|
Defaults match the platform's PHP configuration exactly — customize in the
|
|
140
140
|
Control Panel once, or per call from code.
|
|
141
141
|
|
|
142
|
+
#### Fresh Results Bias
|
|
143
|
+
|
|
144
|
+
Rank newer documents higher without hiding anything older. Every score is
|
|
145
|
+
multiplied by a recency curve on `creation_date` — full weight for a document
|
|
146
|
+
published today, about half after a year:
|
|
147
|
+
|
|
148
|
+
```python
|
|
149
|
+
store.similarity_search_with_score("solar inverter warranty", fresh_bias=True)
|
|
150
|
+
client.hybrid_search(index, query, fresh_bias=True)
|
|
151
|
+
client.ai_answer(index, question, tuning={"fresh_bias": 1})
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
It **re-orders and never filters**: the hit count is identical either way,
|
|
155
|
+
nothing old becomes unreachable, and a document with no `creation_date` simply
|
|
156
|
+
keeps its place instead of being pushed to the bottom. It applies to all three
|
|
157
|
+
retrieval shapes — vector-only, keyword-only and the fused hybrid ranking —
|
|
158
|
+
because the boost wraps the final score rather than one half of it. Off by
|
|
159
|
+
default.
|
|
160
|
+
|
|
161
|
+
This is the same control visitors get as the **Fresh** toggle beside the sort
|
|
162
|
+
options on the hosted Opensolr search page, so a query behaves identically here
|
|
163
|
+
and there.
|
|
164
|
+
|
|
165
|
+
> `fresh_bias` and `freshness_boost` are two different knobs and the names
|
|
166
|
+
> invite confusion. `freshness_boost` is a hard window in **days** — anything
|
|
167
|
+
> older is filtered out and the hit count drops. `fresh_bias` filters nothing.
|
|
168
|
+
|
|
142
169
|
## How it's tested
|
|
143
170
|
|
|
144
171
|
Every release is validated against **live Opensolr infrastructure** — no mocks:
|
|
@@ -38,6 +38,7 @@ class OpensolrHybridRetriever:
|
|
|
38
38
|
alpha: float = 0.5,
|
|
39
39
|
filters: Optional[Dict[str, Any]] = None,
|
|
40
40
|
lexical: bool = False,
|
|
41
|
+
fresh_bias: bool = False,
|
|
41
42
|
) -> None:
|
|
42
43
|
self.document_store = document_store
|
|
43
44
|
self.top_k = top_k
|
|
@@ -45,6 +46,11 @@ class OpensolrHybridRetriever:
|
|
|
45
46
|
self.alpha = alpha
|
|
46
47
|
self.filters = filters
|
|
47
48
|
self.lexical = lexical
|
|
49
|
+
# Threaded through the component because a pipeline never touches the store
|
|
50
|
+
# directly — run() below is the only door onto OpensolrDocumentStore.search()
|
|
51
|
+
# for a Haystack user, so an option the component does not carry is an option
|
|
52
|
+
# that does not exist in a pipeline.
|
|
53
|
+
self.fresh_bias = fresh_bias
|
|
48
54
|
|
|
49
55
|
@component.output_types(documents=List[Document])
|
|
50
56
|
def run(
|
|
@@ -55,9 +61,14 @@ class OpensolrHybridRetriever:
|
|
|
55
61
|
alpha: Optional[float] = None,
|
|
56
62
|
filters: Optional[Dict[str, Any]] = None,
|
|
57
63
|
lexical: Optional[bool] = None,
|
|
64
|
+
fresh_bias: Optional[bool] = None,
|
|
58
65
|
) -> Dict[str, List[Document]]:
|
|
59
66
|
"""Run the retriever. ``alpha``: 0 = all semantic, 1 = all lexical.
|
|
60
|
-
``lexical=True`` = pure keyword search, no embedding call.
|
|
67
|
+
``lexical=True`` = pure keyword search, no embedding call.
|
|
68
|
+
``fresh_bias=True`` biases the ranking toward recent documents by
|
|
69
|
+
multiplying each score by a recency curve on ``creation_date``; it
|
|
70
|
+
re-orders and never filters, so the hit count is unchanged and nothing
|
|
71
|
+
old becomes unreachable. Off by default."""
|
|
61
72
|
docs = self.document_store.search(
|
|
62
73
|
query=query,
|
|
63
74
|
top_k=top_k if top_k is not None else self.top_k,
|
|
@@ -65,6 +76,7 @@ class OpensolrHybridRetriever:
|
|
|
65
76
|
alpha=alpha if alpha is not None else self.alpha,
|
|
66
77
|
filters=filters if filters is not None else self.filters,
|
|
67
78
|
lexical=lexical if lexical is not None else self.lexical,
|
|
79
|
+
fresh_bias=fresh_bias if fresh_bias is not None else self.fresh_bias,
|
|
68
80
|
)
|
|
69
81
|
return {"documents": docs}
|
|
70
82
|
|
|
@@ -77,6 +89,10 @@ class OpensolrHybridRetriever:
|
|
|
77
89
|
alpha=self.alpha,
|
|
78
90
|
filters=self.filters,
|
|
79
91
|
lexical=self.lexical,
|
|
92
|
+
# Serialized alongside the other search options so a pipeline saved with
|
|
93
|
+
# the bias on comes back with it on. from_dict() tolerates its absence in
|
|
94
|
+
# dicts written before this option existed — the constructor defaults it.
|
|
95
|
+
fresh_bias=self.fresh_bias,
|
|
80
96
|
)
|
|
81
97
|
|
|
82
98
|
@classmethod
|