test_service_voice.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. import unittest
  2. from src.step3_question_answer.recommendation import Recommender
  3. from src.step3_question_answer.knowledge_answers import reference_summary
  4. from src.step3_question_answer.report import markdown, render
  5. from test_recommendation import good_analysis, handoff, retrieval
  6. class ServiceVoiceTests(unittest.TestCase):
  7. def test_policy_summary_has_no_character_rejection(self):
  8. from src.step3_question_answer.cards import summarize
  9. from unittest.mock import Mock
  10. item = Recommender(lambda *args: good_analysis()).answer(handoff(), retrieval())['items'][0]
  11. text = '有效说明。' * 500
  12. model = Mock(return_value={'text': text, 'source_ids': [item['source_id']]})
  13. summary = summarize(model, '政策内容', [item], [], conversation_kind='policy_overview')
  14. self.assertEqual(summary['status'], 'generated')
  15. self.assertEqual(summary['text'], text)
  16. model.assert_called_once()
  17. def test_grounded_summary_leads_answer_and_markdown_actions_stay_last(self):
  18. lead = '您想学技能,可以先了解职业培训支持。'
  19. def model(instruction, data):
  20. if 'cards' in data:
  21. return {'text': lead + '\n\n### 可以先了解的支持\n\n- **职业培训**:提供培训服务。',
  22. 'source_ids': [data['cards'][0]['source_id']]}
  23. return good_analysis()
  24. result = Recommender(model).answer(handoff(), retrieval())
  25. self.assertEqual(result['overview'], lead)
  26. self.assertTrue(result['summary']['text'].startswith(lead))
  27. self.assertEqual(result['summary']['text'].count('### 下一步建议'), 1)
  28. self.assertLess(result['summary']['text'].index('### 可以先了解'), result['summary']['text'].index('### 下一步建议'))
  29. self.assertNotIn('由模型', result['overview'])
  30. self.assertEqual(result['items'][0]['is_policy_library'], True)
  31. html = render(result)
  32. self.assertIn('<h3>可以先了解的支持</h3>', html)
  33. self.assertIn('<strong>职业培训</strong>', html)
  34. self.assertIn('<ol>', html)
  35. def test_summary_failure_uses_existing_cited_answer_as_opening(self):
  36. result = Recommender(lambda *args: good_analysis()).answer(handoff(), retrieval())
  37. self.assertEqual(result['summary']['status'], 'fallback')
  38. self.assertEqual(result['overview'], good_analysis()['answer'])
  39. self.assertIn('### 可以先了解的支持', result['summary']['text'])
  40. def test_exact_qa_answer_without_source_appendix_or_rewriting(self):
  41. answer = '可以线上提交;特殊事项除外。'
  42. result = reference_summary([{'source_id': 'qa', 'title': '合成材料问题', 'answer': answer,
  43. 'citations': [{'path': '/data/answer', 'quote': answer}], 'exact_qa': True}])
  44. self.assertTrue(result['text'].startswith('> ' + answer))
  45. self.assertEqual(result['citations'][0]['quote'], answer)
  46. self.assertEqual(result['text'], '> ' + answer)
  47. def test_markdown_does_not_activate_html_images_or_links(self):
  48. html = markdown('### 标题\n\n<script>bad()</script>\n\n![图片](https://example.invalid/a.png)\n\n[链接](javascript:bad())')
  49. self.assertIn('<h3>标题</h3>', html)
  50. self.assertNotIn('<script>', html)
  51. self.assertNotIn('<img', html)
  52. self.assertNotIn('<a ', html)
  53. def test_overview_summary_rejects_unrequested_qualification_question(self):
  54. def model(instruction, data):
  55. if 'cards' in data:
  56. self.assertEqual(data['conversation_kind'], 'policy_overview')
  57. return {'text': '您是否在本区登记?', 'source_ids': [data['cards'][0]['source_id']]}
  58. value = good_analysis()
  59. value['answer'] = '这项服务提供职业技能培训。'
  60. return value
  61. result = Recommender(model).answer({**handoff(), 'conversation_kind': 'policy_overview'}, retrieval())
  62. self.assertEqual(result['summary']['status'], 'fallback')
  63. self.assertNotIn('您是否', result['summary']['text'])
  64. self.assertEqual(result['next_actions'], [])
  65. def test_supplied_fact_downgrade_does_not_create_generic_reconfirmation(self):
  66. from src.step3_question_answer.recommendation import validate_analysis, evidence_units
  67. from test_recommendation import RECORD
  68. analysis = good_analysis()
  69. analysis['conditions'][0].update(status='满足', question='', user_evidence='我失业了')
  70. result = validate_analysis(analysis, evidence_units(RECORD), {'question': handoff()['original_question']})
  71. self.assertEqual(result['conditions'][0]['status'], '待确认')
  72. self.assertEqual(result['conditions'][0]['question'], '')