- Introduced `TemplateService` for managing SQL templates, allowing for parameterized queries based on user input. - Added functionality to automatically reload templates upon asset creation in `analyst.py`. - Enhanced `CacheService` to support table generation bumping, ensuring cache invalidation on data changes. - Updated `RiskRepository` and `GatewayRepository` to trigger cache invalidation for relevant operations. - Expanded `analyst_schemas.py` to include new fields for template tracking in response metadata. - Created seed SQL script for populating initial templates and added unit tests for template rendering logic. This update significantly improves the efficiency of query handling by leveraging SQL templates, reducing reliance on LLM for common queries.
81 lines
2.8 KiB
Python
81 lines
2.8 KiB
Python
"""模板缓存(D-06 第二层)单元测试。"""
|
|
import unittest
|
|
|
|
from app.service.template_service import QueryTemplate, TemplateService
|
|
|
|
|
|
CUSTOMER_COUNT = QueryTemplate(
|
|
template_key="customer_total_count",
|
|
template_sql="SELECT COUNT(*) AS customer_count FROM core_customer",
|
|
params_schema={"match_all": ["客户", "总数"]},
|
|
tags=["客户", "总数"],
|
|
)
|
|
|
|
SUBSCRIBE_DAYS = QueryTemplate(
|
|
template_key="subscribe_amount_recent_days",
|
|
template_sql=(
|
|
"SELECT COALESCE(SUM(amount), 0) AS subscribe_total FROM core_trade "
|
|
"WHERE trade_type = 'subscribe' "
|
|
"AND trade_date >= DATE_SUB(CURDATE(), INTERVAL :days DAY)"
|
|
),
|
|
params_schema={
|
|
"match_all": ["申购", "金额"],
|
|
"params": [{"name": "days", "placeholder": ":days", "extract": "recent_days", "default": 30}],
|
|
},
|
|
tags=["申购", "金额"],
|
|
)
|
|
|
|
|
|
class TestTemplateService(unittest.TestCase):
|
|
def setUp(self):
|
|
self.svc = TemplateService(templates=[CUSTOMER_COUNT, SUBSCRIBE_DAYS])
|
|
|
|
def test_match_customer_count(self):
|
|
hit = self.svc.try_render("平台客户总数是多少", "full", [], ["analyst"])
|
|
self.assertIsNotNone(hit)
|
|
sql, key = hit
|
|
self.assertEqual(key, "customer_total_count")
|
|
self.assertIn("COUNT(*)", sql)
|
|
|
|
def test_match_subscribe_with_days(self):
|
|
hit = self.svc.try_render("近7天申购金额总额", "full", [], ["analyst"])
|
|
self.assertIsNotNone(hit)
|
|
sql, key = hit
|
|
self.assertEqual(key, "subscribe_amount_recent_days")
|
|
self.assertIn("INTERVAL 7 DAY", sql)
|
|
self.assertNotIn(":days", sql)
|
|
|
|
def test_default_days_when_unspecified(self):
|
|
hit = self.svc.try_render("申购金额汇总", "full", [], ["analyst"])
|
|
self.assertIsNotNone(hit)
|
|
sql, _ = hit
|
|
self.assertIn("INTERVAL 30 DAY", sql)
|
|
|
|
def test_no_match_returns_none(self):
|
|
self.assertIsNone(self.svc.try_render("随便问问", "full", [], ["analyst"]))
|
|
|
|
def test_self_domain_injects_customer_id(self):
|
|
tpl = QueryTemplate(
|
|
template_key="self_trade_count",
|
|
template_sql=(
|
|
"SELECT COUNT(*) AS cnt FROM core_trade "
|
|
"WHERE customer_id = ':customer_id'"
|
|
),
|
|
params_schema={
|
|
"match_all": ["交易", "多少"],
|
|
"params": [
|
|
{"name": "customer_id", "placeholder": ":customer_id", "extract": "scope_customer", "default": ""}
|
|
],
|
|
},
|
|
tags=[],
|
|
)
|
|
svc = TemplateService(templates=[tpl])
|
|
hit = svc.try_render("我有多少笔交易", "self", ["CUST-9527"], ["customer"])
|
|
self.assertIsNotNone(hit)
|
|
sql, _ = hit
|
|
self.assertIn("CUST-9527", sql)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|