assistant/tests/test_intent_grounding_d38.py

133 lines
6.8 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""User-bound scopes and result requirements, without model/platform calls."""
from copy import deepcopy
import pytest
from backend.prospecting.contracts import ProspectingBrief, TARGET_QUESTION
from backend.prospecting.dialogue import _ground_scope, reground_requirements
REQUEST = (
"我提供杭州装修服务,请在小红书找2位本人明确表达装修或设计服务需求的候选,优先查看评论和回复。"
"按人去重,整理需求原话、来源链接和主页入口;页面可见的小红书号能取得就记录,没有就说明。"
"最后导出名单,只做阅读和整理,不关注、不私信。遇到平台限制就停下来告诉我,保留已有成果。"
)
def ground(message, *, current=None, history=None, proposed=None):
return _ground_scope(proposed or ProspectingBrief(target_candidates=99,
required_result_fields=["csv", "xiaohongshu_id", "explicit_demand"]),
current or ProspectingBrief(), message, history or [])
def test_exact_real_request_keeps_count_and_explicit_demand_while_account_remains_optional():
actual = ground(REQUEST)
assert actual.target_candidates == 2 and TARGET_QUESTION not in actual.missing()
assert actual.required_result_fields == ["csv", "explicit_demand"]
assert actual.region is None # Merchant location is not a new geographic filter.
assert actual.max_notes is None and actual.max_comments_per_note is None
@pytest.mark.parametrize("message,count", [
("找3位正在准备装修的客户", 3),
("请寻找4名本人提出设计需求的潜在客户", 4),
("整理5个最近正在比较装修公司的真实用户", 5),
("收集6条已经明确表示要找设计服务的线索", 6),
("先找2位预算在10万元并且正在装修的客户", 2),
("找2位有需求的候选,改成3位", 3),
("先找3位客户,最后给我2位本人明确表达需求的候选", 2),
("例如找8位客户,实际先找2位有装修需求的候选", 2),
])
def test_quantity_binds_unit_and_described_person_object(message, count):
assert ground(message).target_candidates == count
@pytest.mark.parametrize("message", [
"预算300元,找本人有装修需求的客户",
"我做iPhone15配件,找本人明确需求的客户",
"目标是20人以上的公司,找有需求的客户",
"我们有2位同事,请找本人表达需求的候选",
"需要3位员工负责找客户,人数暂没定",
"找2个装修套餐并整理有需求的客户",
"找2位或3位有明确需求的候选",
"找2到3位有明确需求的候选",
"找2位有明确需求的候选到3位候选",
"不要帮我找2位有明确需求的候选,先讨论方案",
"比如找2位有明确需求的候选,实际数量还没决定",
"‘找2位本人明确表达需求的候选’是引用,帮我找客户",
"『找2位本人明确表达需求的候选』是示例,帮我找客户",
"`找2位本人明确表达需求的候选` 是代码示例,帮我找客户",
"```python\n找2位本人明确表达需求的候选\n```\n帮我找客户",
])
def test_unrelated_or_unconfirmed_quantities_cannot_be_used_as_target(message):
assert ground(message).target_candidates is None
@pytest.mark.parametrize("message", [
"页面可见的小红书号能取得就记录,没有就说明",
"小红书号有则填,无则空",
"取得小红书号就记录,获取不到则留空",
"小红书号最好取得,但拿不到也不影响交付",
"整理小红书号,找不到就标注未知",
"账号可选,名单继续保留",
"小红书号不是必须,没有也可以",
])
def test_conditional_account_recording_is_optional_and_removes_old_compiled_requirement(message):
current = ProspectingBrief(target_candidates=1, required_result_fields=["xiaohongshu_id"])
result = ground(message, current=current)
assert "xiaohongshu_id" not in result.required_result_fields
assert result.target_candidates == 1
@pytest.mark.parametrize("message", [
"必须取得小红书号,没有小红书号的人不计入",
"整理2个页面可见小红书号",
"需要提供正确归属的小红书号",
"有小红书号才算候选",
"只有取得小红书号才计入名单",
"必须有小红书号,拿不到也要继续找",
"必须有小红书号,没有就说明缺失",
"必须取得小红书号后再记录",
])
def test_explicit_account_requirement_is_not_weakened(message):
assert "xiaohongshu_id" in ground(message).required_result_fields
@pytest.mark.parametrize("message,fields", [
("找2位本人明确表达装修或设计服务需求的候选", {"explicit_demand"}),
("找2位候选,要求本人明确表达装修或设计服务需求", {"explicit_demand"}),
("目标客户:本人明确表达装修或设计服务需求的用户", {"explicit_demand"}),
("优先找有明确需求的人", set()),
("不一定有明确需求,相关信号也保留", set()),
("告诉我用户有没有明确需求", set()),
("小红书号可选,但必须导出CSV", {"csv"}),
("CSV可选,但必须提供小红书号", {"xiaohongshu_id"}),
])
def test_requirement_subject_and_optional_mode_stay_with_their_own_field(message, fields):
assert set(ground(message).required_result_fields) == fields
def test_revisions_follow_conversation_order_and_assistant_text_cannot_add_requirements():
history = [{"role": "user", "text": "必须有小红书号,只接受本人明确需求"},
{"role": "assistant", "text": "必须导出CSV"},
{"role": "user", "text": "小红书号能取得就记录,没有就说明"}]
result = ground("明确需求也不作为必要条件", history=history)
assert result.required_result_fields == []
revised = ground("这次必须提供小红书号", history=history)
assert set(revised.required_result_fields) == {"explicit_demand", "xiaohongshu_id"}
def test_reground_on_continue_repairs_fields_without_overriding_confirmed_quantity_card():
current = ProspectingBrief(target_candidates=1, required_result_fields=["csv", "xiaohongshu_id"],
product="杭州装修服务", user_notes=REQUEST)
history = [{"role": "user", "text": REQUEST},
{"role": "assistant", "text": TARGET_QUESTION},
{"role": "user", "text": "补充当前任务的信息:\n这次先整理多少位候选?:1"}]
before, saved_history = current.model_dump(), deepcopy(history)
result = reground_requirements(current, history)
assert result.target_candidates == 1
assert result.required_result_fields == ["csv", "explicit_demand"]
assert result.product == current.product and result.user_notes == REQUEST
assert current.model_dump() == before and history == saved_history
assert reground_requirements(result, history) == result