generated from kgod/ai-review-template
feat: initialize resume agent with OfferPai sync
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
"""Detail-path guards: skip intents never pollute drafts; LLM gate routes before fact-merge."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from types import SimpleNamespace
|
||||
from typing import Any
|
||||
|
||||
from app.builder_conversation.candidate import _candidate_rewrite
|
||||
from app.builder_conversation.predicates import _is_no_information_reply
|
||||
from app.builder_conversation.rescue import llm_detail_route
|
||||
from app.chat_intents import ChatTurnClassification
|
||||
from builder_flow_helpers import create_builder_session, send_message, start_education
|
||||
from test_api import active_component
|
||||
|
||||
|
||||
class _StubClassifier:
|
||||
def __init__(self, result: ChatTurnClassification) -> None:
|
||||
self.result = result
|
||||
|
||||
def classify(self, message: str, *, state_summary: dict[str, Any]) -> ChatTurnClassification:
|
||||
return self.result
|
||||
|
||||
|
||||
def _agent(classifier: Any) -> Any:
|
||||
return SimpleNamespace(
|
||||
expander=SimpleNamespace(expand=lambda entry, *, context: {}),
|
||||
_chat_intent_classifier=classifier,
|
||||
)
|
||||
|
||||
|
||||
def _profile_with_draft() -> dict[str, Any]:
|
||||
return {
|
||||
"job_type": "campus",
|
||||
"builder": {
|
||||
"active_section": "education",
|
||||
"identity_draft": {"school": "X 大学", "description": "完成数据库课程项目。"},
|
||||
"gap_state": {"asked": ["academic_result"], "skipped": [], "rounds": 1},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
def test_skip_words_count_as_no_information() -> None:
|
||||
for word in ("跳过", "先跳过", "跳过吧", "不用了", "不需要", "以后再说", "没有了"):
|
||||
assert _is_no_information_reply(word), word
|
||||
|
||||
|
||||
def test_skip_reply_does_not_pollute_description(client: Any) -> None:
|
||||
session_id, body = create_builder_session(client)
|
||||
start_education(client, session_id, body)
|
||||
send_message(client, session_id, "完成数据库课程项目。") # triggers the gap prompt
|
||||
reply = send_message(client, session_id, "跳过")
|
||||
card = active_component(reply)["data"]
|
||||
assert card["component"] == "experience_confirm_card"
|
||||
assert "跳过" not in str(card["value"].get("description") or "")
|
||||
|
||||
|
||||
def test_detail_gate_no_info_skips_gap_without_merging() -> None:
|
||||
agent = _agent(_StubClassifier(ChatTurnClassification(intent="no_info", confidence=0.9)))
|
||||
transition = llm_detail_route(agent, _profile_with_draft(), "先跳过这个")
|
||||
|
||||
assert transition is not None
|
||||
state = transition.profile["builder"]
|
||||
assert "先跳过这个" not in state["identity_draft"]["description"]
|
||||
assert "academic_result" in state["gap_state"]["skipped"]
|
||||
|
||||
|
||||
def test_detail_gate_revise_regenerates_candidate() -> None:
|
||||
agent = _agent(_StubClassifier(ChatTurnClassification(
|
||||
intent="revise_proposal", confidence=0.9, revision_instruction="再简洁一点",
|
||||
)))
|
||||
transition = llm_detail_route(agent, _profile_with_draft(), "帮我再精简下")
|
||||
|
||||
assert transition is not None
|
||||
assert transition.profile["builder"]["pending_entry"]["_proposal"] is not None
|
||||
assert "帮我再精简下" not in transition.profile["builder"]["identity_draft"]["description"]
|
||||
|
||||
|
||||
def test_detail_gate_chitchat_does_not_merge() -> None:
|
||||
agent = _agent(_StubClassifier(ChatTurnClassification(intent="chitchat", confidence=0.9)))
|
||||
transition = llm_detail_route(agent, _profile_with_draft(), "好的谢谢")
|
||||
|
||||
assert transition is not None
|
||||
assert transition.profile["builder"]["identity_draft"]["description"] == "完成数据库课程项目。"
|
||||
|
||||
|
||||
def test_detail_gate_passes_facts_and_low_confidence_through() -> None:
|
||||
facts = _agent(_StubClassifier(ChatTurnClassification(intent="provide_facts", confidence=0.9)))
|
||||
assert llm_detail_route(facts, _profile_with_draft(), "GPA 4.3") is None
|
||||
shaky = _agent(_StubClassifier(ChatTurnClassification(intent="no_info", confidence=0.4)))
|
||||
assert llm_detail_route(shaky, _profile_with_draft(), "跳过") is None
|
||||
|
||||
|
||||
def test_candidate_rewrite_ensure_facts_appends_missing() -> None:
|
||||
class _Expander:
|
||||
def expand(self, entry: dict[str, Any], *, context: dict[str, Any]) -> dict[str, Any]:
|
||||
return {"optimized_description": "主修课程:数据结构、计算机视觉。", "source": "test"}
|
||||
|
||||
agent = SimpleNamespace(expander=_Expander())
|
||||
proposal = _candidate_rewrite(
|
||||
agent,
|
||||
{"job_type": "campus"},
|
||||
{"description": "学习数据结构、计算机视觉课程。GPA: 4.3/5.0,排名前百分之10。"},
|
||||
"education",
|
||||
ensure_facts=True,
|
||||
)
|
||||
assert "GPA: 4.3/5.0" in proposal["optimized_description"]
|
||||
assert "排名前百分之10" in proposal["optimized_description"]
|
||||
assert proposal["uncovered_facts"] == []
|
||||
Reference in New Issue
Block a user