opensolr-haystack 0.4.0__tar.gz → 0.5.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.4.0 → opensolr_haystack-0.5.0}/PKG-INFO +29 -2
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/README.md +28 -1
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/haystack_integrations/document_stores/opensolr/client.py +9 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/haystack_integrations/document_stores/opensolr/store.py +62 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/PKG-INFO +29 -2
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/pyproject.toml +1 -1
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/LICENSE +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/haystack_integrations/components/retrievers/opensolr/__init__.py +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/haystack_integrations/components/retrievers/opensolr/retriever.py +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/haystack_integrations/document_stores/opensolr/__init__.py +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/SOURCES.txt +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/dependency_links.txt +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/requires.txt +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/top_level.txt +0 -0
- {opensolr_haystack-0.4.0 → opensolr_haystack-0.5.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.5.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
|
|
@@ -145,10 +145,37 @@ Don't need vectors? Pure keyword search skips the embedding call entirely —
|
|
|
145
145
|
zero AI quota, and it works on **any** Opensolr index, including non-vector
|
|
146
146
|
ones and older Solr versions.
|
|
147
147
|
|
|
148
|
+
## Search by image
|
|
149
|
+
|
|
150
|
+
Search your index with a **photo** instead of a text query. Opensolr reads the
|
|
151
|
+
picture three ways — visual labels (what it depicts), OCR text (words printed on
|
|
152
|
+
it), and any barcode / QR code — and turns that into an ordinary search. Nothing
|
|
153
|
+
new is stored in Solr; the picture simply becomes words.
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# What the picture reads as (labels, OCR text, barcodes) — no search yet:
|
|
157
|
+
read = store.image_to_words("photo.jpg") # path, bytes, or base64
|
|
158
|
+
# {'text': 'red running shoe', 'mode': 'clip',
|
|
159
|
+
# 'labels': ['running shoe', 'sneaker'], 'codes': ['0123456789012']}
|
|
160
|
+
|
|
161
|
+
# Search the index with the picture:
|
|
162
|
+
docs = store.search_by_image("photo.jpg", top_k=4) # engine picks the best reading
|
|
163
|
+
docs = store.search_by_image("photo.jpg", using="meaning") # visual labels
|
|
164
|
+
docs = store.search_by_image("photo.jpg", using="text") # only OCR text
|
|
165
|
+
docs = store.search_by_image("photo.jpg", using="code") # exact barcode / QR match
|
|
166
|
+
docs = store.search_by_image("photo.jpg", using="all") # labels + OCR + codes
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`search_by_image` forwards the same tuning as `search` — `hybrid`, `lexical`,
|
|
170
|
+
`alpha`, `fresh_bias`, `filters` — so an image query runs through the exact
|
|
171
|
+
hybrid pipeline a text query does.
|
|
172
|
+
|
|
148
173
|
## Your index schema
|
|
149
174
|
|
|
150
175
|
Documents follow the Opensolr document model (`title`, `description`, `text`,
|
|
151
|
-
`meta_*` custom fields).
|
|
176
|
+
`meta_*` custom fields). The whole schema, every field and every type suffix,
|
|
177
|
+
is explained in the [Index Schema Reference](https://opensolr.com/opensolr-platform-user-documentation/schema-reference).
|
|
178
|
+
To see your own copy: **Control Panel → click your
|
|
152
179
|
index → Configuration → Edit File → schema.xml**. Prefer zero-effort data
|
|
153
180
|
entry? Configure the **Web Crawler** in the Control Panel (Index Tools →
|
|
154
181
|
WebCrawler): add your site URL, validate it, and Opensolr indexes the whole
|
|
@@ -127,10 +127,37 @@ Don't need vectors? Pure keyword search skips the embedding call entirely —
|
|
|
127
127
|
zero AI quota, and it works on **any** Opensolr index, including non-vector
|
|
128
128
|
ones and older Solr versions.
|
|
129
129
|
|
|
130
|
+
## Search by image
|
|
131
|
+
|
|
132
|
+
Search your index with a **photo** instead of a text query. Opensolr reads the
|
|
133
|
+
picture three ways — visual labels (what it depicts), OCR text (words printed on
|
|
134
|
+
it), and any barcode / QR code — and turns that into an ordinary search. Nothing
|
|
135
|
+
new is stored in Solr; the picture simply becomes words.
|
|
136
|
+
|
|
137
|
+
```python
|
|
138
|
+
# What the picture reads as (labels, OCR text, barcodes) — no search yet:
|
|
139
|
+
read = store.image_to_words("photo.jpg") # path, bytes, or base64
|
|
140
|
+
# {'text': 'red running shoe', 'mode': 'clip',
|
|
141
|
+
# 'labels': ['running shoe', 'sneaker'], 'codes': ['0123456789012']}
|
|
142
|
+
|
|
143
|
+
# Search the index with the picture:
|
|
144
|
+
docs = store.search_by_image("photo.jpg", top_k=4) # engine picks the best reading
|
|
145
|
+
docs = store.search_by_image("photo.jpg", using="meaning") # visual labels
|
|
146
|
+
docs = store.search_by_image("photo.jpg", using="text") # only OCR text
|
|
147
|
+
docs = store.search_by_image("photo.jpg", using="code") # exact barcode / QR match
|
|
148
|
+
docs = store.search_by_image("photo.jpg", using="all") # labels + OCR + codes
|
|
149
|
+
```
|
|
150
|
+
|
|
151
|
+
`search_by_image` forwards the same tuning as `search` — `hybrid`, `lexical`,
|
|
152
|
+
`alpha`, `fresh_bias`, `filters` — so an image query runs through the exact
|
|
153
|
+
hybrid pipeline a text query does.
|
|
154
|
+
|
|
130
155
|
## Your index schema
|
|
131
156
|
|
|
132
157
|
Documents follow the Opensolr document model (`title`, `description`, `text`,
|
|
133
|
-
`meta_*` custom fields).
|
|
158
|
+
`meta_*` custom fields). The whole schema, every field and every type suffix,
|
|
159
|
+
is explained in the [Index Schema Reference](https://opensolr.com/opensolr-platform-user-documentation/schema-reference).
|
|
160
|
+
To see your own copy: **Control Panel → click your
|
|
134
161
|
index → Configuration → Edit File → schema.xml**. Prefer zero-effort data
|
|
135
162
|
entry? Configure the **Web Crawler** in the Control Panel (Index Tools →
|
|
136
163
|
WebCrawler): add your site URL, validate it, and Opensolr indexes the whole
|
|
@@ -540,6 +540,15 @@ class OpensolrClient:
|
|
|
540
540
|
def ai(self, method: str, **params: Any) -> Any:
|
|
541
541
|
return self._request(AI_BASE, method, params)
|
|
542
542
|
|
|
543
|
+
def image_to_text(self, index: str, image_b64: str, top_k: int = 8) -> Dict[str, Any]:
|
|
544
|
+
"""Turn an image into search words via the Opensolr image_to_text API.
|
|
545
|
+
|
|
546
|
+
The answer carries ``text`` (the words to search with), ``mode`` ("clip"/"ocr"),
|
|
547
|
+
``labels`` (CLIP visual labels, present even in OCR mode) and ``codes``
|
|
548
|
+
(barcodes / QR codes). No image vector is stored: the picture becomes words.
|
|
549
|
+
"""
|
|
550
|
+
return self.ai("image_to_text", index_name=index, image=image_b64, top_k=top_k)
|
|
551
|
+
|
|
543
552
|
# ------------------------------------------------------------------ #
|
|
544
553
|
# management #
|
|
545
554
|
# ------------------------------------------------------------------ #
|
|
@@ -7,6 +7,8 @@ local embedder component needed at indexing time.
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
+
import base64
|
|
11
|
+
from pathlib import Path
|
|
10
12
|
import json
|
|
11
13
|
import re
|
|
12
14
|
from typing import Any, Dict, List, Optional
|
|
@@ -376,6 +378,66 @@ class OpensolrDocumentStore:
|
|
|
376
378
|
# serialization #
|
|
377
379
|
# ------------------------------------------------------------------ #
|
|
378
380
|
|
|
381
|
+
def image_to_words(self, image, top_k: int = 8) -> Dict[str, Any]:
|
|
382
|
+
"""Read an image and return what it was turned into, without searching yet.
|
|
383
|
+
|
|
384
|
+
Returns ``{"text", "mode", "labels", "codes"}``: the best words to search
|
|
385
|
+
with, whether it was read as visual labels ("clip") or OCR text ("ocr"),
|
|
386
|
+
the CLIP visual labels (present even in OCR mode), and any barcodes / QR codes.
|
|
387
|
+
``image`` is a file path (str/Path) or raw image bytes.
|
|
388
|
+
"""
|
|
389
|
+
raw = bytes(image) if isinstance(image, (bytes, bytearray)) else Path(image).read_bytes()
|
|
390
|
+
b64 = base64.b64encode(raw).decode("ascii")
|
|
391
|
+
ans = self.client.image_to_text(self._index, b64, top_k=top_k)
|
|
392
|
+
labels = [l["label"] for l in (ans.get("labels") or []) if isinstance(l, dict) and l.get("label")]
|
|
393
|
+
codes = []
|
|
394
|
+
for c in (ans.get("codes") or []):
|
|
395
|
+
text = c.get("text") if isinstance(c, dict) else (c if isinstance(c, str) else None)
|
|
396
|
+
if text:
|
|
397
|
+
codes.append(text)
|
|
398
|
+
return {"text": (ans.get("text") or "").strip(), "mode": ans.get("mode") or "clip", "labels": labels, "codes": codes}
|
|
399
|
+
|
|
400
|
+
def search_by_image(
|
|
401
|
+
self,
|
|
402
|
+
image,
|
|
403
|
+
top_k: int = 10,
|
|
404
|
+
using: str = "auto",
|
|
405
|
+
filters: Optional[Dict[str, Any]] = None,
|
|
406
|
+
image_top_k: int = 8,
|
|
407
|
+
**search_kwargs,
|
|
408
|
+
) -> List[Document]:
|
|
409
|
+
"""Search the index with a photo instead of a text query.
|
|
410
|
+
|
|
411
|
+
The image is turned into words by :meth:`image_to_words`, then those words
|
|
412
|
+
run through the normal :meth:`search`, so ``hybrid``, ``lexical``, ``alpha``
|
|
413
|
+
and ``fresh_bias`` apply via ``search_kwargs``. No image vector is stored.
|
|
414
|
+
|
|
415
|
+
``using``: which reading to search with — ``"auto"`` (the engine's chosen
|
|
416
|
+
text), ``"meaning"`` (CLIP visual labels), ``"text"`` (OCR text only), or
|
|
417
|
+
``"code"`` (the first barcode / QR code), or ``"all"`` (labels + OCR text + barcodes combined).
|
|
418
|
+
"""
|
|
419
|
+
read = self.image_to_words(image, top_k=image_top_k)
|
|
420
|
+
if using == "meaning":
|
|
421
|
+
query = ", ".join(read["labels"])
|
|
422
|
+
elif using == "text":
|
|
423
|
+
query = read["text"] if read["mode"] == "ocr" else ""
|
|
424
|
+
elif using == "code":
|
|
425
|
+
query = read["codes"][0] if read["codes"] else ""
|
|
426
|
+
search_kwargs.setdefault("lexical", True)
|
|
427
|
+
elif using == "all":
|
|
428
|
+
parts = list(read["labels"])
|
|
429
|
+
if read["mode"] == "ocr" and read["text"]:
|
|
430
|
+
parts.append(read["text"])
|
|
431
|
+
parts.extend(read["codes"])
|
|
432
|
+
query = ", ".join(p for p in parts if p)
|
|
433
|
+
elif using == "auto":
|
|
434
|
+
query = read["text"]
|
|
435
|
+
else:
|
|
436
|
+
raise ValueError("using must be one of 'auto', 'meaning', 'text', 'code', 'all'")
|
|
437
|
+
if not query:
|
|
438
|
+
return []
|
|
439
|
+
return self.search(query, top_k=top_k, filters=filters, **search_kwargs)
|
|
440
|
+
|
|
379
441
|
def to_dict(self) -> Dict[str, Any]:
|
|
380
442
|
return default_to_dict(
|
|
381
443
|
self,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: opensolr-haystack
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.5.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
|
|
@@ -145,10 +145,37 @@ Don't need vectors? Pure keyword search skips the embedding call entirely —
|
|
|
145
145
|
zero AI quota, and it works on **any** Opensolr index, including non-vector
|
|
146
146
|
ones and older Solr versions.
|
|
147
147
|
|
|
148
|
+
## Search by image
|
|
149
|
+
|
|
150
|
+
Search your index with a **photo** instead of a text query. Opensolr reads the
|
|
151
|
+
picture three ways — visual labels (what it depicts), OCR text (words printed on
|
|
152
|
+
it), and any barcode / QR code — and turns that into an ordinary search. Nothing
|
|
153
|
+
new is stored in Solr; the picture simply becomes words.
|
|
154
|
+
|
|
155
|
+
```python
|
|
156
|
+
# What the picture reads as (labels, OCR text, barcodes) — no search yet:
|
|
157
|
+
read = store.image_to_words("photo.jpg") # path, bytes, or base64
|
|
158
|
+
# {'text': 'red running shoe', 'mode': 'clip',
|
|
159
|
+
# 'labels': ['running shoe', 'sneaker'], 'codes': ['0123456789012']}
|
|
160
|
+
|
|
161
|
+
# Search the index with the picture:
|
|
162
|
+
docs = store.search_by_image("photo.jpg", top_k=4) # engine picks the best reading
|
|
163
|
+
docs = store.search_by_image("photo.jpg", using="meaning") # visual labels
|
|
164
|
+
docs = store.search_by_image("photo.jpg", using="text") # only OCR text
|
|
165
|
+
docs = store.search_by_image("photo.jpg", using="code") # exact barcode / QR match
|
|
166
|
+
docs = store.search_by_image("photo.jpg", using="all") # labels + OCR + codes
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
`search_by_image` forwards the same tuning as `search` — `hybrid`, `lexical`,
|
|
170
|
+
`alpha`, `fresh_bias`, `filters` — so an image query runs through the exact
|
|
171
|
+
hybrid pipeline a text query does.
|
|
172
|
+
|
|
148
173
|
## Your index schema
|
|
149
174
|
|
|
150
175
|
Documents follow the Opensolr document model (`title`, `description`, `text`,
|
|
151
|
-
`meta_*` custom fields).
|
|
176
|
+
`meta_*` custom fields). The whole schema, every field and every type suffix,
|
|
177
|
+
is explained in the [Index Schema Reference](https://opensolr.com/opensolr-platform-user-documentation/schema-reference).
|
|
178
|
+
To see your own copy: **Control Panel → click your
|
|
152
179
|
index → Configuration → Edit File → schema.xml**. Prefer zero-effort data
|
|
153
180
|
entry? Configure the **Web Crawler** in the Control Panel (Index Tools →
|
|
154
181
|
WebCrawler): add your site URL, validate it, and Opensolr indexes the whole
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "opensolr-haystack"
|
|
7
|
-
version = "0.
|
|
7
|
+
version = "0.5.0"
|
|
8
8
|
description = "Haystack integration for Opensolr — managed Apache Solr DocumentStore with server-side embeddings and hybrid BM25+kNN retrieval"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
{opensolr_haystack-0.4.0 → opensolr_haystack-0.5.0}/opensolr_haystack.egg-info/top_level.txt
RENAMED
|
File without changes
|
|
File without changes
|