优化连续追问的报价条件与订单指代
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
"""Statistics use explicit exception reasons and actual, order-level progress."""
|
||||
|
||||
import json
|
||||
import re
|
||||
from pathlib import Path
|
||||
import sqlite3
|
||||
import tempfile
|
||||
@@ -48,6 +49,7 @@ class OrderStatisticsTests(unittest.TestCase):
|
||||
model.assert_not_called()
|
||||
self.assertEqual(events[-1],{'d':1},events)
|
||||
self.assertNotIn('_order_list_state',str(events));self.assertNotIn('_customer_data',str(events))
|
||||
self.assertNotIn('_order_reference',str(events))
|
||||
self.assertNotIn('SECRET',str(events));self.assertNotIn('不能泄露',str(events))
|
||||
return events[0]
|
||||
|
||||
@@ -155,6 +157,112 @@ class OrderStatisticsTests(unittest.TestCase):
|
||||
self.assertIn('7 票明确标记异常',text)
|
||||
self.assertEqual(text.count('- 入仓码:'),5)
|
||||
|
||||
def test_subset_followups_keep_previous_stage_and_show_recorded_reasons(self):
|
||||
self.assertTrue(self.ask('异常的呢')['login_required'])
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('已清关的订单有多少',cid)
|
||||
text=self.ask('其中异常的呢',cid)['t']
|
||||
self.assertIn('1 票当前节点为“已清关、可提柜”',text)
|
||||
self.assertIn('等待客户资料',text)
|
||||
self.assertNotIn('待核实资料',text)
|
||||
self.assertIn('1 票当前节点',self.ask('这些一共多少票',cid)['t'])
|
||||
text=self.ask('异常原因呢',cid)['t']
|
||||
self.assertIn('等待客户资料',text)
|
||||
self.assertNotIn('业务状态:',text)
|
||||
self.assertIn('共1票',self.ask('查看全部',cid)['t'])
|
||||
|
||||
def test_ordinal_uses_the_displayed_reply_even_when_new_orders_arrive(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
text=self.ask('我有多少异常订单',cid)['t']
|
||||
shown=re.findall(r'^- 入仓码:([^;]+);订单号:([^;]+);',text,re.M)
|
||||
with self.app.app_context():
|
||||
c=db.connect()
|
||||
order_data.import_records(c,[{'tenant_id':'a','order_no':'NEWEST20260001','inbound_code':'NEWESTIN20260001',
|
||||
'status':'PROCESSING','source_updated_at':'2030-01-01','exception_reason':'新记录'}])
|
||||
c.commit();c.close()
|
||||
card=self.ask('第一票的轨迹',cid)['card']
|
||||
self.assertEqual(card['no'],shown[0][1])
|
||||
card=self.ask('第二个呢',cid)['card']
|
||||
self.assertEqual(card['no'],shown[1][1])
|
||||
self.assertNotIn('NEWEST',str(card))
|
||||
|
||||
def test_selected_order_survives_acknowledgements_and_long_detail_followups(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('我有多少异常订单',cid)
|
||||
first=self.ask('第一个呢',cid)['card']['no']
|
||||
for _ in range(8):
|
||||
self.ask('谢谢',cid)
|
||||
text=self.ask('异常原因呢',cid)['t']
|
||||
self.assertNotIn('请提供',text)
|
||||
self.assertEqual(self.ask('重量呢',cid)['card']['no'],first)
|
||||
|
||||
def test_empty_or_out_of_range_ordinals_never_choose_an_unshown_order(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('我有多少异常订单',cid)
|
||||
self.assertIn('展示了5票',self.ask('第6票的轨迹',cid)['t'])
|
||||
self.ask('已还柜的订单有多少',cid)
|
||||
self.assertIn('当前列表没有',self.ask('第一个呢',cid)['t'])
|
||||
self.assertIn('0 票当前节点为“已还柜”',self.ask('到哪了',cid)['t'])
|
||||
|
||||
def test_ordinals_and_subsets_require_the_current_owned_topic_and_login(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('我有多少异常订单',cid)
|
||||
self.ask('美国30KG海运报价',cid)
|
||||
text=self.ask('第一票的轨迹',cid)['t']
|
||||
self.assertIn('请先查看',text)
|
||||
self.assertNotIn('INSTAT',text)
|
||||
self.ask('我有多少异常订单',cid)
|
||||
self.client.post('/api/customer/logout')
|
||||
self.assertTrue(self.ask('第一个呢',cid)['login_required'])
|
||||
self.assertTrue(self.ask('其中异常的呢',cid)['login_required'])
|
||||
|
||||
def test_conflicting_subset_conditions_request_a_scope_change(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('已清关的订单有多少',cid)
|
||||
self.assertIn('确认要切换筛选条件',self.ask('其中已到港的呢',cid)['t'])
|
||||
self.assertIn('10 票当前节点',self.ask('那已到港的呢',cid)['t'])
|
||||
|
||||
def test_subset_clarification_keeps_the_original_scope_for_the_next_answer(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('已清关的订单有多少',cid)
|
||||
self.assertIn('请明确',self.ask('其中今天的异常呢',cid)['t'])
|
||||
self.assertIn('1 票当前节点',self.ask('其中异常的呢',cid)['t'])
|
||||
|
||||
def test_a_shipping_quote_starting_with_these_is_a_new_quote_topic(self):
|
||||
from logistics_chat.quote_data import import_snapshot
|
||||
from test_quotes import fixture_snapshot
|
||||
with self.app.app_context():
|
||||
c=db.connect();import_snapshot(c,fixture_snapshot(),activate=True);c.commit();c.close()
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('我有多少个订单',cid)
|
||||
text=self.ask('这些货物美国30KG海运报价',cid)['t']
|
||||
self.assertIn('美国 30KG',text)
|
||||
self.assertNotIn('订单范围',text)
|
||||
self.assertIn('请先查看',self.ask('第一个订单呢',cid)['t'])
|
||||
|
||||
def test_legacy_list_state_can_resolve_ordinals_without_saved_identifiers(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
text=self.ask('我有多少异常订单',cid)['t']
|
||||
first=re.findall(r'^- 入仓码:([^;]+);订单号:([^;]+);',text,re.M)[0][1]
|
||||
with self.app.app_context():
|
||||
c=db.connect()
|
||||
state=json.loads(c.execute('SELECT order_list_state FROM chat_history WHERE id=?',(cid,)).fetchone()[0])
|
||||
del state['shown']
|
||||
c.execute('UPDATE chat_history SET order_list_state=? WHERE id=?',(json.dumps(state),cid))
|
||||
c.commit();c.close()
|
||||
self.assertEqual(self.ask('第一个呢',cid)['card']['no'],first)
|
||||
|
||||
def test_ordinal_uses_saved_identifiers_when_a_field_contains_display_separators(self):
|
||||
self.login();cid=self.client.post('/api/new_chat').json['id']
|
||||
with self.app.app_context():
|
||||
c=db.connect()
|
||||
order_data.import_records(c,[{'tenant_id':'a','order_no':'STRUCTURED20260001',
|
||||
'inbound_code':'VALUE;订单号:OTHER20260001','status':'PROCESSING',
|
||||
'source_updated_at':'2030-01-01','exception_reason':'待核实'}])
|
||||
c.commit();c.close()
|
||||
self.ask('我有多少异常订单',cid)
|
||||
self.assertEqual(self.ask('第一个呢',cid)['card']['no'],'STRUCTURED20260001')
|
||||
|
||||
def test_ambiguous_speech_answers_the_clear_count_and_requests_the_missing_meaning(self):
|
||||
self.login()
|
||||
text=self.ask('当前,我的订单有多少条,一层有多少条?')['t']
|
||||
|
||||
@@ -114,7 +114,7 @@ class QuoteBusinessTests(unittest.TestCase):
|
||||
text=self.ask('海运和空运哪个好,美国30KG')
|
||||
self.assertIn('没有美国空运费率',text)
|
||||
text=self.ask('美国美西海派多久')
|
||||
self.assertIn('提取不等于送达',text);self.assertNotIn('元/KG',text)
|
||||
self.assertIn('按开船后到提取计算',text);self.assertNotIn('元/KG',text)
|
||||
text=self.ask('Please quote 30kg to US by sea')
|
||||
self.assertIn('CNY/kg',text)
|
||||
self.assertFalse(__import__('re').search(r'[\u4e00-\u9fff]',text),text)
|
||||
|
||||
@@ -119,3 +119,119 @@ class QuoteTimingTests(unittest.TestCase):
|
||||
self.assertIn('最快参考方案暂时无法确定',text)
|
||||
self.assertIn('最慢参考方案暂时无法确定',text)
|
||||
self.assertNotIn('1000KG =',text)
|
||||
|
||||
def test_selected_route_survives_total_calculation_time_and_tax_questions(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国1000KG义乌美东海运,便宜的报价',cid)
|
||||
for question in ('那一共多少钱','怎么算出来的'):
|
||||
text=self.ask(question,cid)
|
||||
self.assertIn('普船海派',text)
|
||||
self.assertIn('1000KG = 6000元',text)
|
||||
self.assertNotIn('美森正班海派',text)
|
||||
text=self.ask('多快能到',cid)
|
||||
self.assertIn('普船海派',text)
|
||||
self.assertIn('船开后25-30天左右提取',text)
|
||||
self.assertNotIn('美森正班海派',text)
|
||||
self.assertIn('标注包税',self.ask('含税吗',cid))
|
||||
text=self.ask('具体多少',cid)
|
||||
self.assertIn('1000KG = 6000元',text)
|
||||
self.assertNotIn('美森正班海派',text)
|
||||
text=self.ask('全部渠道报价',cid)
|
||||
self.assertIn('美森正班海派',text)
|
||||
self.assertIn('普船海派',text)
|
||||
|
||||
def test_polite_acknowledgements_keep_quote_conditions_and_selection(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国30KG义乌美西最快海派报价',cid)
|
||||
for question in ('谢谢','好的,谢谢您','OK'):
|
||||
self.ask(question,cid)
|
||||
text=self.ask('改成50KG呢',cid)
|
||||
self.assertIn('美森正班海派 · 义乌',text)
|
||||
self.assertIn('50KG = 400元',text)
|
||||
self.assertNotIn('普船海派',text)
|
||||
text=self.ask('所有箱都是普通货',cid)
|
||||
self.assertIn('最快参考方案',text)
|
||||
self.assertNotIn('普船海派',text)
|
||||
|
||||
def test_missing_weight_unit_stays_pending_until_an_explicit_unit_is_supplied(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国1000KG义乌美西海运最快报价',cid)
|
||||
for question in ('重量改成800,其他不变','换成华南','谢谢','美东呢'):
|
||||
text=self.ask(question,cid)
|
||||
if question!='谢谢':
|
||||
self.assertIn('单位',text)
|
||||
self.assertNotIn('1000KG =',text)
|
||||
text=self.ask('单位是KG',cid)
|
||||
self.assertIn('美森正班海派 · 华南',text)
|
||||
self.assertIn('800KG = 8000元',text)
|
||||
self.assertNotIn('1000KG',text)
|
||||
self.assertIn('800KG = 8000元',self.ask('具体多少',cid))
|
||||
|
||||
def test_quote_resume_is_explicit_and_survives_later_field_edits(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国30KG义乌美西最快报价',cid)
|
||||
self.ask('我有多少个订单',cid)
|
||||
text=self.ask('50KG呢',cid)
|
||||
self.assertNotIn('美森正班海派',text)
|
||||
text=self.ask('回到刚才的报价',cid)
|
||||
self.assertIn('30KG = 240元',text)
|
||||
self.assertNotIn('50KG',text)
|
||||
text=self.ask('换成华南',cid)
|
||||
self.assertIn('美森正班海派 · 华南',text)
|
||||
self.assertIn('30KG = 240元',text)
|
||||
|
||||
def test_resume_does_not_recover_us_conditions_across_a_new_country_quote(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国30KG义乌海运报价',cid)
|
||||
with self.app.app_context():
|
||||
db.save_message(cid,'user','新的一票100KG发德国海运报价')
|
||||
db.save_message(cid,'assistant','请核对对应目的地的报价。')
|
||||
self.ask('我有多少个订单',cid)
|
||||
text=self.ask('回到刚才的报价',cid)
|
||||
self.assertIn('目的国家',text)
|
||||
self.assertNotIn('美国 30KG',text)
|
||||
self.assertNotIn('元/KG',text)
|
||||
|
||||
def test_new_quote_with_a_topic_switch_becomes_the_next_followup_root(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国30KG义乌美西最快报价',cid)
|
||||
self.ask('换个话题,美国50KG华南美东海运报价',cid)
|
||||
text=self.ask('最慢的呢',cid)
|
||||
self.assertIn('普船海派 · 华南',text)
|
||||
self.assertIn('50KG = 300元',text)
|
||||
self.assertNotIn('30KG',text)
|
||||
self.ask('另外问美国海运报价',cid)
|
||||
text=self.ask('20KG呢',cid)
|
||||
self.assertIn('美国 20KG',text)
|
||||
self.assertIn('义乌',text)
|
||||
self.assertNotIn('50KG',text)
|
||||
|
||||
def test_explicit_selection_and_business_question_are_retained_independently(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国1000KG义乌美东海运报价',cid)
|
||||
self.assertIn('标注包税',self.ask('最快的含税吗',cid))
|
||||
text=self.ask('那一共多少钱',cid)
|
||||
self.assertIn('1000KG = 10000元',text)
|
||||
self.assertNotIn('普船海派',text)
|
||||
text=self.ask('最快多久能提取',cid)
|
||||
self.assertIn('15天左右提取',text)
|
||||
self.assertNotIn('普船海派',text)
|
||||
|
||||
def test_missing_weight_units_before_a_destination_do_not_reuse_the_old_weight(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国1000KG义乌美西最快海运报价',cid)
|
||||
self.assertIn('单位',self.ask('重量改成800美东,其他不变',cid))
|
||||
text=self.ask('KG',cid)
|
||||
self.assertIn('800KG = 8000元',text)
|
||||
self.assertNotIn('1000KG',text)
|
||||
|
||||
def test_all_channels_clears_the_named_service_and_keeps_origin_destination_weight(self):
|
||||
cid=self.client.post('/api/new_chat').json['id']
|
||||
self.ask('美国1000KG义乌美东普船海派最便宜报价',cid)
|
||||
text=self.ask('全部渠道报价',cid)
|
||||
self.assertIn('美森正班海派',text)
|
||||
self.assertIn('合德海派',text)
|
||||
self.assertIn('普船海派',text)
|
||||
self.assertIn('1000KG = 10000元',text)
|
||||
self.assertNotIn('华南',text)
|
||||
self.assertNotIn('美西 ',text)
|
||||
|
||||
Reference in New Issue
Block a user