Implement first end-to-end meeting analysis pipeline
This commit is contained in:
@@ -0,0 +1,124 @@
|
||||
import json
|
||||
import tempfile
|
||||
import unittest
|
||||
from pathlib import Path
|
||||
|
||||
from src.meeting_lab.extraction.extract_chunks import (
|
||||
EXTRACTION_CATEGORIES,
|
||||
extraction_path_for_chunk,
|
||||
normalize_current_schema,
|
||||
parse_json_response,
|
||||
)
|
||||
from src.meeting_lab.protocol.build_protocol import build_protocol
|
||||
|
||||
|
||||
class ExtractionProtocolTests(unittest.TestCase):
|
||||
def test_extraction_path_drops_normalized_suffix(self) -> None:
|
||||
path = Path("chunks/chunk_01_normalized.txt")
|
||||
|
||||
self.assertEqual(
|
||||
extraction_path_for_chunk(path),
|
||||
Path("chunks/chunk_01_extraction.json"),
|
||||
)
|
||||
|
||||
def test_normalize_current_schema_maps_legacy_response(self) -> None:
|
||||
result = normalize_current_schema(
|
||||
{
|
||||
"facts": [
|
||||
{
|
||||
"speaker": "A",
|
||||
"statement": "Fact one",
|
||||
"status": "clear",
|
||||
"evidence": "Fact",
|
||||
}
|
||||
],
|
||||
"decisions": [
|
||||
{
|
||||
"decision": "Decision one",
|
||||
"evidence": "Decision",
|
||||
}
|
||||
],
|
||||
"todos": [
|
||||
{
|
||||
"task": "Todo one",
|
||||
"responsible": "B",
|
||||
"deadline": None,
|
||||
"evidence": "Todo",
|
||||
}
|
||||
],
|
||||
"open_questions": [
|
||||
{
|
||||
"question": "Question one",
|
||||
"evidence": "Question",
|
||||
}
|
||||
],
|
||||
"technical_details": [
|
||||
{
|
||||
"subject": "System",
|
||||
"statement": "Technical one",
|
||||
"status": "clear",
|
||||
"evidence": "Technical",
|
||||
}
|
||||
],
|
||||
}
|
||||
)
|
||||
|
||||
self.assertEqual(set(result), set(EXTRACTION_CATEGORIES))
|
||||
self.assertEqual(result["positions"], [])
|
||||
self.assertIn("Fact one", result["facts"][0])
|
||||
self.assertIn("Decision one", result["decisions"][0])
|
||||
self.assertIn("Todo one", result["todos"][0])
|
||||
self.assertIn("Question one", result["questions"][0])
|
||||
self.assertIn("Technical one", result["technical"][0])
|
||||
|
||||
def test_parse_json_response_uses_final_object_after_thinking(self) -> None:
|
||||
text = """
|
||||
Thinking:
|
||||
I will reason about the transcript first.
|
||||
{"facts": ["draft"], "decisions": []}
|
||||
|
||||
Final answer:
|
||||
{
|
||||
"facts": ["final"],
|
||||
"decisions": [],
|
||||
"todos": [],
|
||||
"questions": [],
|
||||
"positions": [],
|
||||
"technical": []
|
||||
}
|
||||
"""
|
||||
|
||||
parsed = parse_json_response(text)
|
||||
|
||||
self.assertEqual(parsed["facts"], ["final"])
|
||||
self.assertEqual(set(parsed), set(EXTRACTION_CATEGORIES))
|
||||
|
||||
def test_build_protocol_groups_extraction_items(self) -> None:
|
||||
with tempfile.TemporaryDirectory() as directory:
|
||||
input_dir = Path(directory)
|
||||
(input_dir / "chunk_01_extraction.json").write_text(
|
||||
json.dumps(
|
||||
{
|
||||
"facts": ["Fact one"],
|
||||
"decisions": ["Decision one"],
|
||||
"todos": ["Todo one"],
|
||||
"questions": ["Question one"],
|
||||
"positions": [],
|
||||
"technical": [],
|
||||
}
|
||||
),
|
||||
encoding="utf-8",
|
||||
)
|
||||
|
||||
output_path = build_protocol(input_dir)
|
||||
|
||||
markdown = output_path.read_text(encoding="utf-8")
|
||||
self.assertIn("# Meeting Protocol", markdown)
|
||||
self.assertIn("## Facts\n- Fact one", markdown)
|
||||
self.assertIn("## Decisions\n- Decision one", markdown)
|
||||
self.assertIn("## Open Questions\n- Question one", markdown)
|
||||
self.assertIn("## Action Items\n- Todo one", markdown)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
Reference in New Issue
Block a user