mirror of
http://100.103.83.12:3003/fegger/odoo-at-payroll.git
synced 2026-09-17 16:56:42 +00:00
102 lines
3.2 KiB
Python
102 lines
3.2 KiB
Python
"""Tests für Index-Bootstrap sowie Interaktions- und Bewertungsprotokoll."""
|
|
from __future__ import annotations
|
|
|
|
import dataclasses
|
|
|
|
import pytest
|
|
|
|
from agent.audit import AuditStore
|
|
from agent.bootstrap import ensure_index, index_is_ready
|
|
from agent.config import Config
|
|
|
|
|
|
def interaction_payload() -> dict:
|
|
return {
|
|
"api_version": "v1",
|
|
"request_id": "test-request-1",
|
|
"status": "answered",
|
|
"question": "Was gilt?",
|
|
"answer": "Belegte Antwort [lb-min-01].",
|
|
"refused": False,
|
|
"verified": True,
|
|
"citations": ["lb-min-01"],
|
|
"sources": [{"id": "lb-min-01", "title": "Quelle"}],
|
|
"conflicts": [],
|
|
"planned_queries": [{"text": "Was gilt?"}],
|
|
"model": "test-model",
|
|
"latency_ms": 42,
|
|
"n_context": 1,
|
|
"regenerations": 0,
|
|
}
|
|
|
|
|
|
def test_audit_persists_interaction_and_rating(tmp_path):
|
|
cfg = Config(
|
|
audit_enabled=True,
|
|
audit_db_path=str(tmp_path / "audit.db"),
|
|
audit_retention_days=30,
|
|
)
|
|
store = AuditStore(cfg)
|
|
try:
|
|
store.record_interaction(interaction_payload())
|
|
store.record_rating("test-request-1", "down", "Quelle war nicht passend")
|
|
rows = store.recent()
|
|
finally:
|
|
store.close()
|
|
|
|
assert len(rows) == 1
|
|
assert rows[0]["question"] == "Was gilt?"
|
|
assert rows[0]["answer"].startswith("Belegte Antwort")
|
|
assert rows[0]["citations"] == ["lb-min-01"]
|
|
assert rows[0]["rating"] == "down"
|
|
assert rows[0]["feedback"] == "Quelle war nicht passend"
|
|
|
|
|
|
def test_audit_can_omit_free_text_and_still_log_metadata(tmp_path, capsys):
|
|
cfg = Config(
|
|
audit_enabled=True,
|
|
audit_db_path=str(tmp_path / "audit.db"),
|
|
audit_log_content=False,
|
|
audit_stdout=True,
|
|
)
|
|
store = AuditStore(cfg)
|
|
try:
|
|
store.record_interaction(interaction_payload())
|
|
store.record_rating("test-request-1", "up", "soll nicht gespeichert werden")
|
|
row = store.recent()[0]
|
|
finally:
|
|
store.close()
|
|
|
|
output = capsys.readouterr().out
|
|
assert row["question"] is None
|
|
assert row["answer"] is None
|
|
assert row["feedback"] is None
|
|
assert "Was gilt?" not in output
|
|
assert "soll nicht gespeichert werden" not in output
|
|
assert '"event": "agent_interaction"' in output
|
|
assert '"event": "agent_rating"' in output
|
|
|
|
|
|
def test_rating_requires_existing_interaction(tmp_path):
|
|
store = AuditStore(Config(audit_db_path=str(tmp_path / "audit.db")))
|
|
try:
|
|
with pytest.raises(KeyError):
|
|
store.record_rating("missing", "up", None)
|
|
finally:
|
|
store.close()
|
|
|
|
|
|
def test_bootstrap_recognizes_existing_mini_index(mini_index):
|
|
assert index_is_ready(mini_index) is True
|
|
dense_cfg = dataclasses.replace(mini_index, embed_off=False)
|
|
assert index_is_ready(dense_cfg) is False
|
|
|
|
|
|
def test_bootstrap_builds_missing_index(mini_cfg, tmp_path):
|
|
cfg = dataclasses.replace(mini_cfg, db_path=str(tmp_path / "new-index.db"))
|
|
assert index_is_ready(cfg) is False
|
|
result = ensure_index(cfg)
|
|
assert result["event"] == "index_bootstrap_completed"
|
|
assert index_is_ready(cfg) is True
|
|
assert ensure_index(cfg)["event"] == "index_ready"
|