라이브코치 소스팩 새로고침 보강
This commit is contained in:
parent
84599bbaa2
commit
1e9f293fda
5 changed files with 182 additions and 8 deletions
|
|
@ -2,7 +2,10 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
|
|
@ -24,6 +27,59 @@ class _SourcePackConn:
|
|||
|
||||
|
||||
class LiveCoachSourcePackTest(unittest.TestCase):
|
||||
def test_manifest_refresh_reads_changed_repo_source_pack_after_cache_warm(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
root = Path(temp_root)
|
||||
workbook_path = root / "live_coaching_workbook_0615.json"
|
||||
source_dir = root / "live_coaching_sources"
|
||||
source_dir.mkdir()
|
||||
|
||||
def write_workbook(summary: str) -> None:
|
||||
workbook_path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"source": {
|
||||
"source_id": "source-a",
|
||||
"title": "Source A",
|
||||
"kb_kind": "theory",
|
||||
"license_class": "A",
|
||||
"citation": "source-a",
|
||||
"external_llm_ok": True,
|
||||
},
|
||||
"chunks": [
|
||||
{
|
||||
"id": "chunk-a",
|
||||
"summary": summary,
|
||||
"citation": "source-a",
|
||||
"visible_to": ["evaluator"],
|
||||
}
|
||||
],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with (
|
||||
patch.object(live_coach, "_REPO_ROOT", root),
|
||||
patch.object(live_coach, "_WORKBOOK_PATH", workbook_path),
|
||||
patch.object(live_coach, "_SOURCE_DIR", source_dir),
|
||||
):
|
||||
live_coach.clear_local_source_pack_cache()
|
||||
write_workbook("first source pack summary")
|
||||
_, first_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
|
||||
first_hash = first_payloads[0]["content_hash"]
|
||||
|
||||
write_workbook("changed source pack summary")
|
||||
_, stale_payloads = source_pack_sync.build_repo_source_pack_manifest()
|
||||
self.assertEqual(stale_payloads[0]["content_hash"], first_hash)
|
||||
|
||||
_, refreshed_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
|
||||
self.assertNotEqual(refreshed_payloads[0]["content_hash"], first_hash)
|
||||
self.assertEqual(refreshed_payloads[0]["chunks"][0]["chunk_text"], "changed source pack summary")
|
||||
|
||||
live_coach.clear_local_source_pack_cache()
|
||||
|
||||
def test_source_packs_build_rag_rows_and_index_payloads(self) -> None:
|
||||
rows = live_coach.build_rag_source_rows()
|
||||
payloads = live_coach.build_rag_index_payloads()
|
||||
|
|
@ -85,6 +141,91 @@ class RagIndexPolicyTest(unittest.IsolatedAsyncioTestCase):
|
|||
|
||||
|
||||
class RepoSourcePackSyncTest(unittest.IsolatedAsyncioTestCase):
|
||||
async def test_sync_refresh_after_file_change_reports_next_document_version(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as temp_root:
|
||||
root = Path(temp_root)
|
||||
workbook_path = root / "live_coaching_workbook_0615.json"
|
||||
source_dir = root / "live_coaching_sources"
|
||||
source_dir.mkdir()
|
||||
|
||||
def write_workbook(summary: str) -> None:
|
||||
workbook_path.write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"source": {
|
||||
"source_id": "source-a",
|
||||
"title": "Source A",
|
||||
"kb_kind": "theory",
|
||||
"license_class": "A",
|
||||
"citation": "source-a",
|
||||
"external_llm_ok": True,
|
||||
},
|
||||
"chunks": [
|
||||
{
|
||||
"id": "chunk-a",
|
||||
"summary": summary,
|
||||
"citation": "source-a",
|
||||
"visible_to": ["evaluator"],
|
||||
}
|
||||
],
|
||||
},
|
||||
ensure_ascii=False,
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
with (
|
||||
patch.object(live_coach, "_REPO_ROOT", root),
|
||||
patch.object(live_coach, "_WORKBOOK_PATH", workbook_path),
|
||||
patch.object(live_coach, "_SOURCE_DIR", source_dir),
|
||||
):
|
||||
live_coach.clear_local_source_pack_cache()
|
||||
write_workbook("first source pack summary")
|
||||
_, first_payloads = source_pack_sync.build_repo_source_pack_manifest(refresh=True)
|
||||
first_payload = first_payloads[0]
|
||||
|
||||
write_workbook("changed source pack summary")
|
||||
conn = _SourcePackConn(
|
||||
{
|
||||
("source-a", first_payload["doc_uri"]): {
|
||||
"doc_id": 10,
|
||||
"version": 2,
|
||||
"content_hash": first_payload["content_hash"],
|
||||
}
|
||||
}
|
||||
)
|
||||
result = await source_pack_sync.sync_repo_source_packs(conn, apply=False, refresh=True)
|
||||
|
||||
self.assertFalse(result.applied)
|
||||
self.assertEqual(result.items[0].previous_version, 2)
|
||||
self.assertEqual(result.items[0].new_version, 3)
|
||||
self.assertFalse(result.items[0].skipped_unchanged)
|
||||
self.assertNotEqual(result.items[0].content_hash, first_payload["content_hash"])
|
||||
|
||||
live_coach.clear_local_source_pack_cache()
|
||||
|
||||
def test_manifest_refresh_invalidates_live_coach_source_cache(self) -> None:
|
||||
with (
|
||||
patch.object(source_pack_sync.live_coach, "clear_local_source_pack_cache") as clear_cache,
|
||||
patch.object(source_pack_sync.live_coach, "build_rag_source_rows", return_value=[]) as build_rows,
|
||||
patch.object(source_pack_sync.live_coach, "build_rag_index_payloads", return_value=[]) as build_payloads,
|
||||
):
|
||||
source_pack_sync.build_repo_source_pack_manifest(refresh=True)
|
||||
|
||||
clear_cache.assert_called_once_with()
|
||||
build_rows.assert_called_once_with()
|
||||
build_payloads.assert_called_once_with()
|
||||
|
||||
def test_manifest_default_reuses_live_coach_source_cache(self) -> None:
|
||||
with (
|
||||
patch.object(source_pack_sync.live_coach, "clear_local_source_pack_cache") as clear_cache,
|
||||
patch.object(source_pack_sync.live_coach, "build_rag_source_rows", return_value=[]),
|
||||
patch.object(source_pack_sync.live_coach, "build_rag_index_payloads", return_value=[]),
|
||||
):
|
||||
source_pack_sync.build_repo_source_pack_manifest()
|
||||
|
||||
clear_cache.assert_not_called()
|
||||
|
||||
def _patch_manifest(self) -> Any:
|
||||
row = {
|
||||
"source_id": "source-a",
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue