conversation_model_acceptance.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import asyncio
  2. from uuid import UUID
  3. import pytest
  4. from sqlalchemy import select
  5. from test_after_sales import scenario # noqa: F401
  6. from test_conversations import setup
  7. from zhifu.core.errors import BusinessError
  8. from zhifu.modules.agent_runtime.config import AgentSettings
  9. from zhifu.modules.agent_runtime.models import AgentRun, ModelAttempt
  10. from zhifu.modules.agent_runtime.worker import execute_one
  11. async def test_real_model_uses_previous_conversation(scenario): # noqa: F811
  12. path = await setup(scenario)
  13. app = scenario["app"]
  14. for text in ("我的商品是键盘,先记住这个信息。", "我上一条消息说的商品是什么?"):
  15. response = await scenario["call"](
  16. "POST", path + "/messages", payload={"text": text, "expected_control_version": 1}
  17. )
  18. assert response.status_code == 201, response.text
  19. assert await execute_one(app.state.sessions, app.state.state, AgentSettings())
  20. response = await scenario["call"]("GET", path + "/messages")
  21. answers = [event for event in response.json()["items"] if event["type"] == "message.assistant"]
  22. assert len(answers) == 2 and "键盘" in answers[-1]["payload"]["text"]
  23. response = await scenario["call"]("GET", path)
  24. assert response.json()["active_run_id"] is None
  25. async def test_takeover_during_real_model_request_rejects_late_answer(scenario): # noqa: F811
  26. path = await setup(scenario)
  27. app = scenario["app"]
  28. response = await scenario["call"](
  29. "POST",
  30. path + "/messages",
  31. payload={"text": "请说明申请售后时需要提供哪些信息。", "expected_control_version": 1},
  32. )
  33. run_id = UUID(response.json()["payload"]["run_id"])
  34. task = asyncio.create_task(execute_one(app.state.sessions, app.state.state, AgentSettings()))
  35. try:
  36. async with asyncio.timeout(10):
  37. while True:
  38. async with app.state.sessions() as session:
  39. attempt = await session.scalar(
  40. select(ModelAttempt).where(ModelAttempt.run_id == run_id.bytes)
  41. )
  42. if attempt:
  43. break
  44. await asyncio.sleep(0.02)
  45. response = await scenario["call"](
  46. "POST", path + "/takeover", "agent", {"expected_control_version": 1}
  47. )
  48. assert response.status_code == 200
  49. with pytest.raises(BusinessError, match="控制权已变更"):
  50. await task
  51. finally:
  52. if not task.done():
  53. task.cancel()
  54. await asyncio.gather(task, return_exceptions=True)
  55. async with app.state.sessions() as session:
  56. run = await session.get(AgentRun, run_id.bytes)
  57. assert run.status == "CANCELLED"
  58. response = await scenario["call"]("GET", path + "/messages")
  59. assert all(event["type"] != "message.assistant" for event in response.json()["items"])