Files

331 lines
10 KiB
Python

from __future__ import annotations
from core.turn_types import GenerationRunResult
from services.generation_execution_service import GenerationExecutionService
from services.turn_execution_service import (
SessionChatNodeExecutionDependencies,
SessionChatNodeExecutionRequest,
SessionChatNodeExecutionService,
TurnExecutionRequest,
TurnExecutionResult,
TurnExecutionService,
)
from turn_execution_helpers import (
DummyManager,
DummyLogRequest,
_base_deps,
_capture_generation_kwargs,
_make_request,
)
import pytest
def test_execute_from_node_inputs_matches_execute_turn_path() -> None:
service = TurnExecutionService()
mgr = DummyManager()
history = {"turns": [], "summary": {"enabled": False, "text": ""}, "meta": {}}
deps, writes = _base_deps(
history,
run_generation_result=GenerationRunResult(
assistant_text="assistant reply",
gen_tokens=64,
turns_limit=12,
last_err=None,
succeeded=True,
non_ctx_error=False,
),
)
result = service.execute_from_node_inputs(
user_text="hello",
session_id="sid",
model="model.gguf",
mmproj="(Auto detect)",
system_prompt="sys",
max_tokens=64,
temperature=0.7,
top_p=0.9,
n_gpu_layers=0,
n_ctx=1024,
media=None,
max_turns=12,
summarize_old_history=True,
summary_chunk_turns=3,
max_tokens_summary=128,
summary_max_chars=1500,
dynamic_max_tokens=True,
min_generation_tokens=96,
safety_margin_tokens=64,
persistent_cache="off",
repeat_penalty=1.12,
repeat_last_n=256,
rewrite_continue=True,
runtime_cache="off",
log_level="timing",
suppress_backend_logs=True,
history_dir="",
reset_session=False,
stream_to_console=False,
model_manager=mgr,
chat_handler_overrides=None,
text_chat_builder_overrides=None,
strip_assistant_before_reasoning_filter=False,
include_media_and_stream_in_turn_params=True,
kv_log_saved_when_not_minimal=False,
kv_log_unsupported_when_not_minimal=False,
include_error_in_invalidate_message=False,
enable_attempt_logging=False,
log_prefix="[LLM Session Chat]",
dependencies=deps,
)
assert result.generation_succeeded is True
assert result.assistant_text == "assistant reply"
assert writes and writes[0][0] == "hist.json"
def test_execute_session_chat_turn_adds_media_stream_params() -> None:
service = TurnExecutionService()
mgr = DummyManager()
history = {"turns": [], "summary": {"enabled": False, "text": ""}, "meta": {}}
deps, _writes = _base_deps(
history,
run_generation_result=GenerationRunResult(
assistant_text="assistant reply",
gen_tokens=64,
turns_limit=12,
last_err=None,
succeeded=True,
non_ctx_error=False,
),
)
result = service.execute_session_chat_turn(
user_text="hello",
session_id="sid",
model="model.gguf",
mmproj="(Auto detect)",
system_prompt="sys",
max_tokens=64,
temperature=0.7,
top_p=0.9,
n_gpu_layers=0,
n_ctx=1024,
media=None,
max_turns=12,
summarize_old_history=True,
summary_chunk_turns=3,
max_tokens_summary=128,
summary_max_chars=1500,
dynamic_max_tokens=True,
min_generation_tokens=96,
safety_margin_tokens=64,
persistent_cache="off",
repeat_penalty=1.12,
repeat_last_n=256,
rewrite_continue=True,
runtime_cache="off",
log_level="timing",
suppress_backend_logs=True,
history_dir="",
reset_session=False,
stream_to_console=False,
model_manager=mgr,
chat_handler_overrides=None,
text_chat_builder_overrides=None,
dependencies=deps,
)
assert result.generation_succeeded is True
params = history["turns"][0]["params"]
assert params["image_used"] is False
assert params["image_count"] == 0
assert params["audio_used"] is False
assert params["audio_format"] == ""
assert "streamed" in params
user = history["turns"][0]["user"]
assert "image_note" in user
assert "audio_note" in user
assert "media_note" not in user
def test_execute_session_chat_turn_records_image_media_params() -> None:
service = TurnExecutionService()
mgr = DummyManager()
history = {"turns": [], "summary": {"enabled": False, "text": ""}, "meta": {}}
deps, _writes = _base_deps(
history,
run_generation_result=GenerationRunResult(
assistant_text="assistant reply",
gen_tokens=64,
turns_limit=12,
last_err=None,
succeeded=True,
non_ctx_error=False,
),
)
request = _make_request(deps, mgr)
media = type("ImageMedia", (), {"shape": (3, 16, 16, 3)})()
request = TurnExecutionRequest(**{**request.__dict__, "media": media})
result = service.execute_turn(request)
assert result.generation_succeeded is True
params = history["turns"][0]["params"]
assert params["image_used"] is True
assert params["image_count"] == 3
assert params["audio_used"] is False
assert params["audio_format"] == ""
def test_execute_session_chat_turn_records_audio_media_params() -> None:
service = TurnExecutionService()
mgr = DummyManager()
history = {"turns": [], "summary": {"enabled": False, "text": ""}, "meta": {}}
deps, _writes = _base_deps(
history,
run_generation_result=GenerationRunResult(
assistant_text="assistant reply",
gen_tokens=64,
turns_limit=12,
last_err=None,
succeeded=True,
non_ctx_error=False,
),
)
request = _make_request(deps, mgr)
request = TurnExecutionRequest(**{**request.__dict__, "media": {"waveform": object(), "sample_rate": 16000}})
result = service.execute_turn(request)
assert result.generation_succeeded is True
params = history["turns"][0]["params"]
assert params["image_used"] is False
assert params["image_count"] == 0
assert params["audio_used"] is True
assert params["audio_format"] == "wav"
def test_execute_dialogue_cycle_turn_strips_and_omits_media_stream_params() -> None:
service = TurnExecutionService()
mgr = DummyManager()
history = {"turns": [], "summary": {"enabled": False, "text": ""}, "meta": {}}
deps, _writes = _base_deps(
history,
run_generation_result=GenerationRunResult(
assistant_text=" assistant reply ",
gen_tokens=64,
turns_limit=12,
last_err=None,
succeeded=True,
non_ctx_error=False,
),
)
result = service.execute_dialogue_cycle_turn(
user_text="hello",
session_id="sid",
model="model.gguf",
mmproj="(Auto detect)",
system_prompt="sys",
max_tokens=64,
temperature=0.7,
top_p=0.9,
n_gpu_layers=0,
n_ctx=1024,
media=None,
max_turns=12,
summarize_old_history=True,
summary_chunk_turns=3,
max_tokens_summary=128,
summary_max_chars=1500,
dynamic_max_tokens=True,
min_generation_tokens=96,
safety_margin_tokens=64,
persistent_cache="off",
repeat_penalty=1.12,
repeat_last_n=256,
rewrite_continue=True,
runtime_cache="off",
log_level="timing",
suppress_backend_logs=True,
history_dir="",
reset_session=False,
stream_to_console=False,
model_manager=mgr,
chat_handler_overrides=None,
text_chat_builder_overrides=None,
dependencies=deps,
)
assert result.generation_succeeded is True
assert result.assistant_text == "assistant reply"
params = history["turns"][0]["params"]
assert "image_used" not in params
assert "audio_used" not in params
assert "streamed" not in params
def test_execute_session_chat_turn_sets_profile_flags() -> None:
service = TurnExecutionService()
captured: dict[str, object] = {}
def _spy_execute_from_node_inputs(**kwargs):
captured.update(kwargs)
return "ok"
service.execute_from_node_inputs = _spy_execute_from_node_inputs # type: ignore[method-assign]
result = service.execute_session_chat_turn(user_text="hello")
assert result == "ok"
assert captured["strip_assistant_before_reasoning_filter"] is False
assert captured["include_media_and_stream_in_turn_params"] is True
assert captured["kv_log_saved_when_not_minimal"] is False
assert captured["kv_log_unsupported_when_not_minimal"] is False
assert captured["include_error_in_invalidate_message"] is False
assert captured["enable_attempt_logging"] is True
assert captured["log_prefix"] == "[LLM Session Chat]"
def test_execute_dialogue_cycle_turn_sets_profile_flags() -> None:
service = TurnExecutionService()
captured: dict[str, object] = {}
def _spy_execute_from_node_inputs(**kwargs):
captured.update(kwargs)
return "ok"
service.execute_from_node_inputs = _spy_execute_from_node_inputs # type: ignore[method-assign]
result = service.execute_dialogue_cycle_turn(user_text="hello")
assert result == "ok"
assert captured["strip_assistant_before_reasoning_filter"] is True
assert captured["include_media_and_stream_in_turn_params"] is False
assert captured["kv_log_saved_when_not_minimal"] is True
assert captured["kv_log_unsupported_when_not_minimal"] is True
assert captured["include_error_in_invalidate_message"] is True
assert captured["enable_attempt_logging"] is True
assert captured["log_prefix"] == "[LLM Dialogue Cycle]"
def test_execute_dialogue_cycle_turn_accepts_log_prefix_override() -> None:
service = TurnExecutionService()
captured: dict[str, object] = {}
def _spy_execute_from_node_inputs(**kwargs):
captured.update(kwargs)
return "ok"
service.execute_from_node_inputs = _spy_execute_from_node_inputs # type: ignore[method-assign]
result = service.execute_dialogue_cycle_turn(
user_text="hello",
log_prefix_override="[LLM Dialogue Cycle A/1]",
)
assert result == "ok"
assert captured["enable_attempt_logging"] is True
assert captured["log_prefix"] == "[LLM Dialogue Cycle A/1]"
assert "log_prefix_override" not in captured