File size: 2,818 Bytes
0e6887b
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
"""IntentClassifier 测试(intent-understanding-layer 任务 5)。

覆盖需求 3.1–3.4:描述性 / 货架期 / 未知分类,LLM 提示优先与关键词兜底。
"""

from __future__ import annotations

from kernel.task_sheet import DocumentProfile, Intent
from kernel.understanding import IntentClassifier


def _empty_profile():
    return DocumentProfile()


def test_descriptive_by_keyword():
    c = IntentClassifier(llm=None)
    assert c.classify("请帮我梳理各规格样品的质量属性规律", _empty_profile()) is Intent.DESCRIPTIVE_SUMMARY


def test_shelf_life_by_keyword():
    c = IntentClassifier(llm=None)
    assert c.classify("请预测该产品的货架期", _empty_profile()) is Intent.SHELF_LIFE
    assert c.classify("外推 36 个月的稳定性", _empty_profile()) is Intent.SHELF_LIFE


def test_unknown_when_no_keyword():
    c = IntentClassifier(llm=None)
    assert c.classify("这是什么", _empty_profile()) is Intent.UNKNOWN


def test_unknown_when_ambiguous_both():
    c = IntentClassifier(llm=None)
    # 同时含「梳理」与「货架期」→ 交澄清。
    assert c.classify("梳理数据并预测货架期", _empty_profile()) is Intent.UNKNOWN


def test_llm_hint_takes_precedence():
    c = IntentClassifier(llm=None)
    out = c.classify("随便什么", _empty_profile(), llm_hint="descriptive_summary")
    assert out is Intent.DESCRIPTIVE_SUMMARY


def test_invalid_llm_hint_falls_back_to_keyword():
    c = IntentClassifier(llm=None)
    out = c.classify("预测货架期", _empty_profile(), llm_hint="nonsense")
    assert out is Intent.SHELF_LIFE


def test_compatibility_by_keyword():
    c = IntentClassifier(llm=None)
    assert c.classify("评估原料药与辅料的相容性", _empty_profile()) is Intent.COMPATIBILITY
    assert c.classify("API 与乳糖的配伍风险", _empty_profile()) is Intent.COMPATIBILITY


def test_compatibility_by_input_signature():
    """SMILES + 辅料同时存在 → 相容性强信号(优先于关键词)。"""
    c = IntentClassifier(llm=None)
    out = c.classify("", _empty_profile(), has_smiles=True, has_excipient=True)
    assert out is Intent.COMPATIBILITY


def test_smiles_only_leans_compatibility():
    c = IntentClassifier(llm=None)
    out = c.classify("", _empty_profile(), has_smiles=True)
    assert out is Intent.COMPATIBILITY


def test_compatibility_llm_hint():
    c = IntentClassifier(llm=None)
    out = c.classify("随便", _empty_profile(), llm_hint="compatibility")
    assert out is Intent.COMPATIBILITY


def test_shelf_life_not_overridden_by_compat_signal():
    """明确外推意图时不被相容性关键词误夺(无 smiles+excipient 双信号)。"""
    c = IntentClassifier(llm=None)
    assert c.classify("预测货架期", _empty_profile()) is Intent.SHELF_LIFE