Spaces:
Paused
Paused
Download tests/test_retro/test_rag.py from whassan/SensorflowStudio: direct link, hf CLI and curl.
- Browser
- Download file 5.58 kB
-
https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/tests/test_retro/test_rag.py
- Command line
-
hf download hf://spaces/whassan/SensorflowStudio/tests/test_retro/test_rag.py
-
curl -L -o test_rag.py https://huggingface.co/spaces/whassan/SensorflowStudio/resolve/main/tests/test_retro/test_rag.py
5.58 kB
| """Phase 2 tests: chunking, retrieval eval, synthetic labeling, and the | |
| no-citation-without-retrieval hard rule.""" | |
| from __future__ import annotations | |
| import pytest | |
| from pydantic import ValidationError | |
| from sensorflow.retro.rag.chunking import chunk_document, chunk_words, parse_sections | |
| from sensorflow.retro.rag.corpus import SEED_DOCUMENTS | |
| from sensorflow.retro.rag.evalharness import EVAL_QUERIES, run_retrieval_eval | |
| from sensorflow.retro.scorecard import RetrievedStandard | |
| # ------------------------------------------------------------------ chunking | |
| def test_parse_sections_and_word_chunking(): | |
| text = "preamble line\n## Alpha\n" + ("word " * 300) + "\n## Beta\nshort tail" | |
| secs = parse_sections(text) | |
| assert [s["section"] for s in secs] == ["preamble", "Alpha", "Beta"] | |
| chunks = chunk_words(secs[1]["text"], chunk_size=100, overlap=20) | |
| assert len(chunks) >= 3 | |
| # overlap: consecutive chunks share their boundary words | |
| first_words = chunks[0].split() | |
| second_words = chunks[1].split() | |
| assert first_words[-20:] == second_words[:20] | |
| def test_chunk_config_validation(): | |
| with pytest.raises(ValueError): | |
| chunk_words("a b c", chunk_size=10, overlap=10) | |
| with pytest.raises(ValueError): | |
| chunk_words("a b c", chunk_size=0) | |
| def test_chunk_document_propagates_metadata(): | |
| chunks = chunk_document("DOC-1", "## Sec A\nhello world content here", | |
| {"doc_id": "DOC-1", "source": "unit"}, | |
| chunk_size=50, overlap=10) | |
| assert chunks and chunks[0].metadata["section"] == "Sec A" | |
| assert chunks[0].metadata["source"] == "unit" | |
| # ---------------------------------------------------------------- eval harness | |
| def test_retrieval_eval_precision(fallback_index): | |
| report = run_retrieval_eval(index=fallback_index, k=4) | |
| assert report.num_queries == len(EVAL_QUERIES) >= 12 | |
| # deterministic fallback embedder must resolve at least 85% of the | |
| # expected-source assertions at k=4 | |
| assert report.precision_at_k >= 0.85, [ | |
| r.model_dump() for r in report.results if not r.hit_at_k] | |
| def test_every_synthetic_hit_is_labeled(fallback_index): | |
| """Synthetic rules carry the SYNTHETIC label in content AND metadata; the | |
| SOTIF doc carries the paraphrase label. No unlabeled hit can exist.""" | |
| for item in EVAL_QUERIES: | |
| for hit in fallback_index.search(item["query"], k=4): | |
| if hit.synthetic: | |
| assert "SYNTHETIC_EXAMPLE" in hit.label | |
| assert ("SYNTHETIC_EXAMPLE" in hit.retrieved_text | |
| or "NOT_A_REAL_STANDARD" in hit.retrieved_text) | |
| else: | |
| assert hit.label == "PARAPHRASE_NOT_STANDARD_TEXT" | |
| assert "PARAPHRASE_NOT_STANDARD_TEXT" in hit.retrieved_text | |
| def test_seed_corpus_covers_required_doc_types(): | |
| types = {d["doc_type"] for d in SEED_DOCUMENTS} | |
| assert {"safety_requirement", "launch_criteria", "perception_requirement", | |
| "odd_definition", "historical_retrospective", "evaluation_policy", | |
| "standard_concept_paraphrase"} <= types | |
| for doc in SEED_DOCUMENTS: | |
| # full metadata is mandatory | |
| for key in ("source", "version", "jurisdiction", "doc_type", | |
| "effective_date"): | |
| assert doc[key] | |
| # ------------------------------------- no-citation-without-retrieval hard rule | |
| def test_citation_impossible_without_retrieved_text(): | |
| """RetrievedStandard has no escape hatch: a citation cannot be built | |
| without real retrieved text and a relevance score.""" | |
| base = dict(source="s", document="d", version="1", section="x", | |
| doc_id="D-1", doc_type="t", jurisdiction="j", | |
| effective_date="2026-01-01", synthetic=True, label="L", | |
| chunk_id="c1") | |
| with pytest.raises(ValidationError): | |
| RetrievedStandard(**base) # no retrieved_text / relevance_score at all | |
| with pytest.raises(ValidationError): | |
| RetrievedStandard(**base, retrieved_text="too short", | |
| relevance_score=0.5) | |
| with pytest.raises(ValidationError): | |
| RetrievedStandard(**base, | |
| retrieved_text="long enough retrieved text body here", | |
| relevance_score=1.7) | |
| def test_retriever_always_returns_full_citation_fields(fallback_index): | |
| hits = fallback_index.search("pedestrian stopping distance recall", k=4) | |
| assert hits | |
| for h in hits: | |
| assert h.source and h.document and h.version and h.section | |
| assert len(h.retrieved_text) >= 20 | |
| assert 0.0 <= h.relevance_score <= 1.0 | |
| def test_agent_citations_are_backed_by_retrieval(retro_root): | |
| """End-to-end: every citation on a scorecard corresponds to a retrieval | |
| hit recorded in the audited RAG tool calls.""" | |
| from sensorflow.retro.agent.orchestrator import analyze_fixture | |
| from sensorflow.retro.tools.builtin import build_registry | |
| from sensorflow.retro import store as retro_store | |
| sc = analyze_fixture("missed_pedestrian_rain", backend="mock") | |
| assert sc.retrieved_standards, "canonical fixture must cite requirements" | |
| audit = retro_store.read_audit("missed_pedestrian_rain") | |
| rag_calls = [r for r in audit if r["tool"] == "safety_standard_rag" | |
| and r["status"] == "ok"] | |
| assert rag_calls, "citations exist but no audited retrieval call was made" | |
| for std in sc.retrieved_standards: | |
| assert std.retrieved_text and std.relevance_score >= 0.0 | |
| assert std.chunk_id # traceable to a stored chunk | |