request_utils.py 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238
  1. #!/usr/bin/env python
  2. # -*- coding: utf-8 -*-
  3. """
  4. @Time : 2024/10/17 14:36
  5. @File : request_utils.py.py
  6. @Desc :
  7. """
  8. import re
  9. import os
  10. import shutil
  11. import json
  12. from config import get_logger
  13. import requests
  14. import base64
  15. from database import *
  16. from util import timetic, norm_community
  17. import uuid
  18. SERVE_HOST = os.environ.get("SERVE_HOST", "192.168.100.159")
  19. VOICE_DIR = os.environ.get("VOICE_DIR","/root/aibot/dm/voice")
  20. logger = get_logger()
  21. def nlg_service(uid, bid, node_name, choose_speech):
  22. return ''
  23. def get_voice(content, is_local, silence_duration):
  24. # appid = "1226203350"
  25. # access_token = "mMPNJ4WbSVL6NHQKvn4qllYfwv1G4X5w"
  26. # 企业
  27. appid = "8661018433"
  28. access_token ="KkTVKPD9kY-i27Hr9gXtFQ4zqY7nrhJl"
  29. cluster = "volcano_tts"
  30. voice_type = "BV700_V2_streaming"
  31. host = "openspeech.bytedance.com"
  32. api_url = f"https://{host}/api/v1/tts"
  33. header = {"Authorization": f"Bearer;{access_token}"}
  34. #DEFAULT_FILE_UPLOAD_URL = 'http://10.0.0.28:8080/qiniuyun/upLoadImage'
  35. DEFAULT_FILE_UPLOAD_URL = 'http://192.168.9.54:8080/qiniuyun/upLoadImage'
  36. rid = str(uuid.uuid4())
  37. request_json = {
  38. "app": {
  39. "appid": appid,
  40. "token": "access_token",
  41. "cluster": cluster
  42. },
  43. "user": {
  44. "uid": "388808087185088"
  45. },
  46. "audio": {
  47. "voice_type": voice_type,
  48. #"encoding": "mp3",
  49. "encoding": "wav",
  50. "rate": "16000",
  51. "speed_ratio": 0.9,
  52. "volume_ratio": 1.0,
  53. "pitch_ratio": 1.0,
  54. "emotion": "customer_service",
  55. "language": "zh"
  56. },
  57. "request": {
  58. "reqid": rid,
  59. "text": content,
  60. "text_type": "plain",
  61. "operation": "query",
  62. "with_frontend": 1,
  63. "frontend_type": "unitTson",
  64. "silence_duration":silence_duration
  65. }
  66. }
  67. try:
  68. resp = requests.post(api_url, json.dumps(request_json), headers=header)
  69. rfile =f"{rid}.wav"
  70. path, file=f"{VOICE_DIR}/{rfile}", f"../voice/{rfile}"
  71. if "data" in resp.json():
  72. data = resp.json()["data"]
  73. file_to_save = open(file, "wb")
  74. file_to_save.write(base64.b64decode(data))
  75. if is_local:
  76. if os.path.exists(file):
  77. logger.info(f"voice local file ::session_id={rid}, res={file}")
  78. return path
  79. else:
  80. files = {'file': open(file, 'rb')}
  81. response = requests.post(DEFAULT_FILE_UPLOAD_URL, files=files)
  82. if response.ok:
  83. result = json.loads(response.text)
  84. url = result.get('data')
  85. if os.path.exists(file):
  86. os.system(f"rm -fr {file}")
  87. logger.info(f"voice upload_plot::session_id={rid}, res={url}")
  88. return url
  89. except Exception as e:
  90. logger.info(f"voice generate 错误{e}")
  91. @timetic
  92. def voice_service(content, local=False, silence_duration="125"):
  93. encode_b = content.encode("utf-8")
  94. key = base64.b64encode(encode_b)
  95. name = "voice_url"
  96. retry,num =1,1
  97. while num <= retry:
  98. try:
  99. url = r.hget(name, key)
  100. #url=''
  101. if url:
  102. logger.info(f"获取voice url成功:{content}")
  103. return url
  104. else:
  105. url = get_voice(content, local, silence_duration)
  106. r.hset(name, key, url)
  107. r.expire(name, 3600 * 24*7)
  108. return url
  109. except Exception as e:
  110. logger.info(f"get voice url {num}缓存错误{e}")
  111. num +=1
  112. @timetic
  113. def intent_service(node_name, asr, bid, code, uid, sessionid):
  114. param = json.dumps(dict(nodeId=code,
  115. userId=uid,
  116. sessionId=sessionid,
  117. taskId=bid,
  118. query=asr,
  119. nodeName = node_name
  120. ), ensure_ascii=False)
  121. try:
  122. #ip= "10.0.0.24"
  123. res = requests.post(f"http://{SERVE_HOST}:50072/intention",
  124. param.encode("UTF-8"),
  125. headers={'Content-Type': 'application/json;charset=utf-8'},
  126. timeout=8)
  127. content = json.loads(res.text)
  128. logger.info(f"intent service:{content}")
  129. return [content]
  130. except Exception as e:
  131. logger.error(f"intent服务异常:query:{asr},uid:{uid},session:{sessionid}:{e}")
  132. return []
  133. @timetic
  134. def business_service(session_id, uid, code, tools, asr):
  135. def getContent(contents, tools):
  136. if tools in ["water_info", "water_loc_info"]:
  137. mess = '您查询的小区'
  138. neighbourhoodName = [item.get('neighbourhoodName') for item in contents]
  139. reason = [item.get('reason') for item in contents]
  140. timeBegin = ["于"+item.get('timeBegin') + "停水" for item in contents]
  141. timeEnd = [item.get('timeEnd') for item in contents]
  142. conclusions = [f"预计{time}恢复供水" if time is not None else "暂未确定恢复时间" for time in timeEnd]
  143. nums = len(neighbourhoodName)
  144. mess +=";".join([",".join(i) for i in zip(neighbourhoodName, reason, timeBegin, conclusions)])
  145. mess +=",解决轻按1,未解决请按2"
  146. elif tools in ["fee_info", "fee_user_info"]:
  147. mess = "您账户截止"
  148. statisticsTime = [content.get("statisticsTime", '') for content in contents]
  149. waterFees = [round(float(content.get("waterFees", 0)), 2) for content in contents]
  150. meterAmount = [round(float(content.get("meterAmount", 0)),2) for content in contents]
  151. mess = mess + statisticsTime[0] + "您的抄表表数为"+str(meterAmount[0]) +"欠费金额为" + str(waterFees[0])+ "元。如需详细查询缴费和水量情况可以登陆佳木斯供水公众号,如需人工查询请拨打8247777,解决轻按1, 未解决请按2."
  152. elif tools in ["user_info", "user_phone_info"]:
  153. neighbour, cardNo = [content.get("neighbourhoodName") for content in contents], [content.get("userNo") for content in contents]
  154. nums = len(neighbour)
  155. mess = f"根据您的手机号查询到{nums}个小区," + ";".join(map(lambda x: ",".join(x), zip(neighbour, ["户号是"]* nums, cardNo)))+ "。解决轻按1, 未解决请安2."
  156. elif tools in ["meter_owner_phone", "meter_owner_neighbour"]:
  157. loc_phone = [[content['neighbourhoodName'], content['meterReaderPhone']] for content in contents]
  158. mess = f"您查询的小区{loc_phone[0][0]},抄表员电话是{loc_phone[0][1]},重听请说再说一次,解决轻按“1”, 未解决请按“2”."
  159. else:
  160. mess = ''
  161. return mess
  162. pattern = r'DTMF(.*?)DTMF'
  163. matches = re.findall(pattern, asr, re.DOTALL)
  164. if matches:
  165. asr = re.sub("[()]", "", matches[-1])
  166. else:
  167. asr = asr.split("###")[-1]
  168. asr = asr.strip(r""""$%&'()*+,,-./:;<=>?@[\]^_`{|}~。??!""")
  169. if tools in ["water_loc_info", "fee_user_info", "user_phone_info", "meter_owner_neighbour"] and len(asr)==0:
  170. return [{"title": "NO", "isFaq": False, "faqContent": '', "asr": asr, "businessContent": ''}]
  171. # parse water_loc_info
  172. if tools in ["water_loc_info", "meter_owner_neighbour"]:
  173. asr = norm_community(asr)
  174. param = json.dumps(dict(nodeId=code,
  175. userId=uid,
  176. sessionId=session_id,
  177. asrText=asr,
  178. method=tools
  179. ), ensure_ascii=False)
  180. try:
  181. # 192.168.40.21
  182. res = requests.post(f"http://{SERVE_HOST}:8001/bigModel/queryBusinessInfo",
  183. param.encode("UTF-8"),
  184. headers={'Content-Type': 'application/json;charset=utf-8'},
  185. timeout=30)
  186. resp = json.loads(res.text)
  187. logger.info(f"bussiness:{resp}, tools:{tools}, session:{session_id}")
  188. if resp['code'] == "0":
  189. content = resp['data'].get("contents")
  190. title = "NO" if content is None or len(content)==0 else "YES"
  191. businessContent = getContent(content, tools) if title == "YES" else ''
  192. opt = [{"title": title, "isFaq": False, "faqContent": '', "asr": asr, "businessContent": businessContent}]
  193. logger.info(f"code:{code},uid:{uid}, tools:{tools},asr:{asr}, opt:{opt}")
  194. return opt
  195. else:
  196. return [{"title": "NO", "isFaq": False, "faqContent": '', "asr": asr, "businessContent": ''}]
  197. except Exception as e:
  198. logger.info(f"bussion service服务异常:session:{session_id}, tools:{tools},uid:{ uid}:{e}")
  199. return [{"title": "NO", "isFaq": False, "faqContent": '', "asr": asr, "businessContent":''}]
  200. @timetic
  201. def aibot_service(ip ="192.168.100.159",port="40072", nodeId="start", userId='no', sessionId='1', taskId='10001', asrText='是', ext='', recordId=''):
  202. param = json.dumps(dict(nodeId=nodeId,
  203. userId=userId,
  204. sessionId=sessionId,
  205. taskId=taskId,
  206. asrText=asrText,
  207. ext=ext,
  208. recordId=recordId
  209. ), ensure_ascii=False)
  210. try:
  211. res = requests.post(f"http://{ip}:{port}/botservice",
  212. param.encode("UTF-8"),
  213. headers={'Content-Type': 'application/json;charset=utf-8'},
  214. timeout=30)
  215. resp = json.loads(res.text)
  216. if resp['code'] == 0:
  217. content = resp['data']
  218. logger.info(f"aibot: {resp}")
  219. return resp
  220. except Exception as e:
  221. logger.error(f"Ai bot服务异常:{nodeId}, {taskId},{ userId}:{e}")
  222. return
  223. if __name__ == "__main__":
  224. print(voice_service("欢迎致电“佳木斯龙江环保供水服务热线”。我们最新推出智能语音服务,说话就能查询业务, 抢先体验请按1, 传统服务请按2"))
  225. #intent_service("1", "没听清", "2200", "1", "10", "1")
  226. #aibot_service()