런타임 계약과 학습자 흐름 보강
This commit is contained in:
parent
f456b8997a
commit
206018b088
56 changed files with 4306 additions and 1008 deletions
110
apps/api/app/test_persona_generation_contract.py
Normal file
110
apps/api/app/test_persona_generation_contract.py
Normal file
|
|
@ -0,0 +1,110 @@
|
|||
"""Regression tests for persona draft generation contract helpers."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import unittest
|
||||
|
||||
from .contracts.engine_gateway import GenerateResponse
|
||||
from . import persona_generation_contract as contract
|
||||
from .persona_read_model import PersonaDraftGenerateRequest
|
||||
|
||||
|
||||
class PersonaGenerationContractTest(unittest.TestCase):
|
||||
def test_persona_generation_schema_pins_required_fields(self) -> None:
|
||||
schema = contract.persona_generation_schema()
|
||||
draft_schema = schema["properties"]["draft"]
|
||||
|
||||
self.assertFalse(schema["additionalProperties"])
|
||||
self.assertEqual(schema["required"], ["draft", "source_summary", "warnings"])
|
||||
self.assertFalse(draft_schema["additionalProperties"])
|
||||
self.assertIn("source_provenance", draft_schema["required"])
|
||||
self.assertEqual(draft_schema["properties"]["difficulty"]["enum"], ["easy", "moderate", "hard"])
|
||||
|
||||
def test_persona_draft_prompt_bundle_is_stable(self) -> None:
|
||||
bundle = contract.persona_draft_prompt_bundle()
|
||||
|
||||
self.assertEqual(bundle["id"], "persona-draft-rag")
|
||||
self.assertEqual(bundle["version"], "2026-06-28.1")
|
||||
self.assertRegex(bundle["hash"], r"^[0-9a-f]{12}$")
|
||||
|
||||
def test_persona_generation_payload_from_response_uses_legacy_json_fallback(self) -> None:
|
||||
response = GenerateResponse(
|
||||
text='```json\n{"source_summary":"요약","warnings":["검수 필요"]}\n```',
|
||||
model="test-model",
|
||||
provider="test-provider",
|
||||
structured=None,
|
||||
)
|
||||
|
||||
payload = contract.persona_generation_payload_from_response(response)
|
||||
|
||||
self.assertEqual(payload["source_summary"], "요약")
|
||||
self.assertEqual(payload["warnings"], ["검수 필요"])
|
||||
|
||||
def test_persona_generation_payload_from_response_returns_empty_dict_for_invalid_output(self) -> None:
|
||||
response = GenerateResponse(text="[1, 2, 3]", model="test-model", provider="test-provider")
|
||||
|
||||
self.assertEqual(contract.persona_generation_payload_from_response(response), {})
|
||||
|
||||
def test_coerce_persona_generated_draft_normalizes_nested_draft(self) -> None:
|
||||
request = PersonaDraftGenerateRequest(
|
||||
source_ids=["persona_authoring_test"],
|
||||
source_kind="client_record",
|
||||
code_hint="p9",
|
||||
display_name_hint="힌트 페르소나",
|
||||
difficulty="hard",
|
||||
theory_target=["CBT"],
|
||||
)
|
||||
|
||||
draft = contract.coerce_persona_generated_draft(
|
||||
{
|
||||
"draft": {
|
||||
"difficulty": "unsupported",
|
||||
"theory_target": [" Humanistic ", ""],
|
||||
"big5": {"O": 0.8, "C": "ignored"},
|
||||
"resistance": {},
|
||||
"affect_baseline": {},
|
||||
"is_synthetic": False,
|
||||
}
|
||||
},
|
||||
request,
|
||||
)
|
||||
|
||||
self.assertEqual(draft.code, "P9")
|
||||
self.assertEqual(draft.display_name, "힌트 페르소나")
|
||||
self.assertEqual(draft.difficulty, "hard")
|
||||
self.assertEqual(draft.theory_target, ["humanistic"])
|
||||
self.assertEqual(draft.big5, {"O": 0.8})
|
||||
self.assertEqual(draft.resistance["base_resistance"], 0.5)
|
||||
self.assertEqual(draft.source_provenance, "masked client_record")
|
||||
self.assertFalse(draft.is_synthetic)
|
||||
self.assertFalse(draft.submit_for_review)
|
||||
|
||||
def test_coerce_persona_generated_draft_accepts_top_level_payload_without_draft(self) -> None:
|
||||
request = PersonaDraftGenerateRequest(
|
||||
source_ids=["persona_authoring_test"],
|
||||
source_kind="mixed_notes",
|
||||
difficulty="moderate",
|
||||
)
|
||||
|
||||
draft = contract.coerce_persona_generated_draft(
|
||||
{
|
||||
"code": "p10",
|
||||
"display_name": "상위 페르소나",
|
||||
"difficulty": "easy",
|
||||
"theory_target": ["CBT"],
|
||||
"demographics": "not-a-dict",
|
||||
"presenting": {"summary": "불안"},
|
||||
},
|
||||
request,
|
||||
)
|
||||
|
||||
self.assertEqual(draft.code, "P10")
|
||||
self.assertEqual(draft.display_name, "상위 페르소나")
|
||||
self.assertEqual(draft.difficulty, "easy")
|
||||
self.assertEqual(draft.theory_target, ["cbt"])
|
||||
self.assertEqual(draft.demographics, {})
|
||||
self.assertEqual(draft.presenting, {"summary": "불안"})
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Loading…
Add table
Add a link
Reference in a new issue