utils.py 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. @Time : 2024/10/15 16:19
  5. @File : utils.py
  6. @Desc :
  7. """
  8. from datetime import datetime
  9. from functools import wraps
  10. from typing import (Any,
  11. List,
  12. Text,
  13. Dict
  14. )
  15. from config import (
  16. get_logger,
  17. GENERATED,
  18. FIXED,
  19. MOUDLES
  20. )
  21. from threading import Thread
  22. import json
  23. logger = get_logger()
  24. from database import Mysql
  25. def get_speech_status(bid: Text = None, options: List[Dict[Text, Text]] = None):
  26. """which speech template to choose"""
  27. res = dict()
  28. module = MOUDLES[bid]
  29. option = ''
  30. if options:
  31. option = options[-1]['title'] # 外呼机器人单选
  32. for key, value in module.items():
  33. if isinstance(value, dict):
  34. if option in value['content']:
  35. res['action'] = key
  36. res['speech_id'] = value['speech_id']
  37. res['speech_type'] = value['speech_type']
  38. res['speech_interrupt'] = value['speech_interrupt']
  39. res['asr'] = options[-1]['asr']
  40. break
  41. return res
  42. def get_robot_speeches(msg, bid, uid, questions: Dict[Any, Any] = None):
  43. """GET speech and speech status"""
  44. from entity import Status
  45. choose_speech_status = get_speech_status(bid, msg.option)
  46. if not choose_speech_status:
  47. choose_speech = Status.base.value
  48. robot_speech, interrupt = speech_main_contents(uid, bid, msg.code, questions)
  49. interrupt = questions[msg.code]['mainInterrupt']
  50. return robot_speech, choose_speech, interrupt
  51. return None, None, None
  52. def speech_main_contents(uid: Text = None,
  53. bid: Text = None,
  54. code: Text = None,
  55. questions: Dict[Any, Any] = None,
  56. options: List[Dict[Any, Any]] = None):
  57. from util import nlg_service
  58. from entity import Status
  59. def parse_options():
  60. if options:
  61. option = options[-1]
  62. is_faq = option['isFaq']
  63. faq_content = option['faqContent']
  64. if is_faq:
  65. return faq_content
  66. if "businessContent" in option:
  67. return option['businessContent']
  68. return
  69. _robot_speech = ''
  70. speech_type = questions[code]['mainType']
  71. node_name = questions[code]['nodeName']
  72. interrupt = questions[code]['mainInterrupt']
  73. choose_speech = Status.base.value
  74. #logger.info(f"code:{code},speech_type:{speech_type}")
  75. topic = questions[code]
  76. # logger.info(f"topic: {topic}")
  77. _faq_content = parse_options()
  78. if speech_type == GENERATED:
  79. # TODO 生成话术
  80. resp = nlg_service(uid, bid, node_name, choose_speech)
  81. if _faq_content or resp:
  82. _robot_speech = "{}&{}".format(_faq_content, resp) if _faq_content else resp
  83. elif speech_type == FIXED:
  84. content = questions[code]['mainContent']
  85. if content or _faq_content:
  86. _robot_speech = "{}&{}".format(_faq_content, content) if _faq_content else content
  87. return _robot_speech, interrupt
  88. def get_next_code_with_track(uid: Text = None,
  89. code: Text = None,
  90. option: Text = None,
  91. questions: Dict[Any, Any] = None
  92. ):
  93. """
  94. use user trackCode get qus id
  95. @param uid:
  96. @param code:
  97. @param option:
  98. @param questions:
  99. @return:
  100. """
  101. options = questions[code]['options']
  102. for cell in options:
  103. if option == cell['title']:
  104. next = cell['next']
  105. logger.info(f"uid:{uid}:code from {code} to {next}")
  106. return next
  107. return code
  108. def _async(f):
  109. def wrapper(*args, **kwargs):
  110. thr = Thread(target=f, args=args, kwargs=kwargs)
  111. thr.start()
  112. return wrapper
  113. @_async
  114. def insert_log(bid, uid, session_id, scene):
  115. """
  116. CREATE TABLE botrecords (
  117. id INT AUTO_INCREMENT PRIMARY KEY,
  118. session VARCHAR(50) unique not null COMMENT '请求id',
  119. req_time DATETIME COMMENT '来电时间',
  120. uid VARCHAR(20) COMMENT '来电手机号',
  121. bid VARCHAR(20) COMMENT '话术id',
  122. intent VARCHAR(20) COMMENT '意图',
  123. contents TEXT comment '内容',
  124. dialog TEXT COMMENT '对话'
  125. );
  126. """
  127. tmp = json.dumps(scene.case, ensure_ascii=False, default=lambda obj: obj.__dict__)
  128. res = json.loads(tmp)
  129. if res:
  130. answers = res.get("answer")
  131. intent = ''
  132. codes = [i for i in map(lambda x: x.get("code"), answers)]
  133. if "1.20" in codes or "1.10" in codes or "1.00" in codes:
  134. for answer in answers:
  135. if answer.get("code") in ["1.20", "1.10", "1.00"]:
  136. asr = answer.get("option", [{}])[-1].get("asr", '')
  137. code = answer.get("code")
  138. opt = answer.get("option", {})
  139. if (code == "1.10" and asr!="1") or (code == "1.00" and asr not in ["2", "1"]):
  140. if opt:
  141. if opt[-1].get("subclass"):
  142. intent = opt[-1].get("subclass")
  143. elif opt[-1].get("firstclass"):
  144. intent = opt[-1].get("firstclass")
  145. else:
  146. intent =opt[-1].get("title", '')
  147. elif code == "1.20":
  148. tags = {"1": "1_停水咨询", "2":"1_漏水保修", "3":"1_户号查询","4":"1_水费查询", "5":"1_水价咨询","6":"1_水质水价保修", "7":"1_投诉建议", "0":"1_转人工"}
  149. intent = tags.get(asr, "1_其他")
  150. elif code == "1.00" and asr=="2":
  151. intent = "不体验AI服务"
  152. elif code == "1.00" and asr=="1":
  153. intent = asr
  154. filter_ans = filter(lambda x: x.get("code") not in ["2.00", "3.00", "4.00"], answers)
  155. content = [i for i in map(lambda x:[ x.get("question"), x.get("option", [{}])[-1].get("asr", '')], filter_ans)]
  156. content.append((res.get("robot_speech"), ''))
  157. contents = json.dumps({"data": content}, ensure_ascii=False)
  158. req_time = datetime.now().strftime("%Y/%m/%d %H:%M:%S")
  159. mysql = Mysql()
  160. mysql.insert_records([session_id, req_time, uid, bid, intent, contents, json.dumps(res, ensure_ascii=False)])
  161. # records = mysql.get_records(uid)
  162. # logger.info(f"databases:uid:{uid}, {records}")
  163. mysql.close_mysql()
  164. def timetic(func):
  165. @wraps(func)
  166. def wrapper(*args, **kwargs):
  167. start = datetime.now()
  168. results = func(*args, **kwargs)
  169. cost = (datetime.now() - start).total_seconds()
  170. if func.__qualname__ == "botservice":
  171. bot = kwargs.get("reqbot")
  172. sessionId, userId,nodeId = bot.sessionId, bot.userId,bot.nodeId
  173. logger.info("{},session:{},uid:{},nodeid:{} ==> {}s".format(func.__qualname__,sessionId , userId, nodeId, cost))
  174. else:
  175. logger.info("{} ==> {}s".format(func.__qualname__, cost))
  176. return results
  177. return wrapper