feat: relationship-seed service for first-co-appearance prompt
This commit is contained in:
@@ -0,0 +1,109 @@
|
||||
"""Tests for the relationship-seed service (T38).
|
||||
|
||||
Per Requirements §5.2, when two bots first co-appear in a chat, the user
|
||||
is prompted with "Have they met before? If yes, write a short prose
|
||||
seed." The prose is parsed via classifier into structured directed-edge
|
||||
content for the ``botA -> botB`` and ``botB -> botA`` edges.
|
||||
|
||||
These tests cover:
|
||||
|
||||
* The happy path: a canned classifier response parses cleanly into a
|
||||
populated :class:`RelationshipSeed` with both directions filled.
|
||||
* Empty prose short-circuits before any classifier call (mock has no
|
||||
canned responses; an accidental call would raise ``IndexError``).
|
||||
* Whitespace-only prose has the same short-circuit behavior.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
|
||||
import pytest
|
||||
|
||||
from chat.llm.mock import MockLLMClient
|
||||
from chat.services.relationship_seed import (
|
||||
RelationshipSeed,
|
||||
seed_inter_bot_edges,
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_seed_parses_canned_prose():
|
||||
canned = json.dumps(
|
||||
{
|
||||
"a_to_b_summary": "old college friend who now distrusts him slightly",
|
||||
"a_to_b_knowledge_facts": [
|
||||
"studied physics together",
|
||||
"lost touch after a falling out",
|
||||
],
|
||||
"a_to_b_affinity_delta": 2,
|
||||
"a_to_b_trust_delta": -1,
|
||||
"b_to_a_summary": "former roommate; warm memories, mild resentment",
|
||||
"b_to_a_knowledge_facts": ["lived together junior year"],
|
||||
"b_to_a_affinity_delta": 3,
|
||||
"b_to_a_trust_delta": 0,
|
||||
}
|
||||
)
|
||||
mock = MockLLMClient(canned=[canned])
|
||||
result = await seed_inter_bot_edges(
|
||||
mock,
|
||||
classifier_model="x",
|
||||
bot_a_id="bot_a",
|
||||
bot_a_name="Alice",
|
||||
bot_b_id="bot_b",
|
||||
bot_b_name="Bob",
|
||||
relationship_prose=(
|
||||
"Alice and Bob met in college. They studied physics together and "
|
||||
"lived as roommates junior year, but drifted apart after a fight."
|
||||
),
|
||||
)
|
||||
assert isinstance(result, RelationshipSeed)
|
||||
assert (
|
||||
result.a_to_b_summary
|
||||
== "old college friend who now distrusts him slightly"
|
||||
)
|
||||
assert result.a_to_b_knowledge_facts == [
|
||||
"studied physics together",
|
||||
"lost touch after a falling out",
|
||||
]
|
||||
assert result.a_to_b_affinity_delta == 2
|
||||
assert result.a_to_b_trust_delta == -1
|
||||
assert (
|
||||
result.b_to_a_summary
|
||||
== "former roommate; warm memories, mild resentment"
|
||||
)
|
||||
assert result.b_to_a_knowledge_facts == ["lived together junior year"]
|
||||
assert result.b_to_a_affinity_delta == 3
|
||||
assert result.b_to_a_trust_delta == 0
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_seed_empty_prose_returns_empty():
|
||||
"""Empty prose short-circuits — classifier must not be called."""
|
||||
mock = MockLLMClient(canned=[])
|
||||
result = await seed_inter_bot_edges(
|
||||
mock,
|
||||
classifier_model="x",
|
||||
bot_a_id="bot_a",
|
||||
bot_a_name="Alice",
|
||||
bot_b_id="bot_b",
|
||||
bot_b_name="Bob",
|
||||
relationship_prose="",
|
||||
)
|
||||
assert result == RelationshipSeed()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_seed_whitespace_only_prose_returns_empty():
|
||||
"""Whitespace-only prose is treated the same as empty."""
|
||||
mock = MockLLMClient(canned=[])
|
||||
result = await seed_inter_bot_edges(
|
||||
mock,
|
||||
classifier_model="x",
|
||||
bot_a_id="bot_a",
|
||||
bot_a_name="Alice",
|
||||
bot_b_id="bot_b",
|
||||
bot_b_name="Bob",
|
||||
relationship_prose=" \n ",
|
||||
)
|
||||
assert result == RelationshipSeed()
|
||||
Reference in New Issue
Block a user