Spaces:
Running
Running
Commit ·
f3310a2
1
Parent(s): fa364c7
fix: InternalCorpusProvider last_error; None novelty/cf scores crash report agent
Browse files- memory/graph_memory.py +3 -3
- similarity/corpus/internal.py +1 -0
- tests/similarity/test_privacy.py +7 -0
- tests/test_graph_memory.py +49 -0
memory/graph_memory.py
CHANGED
|
@@ -344,7 +344,7 @@ class GraphMemory(BaseMemory):
|
|
| 344 |
concerns = r.get("concerns", []) or []
|
| 345 |
strengths = r.get("strengths", []) or []
|
| 346 |
lines = [
|
| 347 |
-
|
| 348 |
f"Most common type: {r.get('common_type', 'factual')}",
|
| 349 |
f"Summary: {r.get('summary', '')}",
|
| 350 |
]
|
|
@@ -369,7 +369,7 @@ class GraphMemory(BaseMemory):
|
|
| 369 |
for cr in claim_rows:
|
| 370 |
lines.append(
|
| 371 |
f" - [{cr.get('cf_type', 'unknown')}] "
|
| 372 |
-
f"(score={cr.get('cf_score'
|
| 373 |
)
|
| 374 |
|
| 375 |
return format_context_block("Counterfactuality Analysis", "\n".join(lines))
|
|
@@ -389,7 +389,7 @@ class GraphMemory(BaseMemory):
|
|
| 389 |
return ""
|
| 390 |
r = rows[0]
|
| 391 |
lines = [
|
| 392 |
-
f"Novelty score: {r.get('novelty_score'
|
| 393 |
f"Problem statement: {r.get('problem_statement', '')}",
|
| 394 |
f"Rationale: {r.get('rationale', '')}",
|
| 395 |
]
|
|
|
|
| 344 |
concerns = r.get("concerns", []) or []
|
| 345 |
strengths = r.get("strengths", []) or []
|
| 346 |
lines = [
|
| 347 |
+
f"Overall counterfactuality score: {(r.get('overall_score') or 0):.2f}/1.0",
|
| 348 |
f"Most common type: {r.get('common_type', 'factual')}",
|
| 349 |
f"Summary: {r.get('summary', '')}",
|
| 350 |
]
|
|
|
|
| 369 |
for cr in claim_rows:
|
| 370 |
lines.append(
|
| 371 |
f" - [{cr.get('cf_type', 'unknown')}] "
|
| 372 |
+
f"(score={(cr.get('cf_score') or 0):.2f}) {cr.get('text', '')}"
|
| 373 |
)
|
| 374 |
|
| 375 |
return format_context_block("Counterfactuality Analysis", "\n".join(lines))
|
|
|
|
| 389 |
return ""
|
| 390 |
r = rows[0]
|
| 391 |
lines = [
|
| 392 |
+
f"Novelty score: {(r.get('novelty_score') or 0):.1f}/10 ({r.get('verdict', 'UNKNOWN')})",
|
| 393 |
f"Problem statement: {r.get('problem_statement', '')}",
|
| 394 |
f"Rationale: {r.get('rationale', '')}",
|
| 395 |
]
|
similarity/corpus/internal.py
CHANGED
|
@@ -45,6 +45,7 @@ class InternalCorpusProvider:
|
|
| 45 |
self._job_id = job_id
|
| 46 |
self._k = k or settings.kgram_size
|
| 47 |
self._w = w or settings.window_size
|
|
|
|
| 48 |
|
| 49 |
async def search_phrase(self, phrase: str, limit: int) -> list[Candidate]:
|
| 50 |
if not settings.enable_internal:
|
|
|
|
| 45 |
self._job_id = job_id
|
| 46 |
self._k = k or settings.kgram_size
|
| 47 |
self._w = w or settings.window_size
|
| 48 |
+
self.last_error: str | None = None
|
| 49 |
|
| 50 |
async def search_phrase(self, phrase: str, limit: int) -> list[Candidate]:
|
| 51 |
if not settings.enable_internal:
|
tests/similarity/test_privacy.py
CHANGED
|
@@ -55,6 +55,13 @@ def test_neutral_label_without_date():
|
|
| 55 |
assert _submitted_label(None) == "CitationEdge Corpus · submitted unknown-date"
|
| 56 |
|
| 57 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 58 |
async def test_indexed_document_is_found_by_internal_provider(fake_mongo):
|
| 59 |
assert await _index(fake_mongo) is True
|
| 60 |
|
|
|
|
| 55 |
assert _submitted_label(None) == "CitationEdge Corpus · submitted unknown-date"
|
| 56 |
|
| 57 |
|
| 58 |
+
def test_internal_provider_exposes_last_error(internal_provider):
|
| 59 |
+
"""Regression: pipeline reads provider.last_error; InternalCorpusProvider
|
| 60 |
+
must define it like every other provider (prod crash: AttributeError)."""
|
| 61 |
+
provider = internal_provider(doc_id="doc_new")
|
| 62 |
+
assert provider.last_error is None
|
| 63 |
+
|
| 64 |
+
|
| 65 |
async def test_indexed_document_is_found_by_internal_provider(fake_mongo):
|
| 66 |
assert await _index(fake_mongo) is True
|
| 67 |
|
tests/test_graph_memory.py
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
"""Regression tests for GraphMemory report-context formatting.
|
| 2 |
+
|
| 3 |
+
Incident: job_829f9c99 - when the novelty agent's LLM call failed under the
|
| 4 |
+
Groq quota storm it stored novelty_score=None, and get_novelty_context raised
|
| 5 |
+
"unsupported format string passed to NoneType.__format__", crashing the report
|
| 6 |
+
agent and stopping the whole pipeline (no PDF, no email).
|
| 7 |
+
"""
|
| 8 |
+
|
| 9 |
+
from unittest.mock import MagicMock
|
| 10 |
+
|
| 11 |
+
import pytest
|
| 12 |
+
|
| 13 |
+
from memory.graph_memory import GraphMemory
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
@pytest.fixture
|
| 17 |
+
def graph_memory(mock_neo4j, mock_embedder):
|
| 18 |
+
return GraphMemory(neo4j=mock_neo4j, embedder=mock_embedder)
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def test_novelty_context_with_none_score(graph_memory):
|
| 22 |
+
"""novelty_score=None (LLM failure) must render as 0.0, not crash."""
|
| 23 |
+
graph_memory.neo4j.run.return_value = [
|
| 24 |
+
{"novelty_score": None, "verdict": "UNKNOWN",
|
| 25 |
+
"problem_statement": "ps", "rationale": "r", "similar_works": []}
|
| 26 |
+
]
|
| 27 |
+
ctx = graph_memory.get_novelty_context("doc_x")
|
| 28 |
+
assert "Novelty score: 0.0/10 (UNKNOWN)" in ctx
|
| 29 |
+
|
| 30 |
+
|
| 31 |
+
def test_novelty_context_with_real_score(graph_memory):
|
| 32 |
+
graph_memory.neo4j.run.return_value = [
|
| 33 |
+
{"novelty_score": 7.3, "verdict": "NOVEL",
|
| 34 |
+
"problem_statement": "ps", "rationale": "r", "similar_works": []}
|
| 35 |
+
]
|
| 36 |
+
ctx = graph_memory.get_novelty_context("doc_x")
|
| 37 |
+
assert "Novelty score: 7.3/10 (NOVEL)" in ctx
|
| 38 |
+
|
| 39 |
+
|
| 40 |
+
def test_counterfactuality_context_with_none_scores(graph_memory):
|
| 41 |
+
"""None overall_score/cf_score (LLM failure) must not crash the report."""
|
| 42 |
+
graph_memory.neo4j.run.side_effect = [
|
| 43 |
+
[{"overall_score": None, "common_type": "factual", "concerns": [],
|
| 44 |
+
"strengths": [], "summary": "s"}],
|
| 45 |
+
[{"text": "c1", "cf_type": "unsupported", "cf_score": None}],
|
| 46 |
+
]
|
| 47 |
+
ctx = graph_memory.get_counterfactuality_context("doc_x")
|
| 48 |
+
assert "Overall counterfactuality score: 0.00/1.0" in ctx
|
| 49 |
+
assert "(score=0.00) c1" in ctx
|