pupunpu's picture
Publish Jev-Interaction
713b429 verified
Raw History Blame Contribute Delete
3.18 kB
"""Stand-ins for every provider, so a call runs with no keys: in tests, in examples, while writing a decision.
from jev_interaction.testing import scripted_session
session, events, judge = scripted_session({"floor": {"carry_on": 0.1, "yield": 0.9}})
The fake judge answers each question it is asked with the probabilities you give for that key (its choice is the
likeliest one) and keeps what it was asked; the fake responder says fixed lines; the fake recognizer yields what you put
on its queue; the fake VAD reports `voice`.
"""
from __future__ import annotations
import asyncio
from collections.abc import Awaitable, Callable
from .adapters.base import Segment
from .config import Config
from .profile import Profile
from .session import Session
class FakeJudge:
def __init__(self, answers: dict[str, dict[str, float]] | None = None):
self.answers, self.asked = dict(answers or {}), []
async def ask(self, questions: dict, state: str) -> dict:
self.asked.append((set(questions), state))
return {k: {"choice": max(v, key=v.get), "probabilities": v} for k, v in self.answers.items() if k in questions}
async def aclose(self) -> None: ...
class FakeRecognizer:
def __init__(self):
self.q: asyncio.Queue[Segment | None] = asyncio.Queue()
def say(self, text: str) -> None:
self.q.put_nowait(Segment(text))
async def connect(self) -> None: ...
async def send(self, pcm: bytes) -> None: ...
async def close(self) -> None:
self.q.put_nowait(None)
async def segments(self):
while (s := await self.q.get()) is not None:
yield s
class FakeResponder:
def __init__(self, lines=("Hey.", "What's up?")):
self.seen: list[list[dict]] = []
self.out = lines
async def lines(self, messages: list[dict], max_tokens: int = 160):
self.seen.append(messages)
for x in self.out:
yield x
class FakeVAD:
def __init__(self):
self.voice = False
def is_voice(self, pcm: bytes) -> bool:
return self.voice
class FakeSynthesizer:
media_type = "audio/mpeg"
async def audio(self, text: str):
yield text.encode("utf-8")
def scripted_session(answers: dict | None = None, policies: dict | None = None, profile: Profile | None = None,
send: Callable[[dict], Awaitable[None]] | None = None, **config) -> tuple[Session, list[dict], FakeJudge]:
"""A session on fakes, plus the list its events land in and its judge. `config` overrides Config fields."""
events: list[dict] = []
async def collect(e: dict) -> None:
events.append(e)
if send:
await send(e)
cfg = Config(policies={**Config().policies, **(policies or {})}, **{"opening_turns": 0, **config})
judge = FakeJudge(answers)
s = Session(profile or Profile("Mara Quinn", task="A companion who chats.", manner="Chatty listener."), send=collect,
judge=judge, recognizer=FakeRecognizer(), responder=FakeResponder(), vad=FakeVAD(), config=cfg)
return s, events, judge
FakeASR, FakeLLM = FakeRecognizer, FakeResponder # the names the tests used