70 lines
3.0 KiB
Python
70 lines
3.0 KiB
Python
import unittest
|
|||
|
|
from pathlib import Path
|
||
|
|
from tempfile import TemporaryDirectory
|
||
|
|
from sqlmodel import SQLModel, Session, create_engine
|
||
|
|
|
||
|
|
from app.agents.composer import validate_consistency_checks
|
||
|
|
from app.agents.coordinator import provider_fingerprint
|
||
|
|
from app.agents.qc import validate_qc_checks
|
||
|
|
from app.models import ModelProvider
|
||
|
|
from app.rag.pipeline import _disk_files
|
||
|
|
from app.rag.store import _as_list, _chunk_id
|
||
|
|
from app.rag.pipeline import release_reserved_chunks, reserve_chunks
|
||
|
|
from array import array
|
||
|
|
|
||
|
|
|
||
|
|
class QualityAndRagTests(unittest.TestCase):
|
||
|
|
def test_empty_qc_is_invalid(self):
|
||
|
|
checks, error = validate_qc_checks([])
|
||
|
|
self.assertEqual(checks, [])
|
||
|
|
self.assertTrue(error)
|
||
|
|
|
||
|
|
def test_qc_requires_named_status(self):
|
||
|
|
checks, error = validate_qc_checks([{"id": "x", "issues": []}])
|
||
|
|
self.assertEqual(checks, [])
|
||
|
|
self.assertTrue(error)
|
||
|
|
|
||
|
|
def test_composer_requires_all_five_fixed_checks(self):
|
||
|
|
checks, error = validate_consistency_checks([])
|
||
|
|
self.assertEqual(checks, [])
|
||
|
|
self.assertTrue(error)
|
||
|
|
|
||
|
|
def test_chunk_id_is_stable(self):
|
||
|
|
item = {"text": " 同一段素材 ", "meta": {"heading": "心法"}}
|
||
|
|
self.assertEqual(_chunk_id("素材.md", item, 1), _chunk_id("素材.md", item, 1))
|
||
|
|
self.assertNotEqual(_chunk_id("素材.md", item, 1), _chunk_id("素材.md", item, 2))
|
||
|
|
|
||
|
|
def test_missing_source_directory_is_an_empty_inventory(self):
|
||
|
|
with TemporaryDirectory() as temp:
|
||
|
|
missing = Path(temp) / "not-created"
|
||
|
|
self.assertEqual(_disk_files(missing), [])
|
||
|
|
|
||
|
|
def test_provider_fingerprint_changes_when_endpoint_changes(self):
|
||
|
|
provider = ModelProvider(id=7, name="gateway", base_url="https://a.example/v1")
|
||
|
|
first = provider_fingerprint(provider, "model-a")
|
||
|
|
self.assertEqual(first, provider_fingerprint(provider, "model-a"))
|
||
|
|
provider.base_url = "https://b.example/v1"
|
||
|
|
self.assertNotEqual(first, provider_fingerprint(provider, "model-a"))
|
||
|
|
|
||
|
|
def test_vector_snapshot_sequences_are_numpy_safe(self):
|
||
|
|
values = array("f", [0.1, 0.2])
|
||
|
|
self.assertEqual(len(_as_list(values)), 2)
|
||
|
|
self.assertAlmostEqual(_as_list(values)[0], 0.1, places=6)
|
||
|
|
self.assertAlmostEqual(_as_list(values)[1], 0.2, places=6)
|
||
|
|
self.assertEqual(_as_list(None), [])
|
||
|
|
|
||
|
|
def test_knowledge_usage_is_unique_per_agent_and_chunk(self):
|
||
|
|
engine = create_engine("sqlite://")
|
||
|
|
SQLModel.metadata.create_all(engine)
|
||
|
|
with Session(engine) as session:
|
||
|
|
hit = {"id": "chunk-1", "kb_id": 3, "text": "素材", "meta": {"file": "a.md"}}
|
||
|
|
self.assertEqual(len(reserve_chunks(session, 10, 20, 30, [hit])), 1)
|
||
|
|
self.assertEqual(len(reserve_chunks(session, 10, 20, 31, [hit])), 0)
|
||
|
|
self.assertEqual(len(reserve_chunks(session, 11, 20, 31, [hit])), 1)
|
||
|
|
release_reserved_chunks(session, 10, 20, 30, [hit])
|
||
|
|
self.assertEqual(len(reserve_chunks(session, 10, 20, 32, [hit])), 1)
|
||
|
|
|
||
|
|
|
||
|
|
if __name__ == "__main__":
|
||
|
|
unittest.main()
|