patternmem-rag 0.1.1__tar.gz → 0.1.2__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.
Files changed (34) hide show
  1. {patternmem_rag-0.1.1/patternmem_rag.egg-info → patternmem_rag-0.1.2}/PKG-INFO +2 -2
  2. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/README.md +1 -1
  3. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/middleware.py +6 -1
  4. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2/patternmem_rag.egg-info}/PKG-INFO +2 -2
  5. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/pyproject.toml +1 -1
  6. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_middleware.py +60 -0
  7. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/LICENSE +0 -0
  8. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/__init__.py +0 -0
  9. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/_utils.py +0 -0
  10. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/augmenter.py +0 -0
  11. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backend.py +0 -0
  12. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/__init__.py +0 -0
  13. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/chroma_backend.py +0 -0
  14. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/faiss_backend.py +0 -0
  15. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/json_backend.py +0 -0
  16. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/neo4j_backend.py +0 -0
  17. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/networkx_backend.py +0 -0
  18. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/backends/sqlite_backend.py +0 -0
  19. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/decay.py +0 -0
  20. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/eval_router.py +0 -0
  21. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/observability.py +0 -0
  22. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/reflector.py +0 -0
  23. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/resolver.py +0 -0
  24. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem/types.py +0 -0
  25. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem_rag.egg-info/SOURCES.txt +0 -0
  26. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem_rag.egg-info/dependency_links.txt +0 -0
  27. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem_rag.egg-info/requires.txt +0 -0
  28. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/patternmem_rag.egg-info/top_level.txt +0 -0
  29. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/setup.cfg +0 -0
  30. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_augmenter.py +0 -0
  31. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_decay.py +0 -0
  32. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_eval_router.py +0 -0
  33. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_resolver.py +0 -0
  34. {patternmem_rag-0.1.1 → patternmem_rag-0.1.2}/tests/test_types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patternmem-rag
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Framework-agnostic RAG middleware that makes any pipeline self-improving via persistent failure-pattern memory.
5
5
  Author-email: Nitesh Kumar <nk-gujjar@users.noreply.github.com>
6
6
  License-Expression: MIT
@@ -53,7 +53,7 @@ Dynamic: license-file
53
53
  # PatternMem RAG
54
54
 
55
55
  [![CI](https://github.com/nk-gujjar/patternmem-rag/actions/workflows/ci.yml/badge.svg)](https://github.com/nk-gujjar/patternmem-rag/actions)
56
- [![PyPI version](https://img.shields.io/badge/pypi-v0.1.0-blue.svg)](https://pypi.org/project/patternmem-rag/)
56
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.1.1-blue.svg)](https://pypi.org/project/patternmem-rag/)
57
57
  [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/patternmem-rag/)
58
58
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
59
59
 
@@ -1,7 +1,7 @@
1
1
  # PatternMem RAG
2
2
 
3
3
  [![CI](https://github.com/nk-gujjar/patternmem-rag/actions/workflows/ci.yml/badge.svg)](https://github.com/nk-gujjar/patternmem-rag/actions)
4
- [![PyPI version](https://img.shields.io/badge/pypi-v0.1.0-blue.svg)](https://pypi.org/project/patternmem-rag/)
4
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.1.1-blue.svg)](https://pypi.org/project/patternmem-rag/)
5
5
  [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/patternmem-rag/)
6
6
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
7
7
 
@@ -49,7 +49,7 @@ from patternmem.eval_router import EvalRouter
49
49
  from patternmem.observability import ObservabilityEmitter
50
50
  from patternmem.reflector import BackgroundReflector
51
51
  from patternmem.resolver import LLMResolver
52
- from patternmem.types import FailurePattern, FailureSignal
52
+ from patternmem.types import FailurePattern, FailureSignal, FailureType
53
53
 
54
54
  logger = logging.getLogger(__name__)
55
55
 
@@ -317,6 +317,9 @@ class PatternMemMiddleware:
317
317
  )
318
318
 
319
319
  for signal in signals:
320
+ if signal.failure_type is FailureType.UNKNOWN and signal.score == 0.0:
321
+ continue
322
+
320
323
  # Match signal to an existing pattern by failure_type
321
324
  matched = next(
322
325
  (
@@ -326,6 +329,8 @@ class PatternMemMiddleware:
326
329
  ),
327
330
  None,
328
331
  )
332
+ if matched is None and signal.failure_type is FailureType.UNKNOWN:
333
+ matched = matched_patterns[0] if matched_patterns else None
329
334
  # matched=None → new pattern will be written in Phase 3
330
335
  self._reflector.enqueue(
331
336
  signal=signal,
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: patternmem-rag
3
- Version: 0.1.1
3
+ Version: 0.1.2
4
4
  Summary: Framework-agnostic RAG middleware that makes any pipeline self-improving via persistent failure-pattern memory.
5
5
  Author-email: Nitesh Kumar <nk-gujjar@users.noreply.github.com>
6
6
  License-Expression: MIT
@@ -53,7 +53,7 @@ Dynamic: license-file
53
53
  # PatternMem RAG
54
54
 
55
55
  [![CI](https://github.com/nk-gujjar/patternmem-rag/actions/workflows/ci.yml/badge.svg)](https://github.com/nk-gujjar/patternmem-rag/actions)
56
- [![PyPI version](https://img.shields.io/badge/pypi-v0.1.0-blue.svg)](https://pypi.org/project/patternmem-rag/)
56
+ [![PyPI version](https://img.shields.io/badge/pypi-v0.1.1-blue.svg)](https://pypi.org/project/patternmem-rag/)
57
57
  [![Python](https://img.shields.io/badge/python-3.10%20%7C%203.11%20%7C%203.12-blue.svg)](https://pypi.org/project/patternmem-rag/)
58
58
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](LICENSE)
59
59
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "patternmem-rag"
7
- version = "0.1.1"
7
+ version = "0.1.2"
8
8
  description = "Framework-agnostic RAG middleware that makes any pipeline self-improving via persistent failure-pattern memory."
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -190,6 +190,66 @@ class TestPhase1Augmentation:
190
190
  )
191
191
  assert "use broader query terms" in received_kwargs["retrieval_hint"]
192
192
 
193
+ async def test_eval_none_does_not_write_or_extract_pattern(
194
+ self, tmp_path: Path
195
+ ) -> None:
196
+ backend = JSONBackend(path=tmp_path / "mw_none.json", similarity_threshold=0.50)
197
+ llm = MagicMock()
198
+
199
+ with patch("patternmem.middleware.SentenceTransformer") as MockST:
200
+ mock_encoder = MagicMock()
201
+ mock_encoder.encode.return_value = np.array(_unit_vec(11), dtype=np.float32)
202
+ MockST.return_value = mock_encoder
203
+
204
+ async with PatternMemMiddleware(
205
+ pipeline=_sync_pipeline,
206
+ backend=backend,
207
+ eval="none",
208
+ llm=llm,
209
+ ) as mw:
210
+ await mw.ainvoke("disabled evaluation")
211
+ await asyncio.sleep(0.05)
212
+
213
+ assert (await backend.get_stats())["count"] == 0
214
+ llm.assert_not_called()
215
+
216
+ async def test_successful_unknown_signal_reinforces_matched_pattern(
217
+ self, tmp_path: Path
218
+ ) -> None:
219
+ backend = JSONBackend(path=tmp_path / "mw_success.json", similarity_threshold=0.50)
220
+ emb = _unit_vec(12)
221
+ pattern = FailurePattern(
222
+ query_embedding=emb,
223
+ failure_type=FailureType.RETRIEVAL_MISS,
224
+ hint_text="broaden query",
225
+ score=0.1,
226
+ )
227
+ await backend.write_pattern(pattern)
228
+
229
+ with patch("patternmem.middleware.SentenceTransformer") as MockST:
230
+ mock_encoder = MagicMock()
231
+ mock_encoder.encode.return_value = np.array(emb, dtype=np.float32)
232
+ MockST.return_value = mock_encoder
233
+
234
+ async with PatternMemMiddleware(
235
+ pipeline=lambda query, **kwargs: {
236
+ "answer": "ok",
237
+ "chunks": ["relevant"],
238
+ "reflect": 0.9,
239
+ },
240
+ backend=backend,
241
+ eval="auto",
242
+ llm=MagicMock(),
243
+ ) as mw:
244
+ await mw.ainvoke("successful hinted query")
245
+ await asyncio.sleep(0.05)
246
+
247
+ patterns = await backend.lookup_patterns(emb, top_k=3)
248
+ assert len(patterns) == 1
249
+ assert patterns[0].id == pattern.id
250
+ assert patterns[0].failure_type == FailureType.RETRIEVAL_MISS
251
+ assert patterns[0].decay_weight == pytest.approx(1.1)
252
+
193
253
 
194
254
  class TestAsyncContextManager:
195
255
  async def test_context_manager_starts_and_stops_reflector(
File without changes
File without changes