opensolr-haystack 0.2.7__tar.gz → 0.2.9__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensolr-haystack
3
- Version: 0.2.7
3
+ Version: 0.2.9
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
@@ -10,6 +10,7 @@ Direct Solr access (select/update) goes to the index's own host, resolved via
10
10
 
11
11
  from __future__ import annotations
12
12
 
13
+ import re
13
14
  import json
14
15
  from typing import Any, Dict, List, Optional, Tuple
15
16
 
@@ -49,16 +50,23 @@ BATCH_EMBED_MAX = 50
49
50
  # rules make it lead with the answer and keep the concrete details. Callers
50
51
  # can still override everything by passing ``instruction``.
51
52
  DEFAULT_RAG_INSTRUCTION = (
52
- # Consolidated 2026-08-26. The rule list had grown to eight overlapping lines and the
53
- # 3B model drowned in them: it restated the question, opened with a preamble, and
54
- # presented items as fit for purposes the context never stated. Tested against the
55
- # live model on three cases (answer present, answer absent, yes/no) before shipping.
53
+ # Length cap and formatting reworked 2026-08-26: the earlier "two to four sentences"
54
+ # rule produced a dense paragraph that dropped most of what the documents said.
55
+ # Verified against a real four-document context before shipping — bulleted, far more
56
+ # detail, zero invented terms. The "do not add from your own knowledge" line is what
57
+ # keeps it grounded; without it the model pads the list with generic advice.
56
58
  "Answer the question using only the context below.\n"
57
59
  "Begin with the answer itself, the specific fact, product or detail. "
58
60
  "No preamble, no restating the question, no heading.\n"
59
- "Then give the concrete supporting details from the context: names, numbers, sizes, dates. "
60
- "Write two to four sentences.\n"
61
- "If the context holds no answer, say that in the first sentence and name what it does contain instead.\n"
61
+ "Be thorough: cover every relevant point the context offers, with the concrete details "
62
+ "\u2014 names, model numbers, measurements, standards, dates.\n"
63
+ "Format it for reading, in Markdown: short paragraphs, and a bullet list when the answer "
64
+ "is a set of steps, precautions or options, each bullet opening with a bold lead-in naming "
65
+ "that item. Never invent generic headings such as \"Overview\", \"Key Points\" or \"Summary\".\n"
66
+ "Use only what the context states. Do not add advice, products or standards from your own "
67
+ "knowledge.\n"
68
+ "If the context holds no answer, say that in the first sentence and name what it does "
69
+ "contain instead.\n"
62
70
  "Never present something as suitable for a purpose the context does not state."
63
71
  )
64
72
 
@@ -385,11 +393,19 @@ class OpensolrClient:
385
393
 
386
394
  parts: List[str] = []
387
395
  for doc in hits[:docs]:
388
- text_words = _flat(doc.get("text")).split()[:words]
396
+ # Truncate at the Nth word by CUTTING the original string, never by splitting and
397
+ # re-joining: " ".join(text.split()) throws away every newline and every run of
398
+ # indentation, so a page arrives as one unbroken line with its paragraphs, lists and
399
+ # code blocks flattened. Text handed to a model has to reach it as written; the
400
+ # structure is part of the meaning (2026-08-26).
401
+ body = _flat(doc.get("text"))
402
+ matches = list(re.finditer(r"\S+", body))
403
+ if len(matches) > words:
404
+ body = body[: matches[words - 1].end()]
389
405
  parts.append(
390
- _flat(doc.get("title")) + " - "
391
- + _flat(doc.get("description")) + " - "
392
- + " ".join(text_words) + " - "
406
+ _flat(doc.get("title")) + "\n"
407
+ + _flat(doc.get("description")) + "\n"
408
+ + body + "\n\n"
393
409
  )
394
410
  return "".join(parts)
395
411
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: opensolr-haystack
3
- Version: 0.2.7
3
+ Version: 0.2.9
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
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "opensolr-haystack"
7
- version = "0.2.7"
7
+ version = "0.2.9"
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" }