优化连续追问的报价条件与订单指代
This commit is contained in:
@@ -9,10 +9,16 @@ US = re.compile(r'美国|美西|美中|美东|洛杉矶|纽约|芝加哥|休斯
|
||||
r'(?<![A-Za-z])(?:USA|(?-i:US)|United States|America)(?=$|[^A-Za-z]|FBA(?![A-Za-z]))|'
|
||||
r'(?:发(?:往|到)?|寄(?:往|到)?|运往|运到|到|往|\bto\s+)\s*us(?=$|[^A-Za-z]|FBA(?![A-Za-z]))',re.I)
|
||||
QUOTE_WORDS = re.compile(r'报价|价格|运费|费用|收费|多少钱|计费|包税|海运|空运|海派|海卡|海铁|美森|合德|普船|附加|保险|代发|申报|偏远|超重|超尺寸|币种|\bEXX\b|\b(?:quote|price|cost|freight)\b',re.I)
|
||||
WEIGHT = re.compile(r'(?<![\d.])(-?\d+(?:\.\d+)?)\s*(kilograms?|kgs?|公斤|千克|grams?|克|g|tons?|吨|lbs?|磅)(?![A-Za-z])',re.I)
|
||||
WEIGHT_UNITS = r'kilograms?|kgs?|公斤|千克|grams?|克|g|tons?|吨|lbs?|磅'
|
||||
WEIGHT = re.compile(r'(?<![\d.])(-?\d+(?:\.\d+)?)\s*('+WEIGHT_UNITS+r')(?![A-Za-z])',re.I)
|
||||
MISSING_WEIGHT_UNIT = '请补充修改后重量的单位,例如KG或吨,我再按新重量核算。'
|
||||
TOPIC_BOUNDARY = re.compile(r'新(?:的)?一(?:票|批)|另外|另一|换个话题|理赔|赔偿|破损|丢失|退件|投诉|查单|轨迹|签收')
|
||||
|
||||
|
||||
def resumes_quote(message):
|
||||
return bool(re.search(r'(?:回到|回头|继续)(?:刚才|之前|前面|上面)(?:的)?(?:美国)?(?:海运)?(?:报价|价格|运费)',message))
|
||||
|
||||
|
||||
def chinese_number(text):
|
||||
digits={c:i for i,c in enumerate('零一二三四五六七八九')};digits.update({'两':2,'〇':0})
|
||||
if all(c in digits for c in text):return ''.join(str(digits[c]) for c in text)
|
||||
@@ -45,6 +51,16 @@ def kg(value,unit):
|
||||
return value
|
||||
|
||||
|
||||
def request_selection(text):
|
||||
if re.search(r'最便宜|便宜的|便宜一?点|优惠|折扣|打折|最省钱|最划算|最低价|cheapest|least expensive',text,re.I):return 'cheapest'
|
||||
fastest=bool(re.search(r'最快|快的|fastest',text,re.I))
|
||||
slowest=bool(re.search(r'最慢|慢的|slowest',text,re.I))
|
||||
if fastest and slowest:return 'speed_compare'
|
||||
if fastest:return 'fastest'
|
||||
if slowest:return 'slowest'
|
||||
return None
|
||||
|
||||
|
||||
def request_mode(text):
|
||||
# Business topics outrank generic verbs such as “怎么算”.
|
||||
if re.search(r'保险|保价|投保|insured|insurance',text,re.I):return 'insurance'
|
||||
@@ -58,21 +74,15 @@ def request_mode(text):
|
||||
if re.search(r'纯电池|带电|内置电池|液体|粉末|食品|医疗用品|仿牌',text):return 'acceptance'
|
||||
from .shipping_faq import preparation_topic
|
||||
if preparation_topic(text):return 'preparation'
|
||||
if re.search(r'最便宜|便宜的|便宜一?点|优惠|折扣|打折|最省钱|最划算|最低价|cheapest|least expensive',text,re.I):return 'cheapest'
|
||||
if re.search(r'最终总价|一共多少钱|总共多少钱|合计多少钱|最终价格|最终费用|到门总价',text):return 'total'
|
||||
fastest=bool(re.search(r'最快|快的|fastest',text,re.I))
|
||||
slowest=bool(re.search(r'最慢|慢的|slowest',text,re.I))
|
||||
if fastest and slowest:return 'speed_compare'
|
||||
if fastest:return 'fastest'
|
||||
if slowest:return 'slowest'
|
||||
if re.search(r'一件代发|散箱入库|整柜卸货|卸货费|仓租|仓储|贴标费',text):return 'fulfillment'
|
||||
if re.search(r'FDA|申报费|报关|续页|品名',text,re.I):return 'customs'
|
||||
if re.search(r'附加费|含税|含派送|全包|包不包|还.*(?:费|加钱)|(?:额外|其他|其它).*(?:费用|收费)|包含.*费|包税.*(?:包含|包括)|超重费|超尺寸|住宅|私人|商业地址',text):return 'fees'
|
||||
if re.search(r'电池|带电|液体|粉末|食品|医疗|能(?:不能|发|走)|可以.*(?:发|走)',text):return 'acceptance'
|
||||
if re.search(r'人民币|美元|美金|币种|currency|\b(?:RMB|CNY|USD)\b',text,re.I) and not WEIGHT.search(text):return 'currency'
|
||||
if re.search(r'怎么(?:算|计算)|计算(?:过程|出来)|怎么算出来|calculation',text,re.I):return 'calculation'
|
||||
if re.search(r'时效|多久|几天',text) and not WEIGHT.search(text):return 'time'
|
||||
return 'quote'
|
||||
if re.search(r'时效|多久|几天|多快(?:能|会)?到',text) and not WEIGHT.search(text):return 'time'
|
||||
return request_selection(text) or 'quote'
|
||||
|
||||
|
||||
def parse_intent(message,warehouse_codes):
|
||||
@@ -90,6 +100,10 @@ def parse_intent(message,warehouse_codes):
|
||||
unknown=[t for t in candidates if t not in warehouse_codes and re.fullmatch(r'[A-Z]{2,4}[0-9][A-Z0-9]{0,2}',t)
|
||||
and not t.startswith(('USD','RMB','CNY'))]
|
||||
errors=materials['errors'][:]
|
||||
pending_weight=re.search(r'(?:总重量|总重|重量|毛重|实重)\s*(?:改成|改为|改到|换成|调整为|是|为)?\s*'
|
||||
r'(-?\d+(?:\.\d+)?)(?![\d.])(?!\s*(?:'+WEIGHT_UNITS+r')(?![A-Za-z]))',text,re.I)
|
||||
if pending_weight:errors.append(MISSING_WEIGHT_UNIT)
|
||||
weight_unit=re.fullmatch(r'(?:单位(?:是|用|为)?|按)?\s*('+WEIGHT_UNITS+r')(?:计算|算|计)?[。.!!??\s]*',text,re.I)
|
||||
from .quote_allocations import allocations
|
||||
assigned=allocations(quantity_text,warehouses,WEIGHT,kg)
|
||||
weights=[m for m in WEIGHT.finditer(quantity_text) if not quantity_text[:m.start()].rstrip().endswith(('x','X','×','*'))]
|
||||
@@ -158,6 +172,7 @@ def parse_intent(message,warehouse_codes):
|
||||
air=bool(re.search(r'空运|空派|\bair\b',text,re.I))
|
||||
sea=bool(re.search(r'海运|海派|海卡|海铁|\bsea\b',text,re.I))
|
||||
english=not re.search(r'[\u4e00-\u9fff]',message) and bool(re.search(r'[A-Za-z]{3,}\s+[A-Za-z]',message))
|
||||
mode=request_mode(text)
|
||||
return {'country':country,'weight':weight,'dims':parsed['dims'],'dim_unit':detect_dim_unit(text),
|
||||
'cbm':cbm.group(1) if cbm else None,'boxes':count,'packages':packages or None,'allocations':assigned,'origin':origin,
|
||||
'services':services or None,'kinds':kinds or None,'transport':parsed['channel'],
|
||||
@@ -165,7 +180,11 @@ def parse_intent(message,warehouse_codes):
|
||||
'warehouse':warehouses[0] if warehouses else None,'warehouses':warehouses or None,
|
||||
'unknown_warehouses':unknown or None,'postal':postal,'zone':zones[0] if zones else None,'zones':zones or None,
|
||||
'tax':'excluded' if re.search(r'不包税|自税|不含税|tax excluded',text,re.I) else ('included' if re.search(r'包税|tax included',text,re.I) else None),
|
||||
'errors':errors,'mode':request_mode(text),'english':True if english else (False if re.search(r'[\u4e00-\u9fff]',message) else None),
|
||||
'errors':errors,'mode':mode,'selection':request_selection(text),
|
||||
'pending_weight':pending_weight[1] if pending_weight else None,
|
||||
'weight_unit':weight_unit[1] if weight_unit else None,
|
||||
'clear_selection':bool(re.search(r'(?:全部|所有|各个?)(?:的)?(?:渠道|线路|方案)|(?:全部|所有)(?:报价|价格|运价)',text)),
|
||||
'english':True if english else (False if re.search(r'[\u4e00-\u9fff]',message) else None),
|
||||
'material':materials['material'],'metal_scope':materials['metal_scope'],
|
||||
'metal_chargeable_weight':materials['metal_chargeable_weight'],
|
||||
'metal_weight_update':materials['metal_weight_update'],
|
||||
@@ -174,6 +193,8 @@ def parse_intent(message,warehouse_codes):
|
||||
|
||||
|
||||
def is_followup(message,intent):
|
||||
if resumes_quote(message):return True
|
||||
if intent.get('weight_unit'):return True
|
||||
if re.search(r'和刚才一样|其他不变|其它不变|每箱不变',message):return True
|
||||
if TOPIC_BOUNDARY.search(message):return False
|
||||
text=message.strip().strip(',,。.!!?? ')
|
||||
@@ -182,6 +203,7 @@ def is_followup(message,intent):
|
||||
if intent.get('warehouse') or intent.get('unknown_warehouses'):
|
||||
return not (intent['country'] and intent['weight'])
|
||||
if intent.get('mode')!='quote':return not (intent['country'] and intent['weight'])
|
||||
if re.fullmatch(r'具体(?:多少|多少钱)(?:呢)?',text):return True
|
||||
if re.fullmatch(r'(?:请|请问|帮我|给我|请给我|麻烦)?(?:再|继续)?(?:提供|显示|列出|看一下|看看|查询)?'
|
||||
r'(?:具体|详细|全部渠道|所有渠道|各渠道)?(?:报价|价格|运费|费用)(?:呢|是多少|多少|怎么样|如何|多少钱)?',text):return True
|
||||
if re.fullmatch(r'(?:邮编|zip|postcode)?\s*\d{5}(?:-\d{4})?(?:呢)?',text,re.I):return True
|
||||
|
||||
Reference in New Issue
Block a user