179 lines
5.7 KiB
Python
179 lines
5.7 KiB
Python
|
|
"""
|
|||
|
|
Unit tests for TemplateEngine.
|
|||
|
|
[AC-IDS-06, AC-IDS-11] Test template variable filling.
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import pytest
|
|||
|
|
|
|||
|
|
from app.services.flow.template_engine import TemplateEngine
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MockLLMClient:
|
|||
|
|
"""Mock LLM client for testing."""
|
|||
|
|
|
|||
|
|
def __init__(self, response: str = "先生"):
|
|||
|
|
self._response = response
|
|||
|
|
|
|||
|
|
async def generate_text(self, prompt: str) -> str:
|
|||
|
|
return self._response
|
|||
|
|
|
|||
|
|
async def generate(self, messages: list) -> "MockResponse":
|
|||
|
|
return MockResponse(self._response)
|
|||
|
|
|
|||
|
|
|
|||
|
|
class MockResponse:
|
|||
|
|
"""Mock LLM response."""
|
|||
|
|
def __init__(self, content: str):
|
|||
|
|
self.content = content
|
|||
|
|
|
|||
|
|
|
|||
|
|
class TestTemplateEngine:
|
|||
|
|
"""[AC-IDS-06, AC-IDS-11] Test cases for TemplateEngine."""
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_no_variables(self):
|
|||
|
|
"""Test template without variables returns as-is."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好,请问有什么可以帮您?",
|
|||
|
|
context=None,
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好,请问有什么可以帮您?"
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_from_context(self):
|
|||
|
|
"""Test filling variables from context."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好{user_name},请问有什么可以帮您?",
|
|||
|
|
context={"user_name": "张先生"},
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好张先生,请问有什么可以帮您?"
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_from_inputs(self):
|
|||
|
|
"""Test filling variables from context inputs."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好,您咨询的是{product}相关的问题吗?",
|
|||
|
|
context={
|
|||
|
|
"inputs": [
|
|||
|
|
{"variable": "product", "input": "手机"},
|
|||
|
|
]
|
|||
|
|
},
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好,您咨询的是手机相关的问题吗?"
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_with_llm(self):
|
|||
|
|
"""Test filling variables using LLM generation."""
|
|||
|
|
llm_client = MockLLMClient(response="先生")
|
|||
|
|
engine = TemplateEngine(llm_client=llm_client)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好{greeting_style},请问您{inquiry_style}?",
|
|||
|
|
context=None,
|
|||
|
|
history=[{"role": "user", "content": "你好"}],
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert "先生" in result
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_multiple_variables(self):
|
|||
|
|
"""Test filling multiple variables."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好{name},您订购的{product}已发货,预计{date}送达。",
|
|||
|
|
context={
|
|||
|
|
"name": "李女士",
|
|||
|
|
"product": "iPhone 15",
|
|||
|
|
"date": "明天",
|
|||
|
|
},
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好李女士,您订购的iPhone 15已发货,预计明天送达。"
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_missing_variable(self):
|
|||
|
|
"""Test handling missing variables with placeholder."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好{unknown_var},请问有什么可以帮您?",
|
|||
|
|
context=None,
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好[unknown_var],请问有什么可以帮您?"
|
|||
|
|
|
|||
|
|
def test_extract_variables(self):
|
|||
|
|
"""Test extracting variable names from template."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
variables = engine.extract_variables(
|
|||
|
|
"您好{name},您订购的{product}预计{date}送达。"
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert variables == ["name", "product", "date"]
|
|||
|
|
|
|||
|
|
def test_extract_variables_empty(self):
|
|||
|
|
"""Test extracting from template without variables."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
variables = engine.extract_variables("您好,请问有什么可以帮您?")
|
|||
|
|
|
|||
|
|
assert variables == []
|
|||
|
|
|
|||
|
|
def test_extract_variables_adjacent(self):
|
|||
|
|
"""Test extracting adjacent variables."""
|
|||
|
|
engine = TemplateEngine(llm_client=None)
|
|||
|
|
|
|||
|
|
variables = engine.extract_variables("{a}{b}{c}")
|
|||
|
|
|
|||
|
|
assert variables == ["a", "b", "c"]
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_with_history_context(self):
|
|||
|
|
"""Test that history is used for LLM prompt."""
|
|||
|
|
llm_client = MockLLMClient(response="贵姓")
|
|||
|
|
engine = TemplateEngine(llm_client=llm_client)
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好,请问您{inquiry_style}?",
|
|||
|
|
context=None,
|
|||
|
|
history=[
|
|||
|
|
{"role": "user", "content": "我想咨询一下"},
|
|||
|
|
{"role": "assistant", "content": "好的,请问您想咨询什么?"},
|
|||
|
|
],
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert "贵姓" in result
|
|||
|
|
|
|||
|
|
@pytest.mark.asyncio
|
|||
|
|
async def test_fill_template_exception_handling(self):
|
|||
|
|
"""Test that exceptions are handled gracefully."""
|
|||
|
|
class FailingLLMClient:
|
|||
|
|
async def generate_text(self, prompt: str) -> str:
|
|||
|
|
raise RuntimeError("LLM service unavailable")
|
|||
|
|
|
|||
|
|
engine = TemplateEngine(llm_client=FailingLLMClient())
|
|||
|
|
|
|||
|
|
result = await engine.fill_template(
|
|||
|
|
template="您好{greeting},请问有什么可以帮您?",
|
|||
|
|
context=None,
|
|||
|
|
history=None,
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
assert result == "您好[greeting],请问有什么可以帮您?"
|