88 lines
3.7 KiB
Python
88 lines
3.7 KiB
Python
import copy
|
|
import json
|
|
|
|
from tools.rag.build_chunks import TOKEN_COUNTER
|
|
from tools.rag.llm_context import compact_rag_payload
|
|
|
|
|
|
def response(text="Unikátny dôkaz o práci osoby. "):
|
|
return {
|
|
"status": "ok",
|
|
"query": "Práca?",
|
|
"engine": "test",
|
|
"strategies": ["test"],
|
|
"complete": None,
|
|
"truncated": False,
|
|
"truncation_reasons": [],
|
|
"index_version": {"version": "test"},
|
|
"instructions": ["Cituj iba dodané zdroje."],
|
|
"answer_format": {},
|
|
"sources": [
|
|
{
|
|
"source_id": "S1",
|
|
"document_path": "pages/eva/README.md",
|
|
"title": "Eva",
|
|
"source_url": "https://example.test/eva",
|
|
"text": text,
|
|
"query_evidence": {"huge_diagnostic": text * 10},
|
|
"retrieval": {"rank": 1},
|
|
}
|
|
],
|
|
"context": text,
|
|
}
|
|
|
|
|
|
def test_compact_payload_contains_evidence_once_and_preserves_sources():
|
|
original = response()
|
|
before = copy.deepcopy(original)
|
|
compact = compact_rag_payload(original)
|
|
assert original == before
|
|
assert json.dumps(compact, ensure_ascii=False).count(original["sources"][0]["text"]) == 1
|
|
assert "text" not in compact["sources"][0] and "query_evidence" not in compact["sources"][0]
|
|
assert compact["sources"][0]["source_url"] == "https://example.test/eva"
|
|
assert compact["index_version"] == original["index_version"]
|
|
assert compact_rag_payload(compact) == compact
|
|
|
|
|
|
def test_entire_tool_json_is_bounded_and_marks_omitted_evidence():
|
|
original = response("Veľmi dlhý dôkaz 🧑🏽💻. " * 2000)
|
|
original["sources"].append({**original["sources"][0], "source_id": "S2", "text": "Ďalší dôkaz"})
|
|
compact = compact_rag_payload(original, max_tokens=700)
|
|
used = TOKEN_COUNTER.count(json.dumps(compact, ensure_ascii=False, separators=(",", ":")))
|
|
assert used <= 700 and compact["context_budget"]["used_tokens"] == used
|
|
assert compact["complete"] is False and compact["truncated"] is True
|
|
assert "llm_context_budget" in compact["truncation_reasons"]
|
|
assert "KONIEC ZDROJA S1" in compact["context"]
|
|
assert compact["source_count"] == 1 and "[OBSAH ZDROJA OREZANÝ]" in compact["context"]
|
|
assert json.loads(compact["context"].splitlines()[1])["truncated"] is True
|
|
|
|
|
|
def test_diagnostics_are_explicit_and_never_forwarded_by_projection():
|
|
verbose = compact_rag_payload(response(), include_diagnostics=True)
|
|
assert verbose["diagnostics"]["sources"][0]["query_evidence"]
|
|
projected = compact_rag_payload(verbose)
|
|
assert "diagnostics" not in projected
|
|
assert "huge_diagnostic" not in json.dumps(projected)
|
|
|
|
|
|
def test_http_serialization_stays_within_budget_and_diagnostics_are_opt_in(monkeypatch):
|
|
from fastapi.testclient import TestClient
|
|
import app.main as main
|
|
import app.routes as routes
|
|
|
|
original = response("Dlhý dôkaz 🐈 " * 1800)
|
|
monkeypatch.setattr(main, "embed_query", lambda _: None)
|
|
monkeypatch.setattr(routes, "build_rag_context", lambda *a, **kw: original)
|
|
monkeypatch.setenv("RAG_LLM_MAX_TOKENS", "700")
|
|
with TestClient(main.app) as client:
|
|
headers = {"X-API-Key": "a" * 64}
|
|
compact = client.post("/rag", json={"query": "Práca?"}, headers=headers)
|
|
assert compact.status_code == 200
|
|
assert TOKEN_COUNTER.count(compact.text) <= 700
|
|
assert "diagnostics" not in compact.json()
|
|
assert "text" not in compact.json()["sources"][0]
|
|
verbose = client.post(
|
|
"/rag", json={"query": "Práca?", "include_diagnostics": True}, headers=headers
|
|
)
|
|
assert verbose.status_code == 200 and verbose.json()["diagnostics"] == original
|