大模型接口远程访问
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

438 lines
21 KiB

  1. import os
  2. import platform
  3. import json
  4. import threading
  5. from time import sleep
  6. import openai
  7. import websocket
  8. import ssl
  9. from SparkApi import Ws_Param, on_message, on_error, on_open, on_close, main
  10. from recvChatGPT_V3 import Chatbot_V3
  11. from flask import Flask, request, render_template, Response, abort
  12. from flask_cors import CORS, cross_origin
  13. import redis
  14. from rpc_test import Zhouzhou
  15. app = Flask(__name__)
  16. # openai.api_key = os.getenv("OPENAI_API_KEY")
  17. openai.api_key = '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'
  18. skills = {}
  19. class ChatCompletionCustom:
  20. def __init__(self):
  21. self.role = {"role": "system", "content": "you are a useful assistant."}
  22. self.history = []
  23. self.skill_list = {}
  24. self.embedding_strings = ['华大基因公司主营业务为通过基因检测、质谱检测、生物信息分析等多组学大数据技术手段,',
  25. '华大基因公司为科研机构、企事业单位、医疗机构、社会卫生组织等提供研究服务和精准医学检测综合解决方案。',
  26. '华大基因以推动生命科学研究进展、生命大数据应用和提高全球医疗健康水平为出发点,',
  27. '基于基因领域研究成果及精准检测技术在民生健康方面的应用,',
  28. '致力于加速科技创新,减少出生缺陷,加强肿瘤防控,抑制重大疾病对人类的危害,实现精准治愈感染,全面助力精准医学。',
  29. '以华大基因举例:作为中国基因行业的奠基者,秉承“基因科技造福人类”的愿景,通过20多年的人才积聚、科研积累和产业积淀,',
  30. '华大基因公司已建成覆盖全球百余个国家和全国所有省市自治区的营销服务网络,成为屈指可数的覆盖本行业全产业链、全应用领域的科技公司,立足技术先进、配置齐全和规模领先的多组学产出平台,已成为全球屈指可数的科学技术服务提供商和精准医疗服务运营商。',
  31. '2017年,华大基因于深圳证券交易所创业板上市',
  32. '在2016年的自然指数排名(Nature Index Annual Tables)中,华大名列亚太地区生命科学产业机构(life science - corporate)第一位,并连续七年蝉联该排名第一',
  33. '人类基因组计划:1999年9月1日,于英国茵格斯顿举行的第五次人类基因组测序战略会议上,华大基因创始人之一杨焕明提出,中国愿承担人类3号染色体短臂端粒一侧约30厘摩尔(相当于约3,000万个碱基对)区域的测序和分析任务,占整体人类基因组测序工作的1%,成为人类基因组计划成员当中唯一一个发展中国家',
  34. '水稻基因组计划:水稻(籼稻)基因组工作框架图:华大基因于2000年启动水稻基因组计划,希望通过测序找出水稻产量相关基因,并于2002年在《科学》期刊以封面文章发布首个水稻(籼稻))因组的工作框架序列图,文章先后被引用接近四千次。此次由中国科学家合作完成的水稻基因工作框架图,是继人类基因组之后完成测定的最大的基因组,也是当时测定的最大植物基因组。 水稻作为第一个完成基因组测序农作物,对解决全球粮食问题具有重要意义,建立了改善水稻品质、提高水稻产量的重要基础,并被当时《科学》杂志期刊编辑认为水稻基因组研究工作,对人类健康的重要性在接下来的二十年较人类基因组更大',
  35. '国际大熊猫基因组计划:从北京奥运会的吉祥物大熊猫“晶晶”抽取样本,利用短序列(short-reads)模式组装全球首个熊科动物、也是第二个肉食类动物的基因图谱,包含2.25千兆(Gb)个碱基对,并于2010年1月在《自然》科学期刊以封面文章发布。研究进一步支持大多数科学家所持的“大熊猫属于熊科动物”的观点,并为日后使用次世代基因测序技术,快速省时地组装大型真核生物(eukaryotic),如哺乳类动基因图谱奠定了基础。研究指出,相比于自然环境,人类活动对其造成的影响更为严重']
  36. # self.df = get_embed_array(self.embedding_strings)
  37. chat = ChatCompletionCustom()
  38. zhouzhou = Zhouzhou()
  39. # config set
  40. config = {
  41. "key": "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",
  42. 'proxy': None,
  43. 'ip': '127.0.0.1', # "127.0.0.1" or your server's internal network ip or your server's public ip
  44. 'port': 5001,
  45. }
  46. URL_API = "https://api.openai.com/v1/chat/completions"
  47. headers = {
  48. "Content-Type": "application/json",
  49. "Authorization": f"Bearer {config['key']}"
  50. }
  51. # init chat bot
  52. chatbot = Chatbot_V3(config['key'], "gpt-3.5-turbo", proxy=config['proxy'])
  53. # 给定一个Dictory,循环获取key,value,并将其组合成"1、{key}2、{key}3、{key}的格式"
  54. def format_skill_list(list={}, msg=''):
  55. prifix = '假设你是北京联通公司的客服,我会给你提出一个问题{q},你在我给定的以下列表{list}中出找一个与该问题{q}接近的问题,如果没有符合的答案,回复”””Null”””。列表{list}问题如下:'
  56. suffix = ',不要做多余回答,回复的内容只能是列表{list}中的内容或"""Null""",我接下来问的问题是:'
  57. result = prifix + '"""'
  58. for i, (key, value) in enumerate(list.items()):
  59. result += f"{i + 1}、{key}"
  60. result += '"""' + suffix + msg
  61. print(result)
  62. return result
  63. def format_skill_list_movie(list={}, msg=''):
  64. prifix = 'answer only in a mark down cell, find the closest sentence . The format is' + \
  65. '"""' + \
  66. '[{"msg": <sentence>}]' + \
  67. '"""' + \
  68. 'Returns Null if there is no matching sentence.The format is' + \
  69. '"""' + \
  70. '[{"msg":"Null"}]' + \
  71. '"""' + \
  72. '我提供的句子如下:'
  73. suffix = '不附加说明和解释的文字。' + \
  74. 'my paragraph is:'
  75. result = prifix + '['
  76. for i, (key, value) in enumerate(list.items()):
  77. result += "{" + f"{i + 1}、{key}" + "},"
  78. result = result[0: -1] + ']' + suffix + '"""' + msg + '"""'
  79. print(result)
  80. return result
  81. def format_skill_list_zhenhuan(list={}, msg='',q_arrs=[]):
  82. prifix = '假设你是公司前台,你在与面前的人对话,语段代表对方的问话,首先生成一个应对,然后从列表中选出一个选项作为回答的内容,如果没有对应意图或者语段缺失则返回0。列表为'
  83. # suffix = '。输出为JSON格式,键为number,代表应对的编号。示例输出为:{"number":_}。不要输出任何说明和解释。语段为:'
  84. suffix = '。输出为JSON格式,键为number,代表应对的编号。不要输出任何说明和解释。语段为:'
  85. result = prifix + '{'
  86. for i, (key, value) in enumerate(list.items()):
  87. q_arrs.append(key)
  88. result += f"{i + 1}、{key}"
  89. result += '}' + suffix + msg + '"'
  90. # result = prifix + msg + suffix
  91. print(result)
  92. return result,q_arrs
  93. # Routing, rendering chat interface
  94. @app.route('/')
  95. def index():
  96. chatbot.reset()
  97. return render_template('chat.html')
  98. # Routing, normal chat,not SSE
  99. @app.route('/chat', methods=['POST'])
  100. def chat():
  101. postData = request.get_json() # Get data from POST request
  102. print(postData)
  103. query = postData.get('query', 'Hello')
  104. max_token = postData.get('max_token', '3000') # nouse
  105. temperature = postData.get('temperature', 0.5)
  106. top_p = postData.get('top_p', 1.0)
  107. role = postData.get('role', 'user')
  108. convo_id = postData.get('convo_id', 'default')
  109. n = postData.get('n', 1)
  110. try:
  111. response = chatbot.ask(prompt=query, role=role, convo_id=convo_id, top_p=top_p, temperature=temperature, n=n)
  112. print(response)
  113. return response
  114. except Exception as e:
  115. return e
  116. # Routing, SSE chat
  117. @app.route('/chatstream', methods=['GET', 'POST'])
  118. def chat_stream():
  119. query = request.args.get('query', 'Hello')
  120. max_token = float(request.args.get('max_token', '3000')) # nNouse
  121. temperature = float(request.args.get('temperature', '0.5'))
  122. top_p = float(request.args.get('top_p', '1.0'))
  123. role = request.args.get('role', 'user')
  124. convo_id = request.args.get('convo_id', 'default')
  125. n = int(request.args.get('n', '1'))
  126. # 将问题格式化
  127. query = format_skill_list(chatbot.skills, query)
  128. return Response(
  129. chatbot.ask_stream_text(prompt=query, role=role, convo_id=convo_id, top_p=top_p, temperature=temperature, n=n),
  130. mimetype='text/event-stream')
  131. def chat_completion_for_multi_turn(msg):
  132. role = {"role": "system", "content": "你是一个幽默段子手."}
  133. print("当前角色: {}".format(chat.role['content']))
  134. input_message = [
  135. chat.role
  136. ]
  137. for i in range(len(msg)):
  138. # 对i除以2取余数,如果是0,输入input_message.append({"role": "user", "content": msg[i]}),否则输入input_message.append({"role": "assistant", "content": msg[i]})
  139. if i % 2 == 0:
  140. input_message.append({"role": "user", "content": msg[i]})
  141. else:
  142. input_message.append({"role": "assistant", "content": msg[i]})
  143. print("调用gpt的prompts:")
  144. print(input_message)
  145. completion = openai.ChatCompletion.create(
  146. model="gpt-3.5-turbo",
  147. # model="gpt-4",/
  148. messages=input_message,
  149. temperature=0.8,
  150. frequency_penalty=0,
  151. max_tokens=1024,
  152. presence_penalty=0,
  153. top_p=1
  154. )
  155. print(completion.choices[0].message['content'])
  156. temp_completion = {'question': {"role": "user", "content": msg},
  157. 'answer': {"role": "assistant", "content": completion.choices[0].message['content']}}
  158. return completion.choices[0].message['content']
  159. @app.route(rule='/chat_data', methods=['post'])
  160. @cross_origin()
  161. def chat_data():
  162. chat.role = {"role": "system",
  163. "content": '根据以下文章提出可能问到的10个问题,并给出对应的答案,回答的形式为"{序号}、{问题}|{答案}",不要回复其他内容。'}
  164. # chat.role = {"role": "system", "content": '我会给出一部电影的资料,将资料拆解成10个问题,要求每个问题的开头都是电影名,并给出对应的答案。回答的形式为"{序号}、{电影名}{问题}|{答案}",不要回复其他内容。'}
  165. try:
  166. req = request
  167. msg = []
  168. m = request.json.get('corpus')
  169. # 如果m不为空,就加入到msg中
  170. if m is not None:
  171. msg.append(m)
  172. data = {'msg': chat_completion_for_multi_turn(msg)}
  173. print("success")
  174. test = {}
  175. # 获得的结果字符串为"问题1|答案1\n问题2|答案2\n问题3|答案3\n问题4|答案4\n...",循环将其分割为问题和答案,将问题作为key,答案作为value,存储在chat.skill_list中
  176. for i in data['msg'].split('\n'):
  177. print()
  178. # chat.skill_list[i.split('|')[0].index('、')] = i.split('|')[1]
  179. q = i.split('|')[0]
  180. a = i.split('|')[1]
  181. chatbot.skills[q[q.index('、') + 1:]] = a
  182. # 将chat.skill_list中的key和value用print()函数打印出来
  183. for i, (key, value) in enumerate(chatbot.skills.items()):
  184. print(f"{i + 1}、{key}:{value}")
  185. # 获取当前路径并打印出来
  186. print(os.getcwd())
  187. # 将chatbot.skills中的key和value保存到skills.csv中,以便后续使用
  188. with open('/Users/ruoxiyin/Documents/缔智元/代码/chatGPT_Web-main/skills.csv', 'a', encoding='utf-8') as f:
  189. for key, value in chatbot.skills.items():
  190. f.write(f"{key}|{value}\n")
  191. return data
  192. except Exception as e:
  193. print("An exception occurred:", str(e))
  194. return {'msg': '真抱歉,我连接Chatgpt的好像出现问题了呀'}
  195. @app.route(rule='/get_skill_list', methods=['get'])
  196. @cross_origin()
  197. def get_skill_list():
  198. print("get_skill_list")
  199. # 将chat.skill_list中的key和value用print()函数打印出来
  200. for i, (key, value) in enumerate(chatbot.skills.items()):
  201. print(f"{i + 1}、{key}:{value}")
  202. # 将chatbot.skills序列化成json格式后作为返回值返回
  203. return json.dumps(chatbot.skills, ensure_ascii=False)
  204. @app.route(rule='/question_answer', methods=['post'])
  205. @cross_origin()
  206. def question_answer():
  207. # 连接redis数据库,地址为39.107.77.235,端口为6379
  208. r = redis.Redis(host='39.107.77.235', port=6381)
  209. # 获取redis数据库中的key为"session"的值,如果存在,返回0,否则新增一个key为"session"的值,值为1
  210. session = r.get("chatgpt:session")
  211. if session is None:
  212. r.set("session", 1)
  213. else:
  214. # 断开redis数据库的连接
  215. r.close()
  216. abort(500)
  217. chat.role = {"role": "system", "content": '你是一个有用的助理'}
  218. try:
  219. req = request
  220. msg = []
  221. m = request.json.get('corpus')
  222. # 如果m不为空,就加入到msg中
  223. if m is not None:
  224. # m = format_skill_list(chatbot.skills, m)
  225. m = format_skill_list_movie(chatbot.skills, m)
  226. msg.append(m)
  227. resp = chat_completion_for_multi_turn(msg)
  228. print(resp)
  229. if resp == 'Null':
  230. data = {'msg': "对不起,这个问题我不太清楚呀"}
  231. # resp = resp[resp.index('、') + 1:]
  232. else:
  233. # 判断chatbot.skills字典是否有resp的key
  234. if resp in chatbot.skills.keys():
  235. data = {'msg': chatbot.skills[resp]}
  236. else:
  237. data = "对不起,这个问题我不太清楚呀"
  238. # 循环遍历chatbot.skills,resp如果包含key,则将对应value赋值给data
  239. for key, value in chatbot.skills.items():
  240. if key in resp:
  241. data = {'msg': value}
  242. break
  243. # 清空redis数据库中的key为"session"的值,并断开连接
  244. r.delete("chatgpt:session")
  245. r.close()
  246. # zhouzhou发送text消息
  247. # zhouzhou.say_text(data['msg'])
  248. return data
  249. except Exception as e:
  250. print("An exception occurred:", str(e))
  251. return {'msg': '真抱歉,我连接Chatgpt的好像出现问题了呀'}
  252. def do_stream_response(resp_words):
  253. for i in range(0, len(resp_words)):
  254. sleep(0.1)
  255. yield 'data: {}\n\n'.format(json.dumps({'content': resp_words[i]}))
  256. @app.route('/chatstream_qa', methods=['GET', 'POST'])
  257. @cross_origin()
  258. def chat_stream_qa():
  259. chat.role = {"role": "system", "content": '你是一个有用的助理'}
  260. query = request.args.get('query', 'Hello')
  261. # 将问题格式化
  262. msg = []
  263. q_arrs = []
  264. query, q_arrs = format_skill_list_zhenhuan(chatbot.skills, query,q_arrs)
  265. msg.append(query)
  266. resp = chat_completion_for_multi_turn(msg)
  267. # resp = 'Null'
  268. data = ''
  269. # 将resp用json格式化,获取当中的number字段
  270. resp = json.loads(resp)
  271. resp = resp['number']
  272. if resp == 0:
  273. data = "对不起,这个问题我不太清楚呀"
  274. else:
  275. # 根据resp的数字获取q_arrs中对应元素,并将该元素判断chatbot.skills字典是否有对应的key
  276. resp = q_arrs[resp - 1]
  277. if resp in chatbot.skills.keys():
  278. data = '匹配到问题:' + resp + ',回答:' + chatbot.skills[resp]
  279. else:
  280. print('data:' + data)
  281. if data is None or data == '':
  282. data = "对不起,这个问题我不太清楚呀"
  283. # 循环遍历chatbot.skills,resp如果包含key,则将对应value赋值给data
  284. for key, value in chatbot.skills.items():
  285. if key in resp:
  286. data = value
  287. break
  288. # zhouzhou发送text消息
  289. # zhouzhou.say_text(data)
  290. return Response(do_stream_response(data), mimetype='text/event-stream')
  291. # return Response('data: {}\n\n'.format(json.dumps({'content':data})))
  292. @app.route('/chat_qa', methods=['GET', 'POST'])
  293. @cross_origin()
  294. def chat_qa():
  295. chat.role = {"role": "system", "content": '你是一个有用的助理'}
  296. print(request.args)
  297. query = request.args.get('query', 'Hello')
  298. # 将问题格式化
  299. msg = []
  300. q_arrs = []
  301. query, q_arrs = format_skill_list_zhenhuan(chatbot.skills, query,q_arrs)
  302. msg.append(query)
  303. resp = chat_completion_for_multi_turn(msg)
  304. # resp = 'Null'
  305. data = ''
  306. # 将resp用json格式化,获取当中的number字段
  307. resp = json.loads(resp)
  308. resp = resp['number']
  309. if resp == 0:
  310. data = "对不起,这个问题我不太清楚呀"
  311. else:
  312. # 根据resp的数字获取q_arrs中对应元素,并将该元素判断chatbot.skills字典是否有对应的key
  313. resp = q_arrs[resp - 1]
  314. if resp in chatbot.skills.keys():
  315. data = chatbot.skills[resp]
  316. else:
  317. print('data:' + data)
  318. if data is None or data == '':
  319. data = "对不起,这个问题我不太清楚呀"
  320. # 循环遍历chatbot.skills,resp如果包含key,则将对应value赋值给data
  321. for key, value in chatbot.skills.items():
  322. if key in resp:
  323. data = value
  324. break
  325. # zhouzhou发送text消息
  326. # zhouzhou.say_text(data)
  327. # 将data格式化成json格式,存入msg字段中
  328. data = {'msg': data}
  329. return data
  330. @app.route('/chatstream_fire', methods=['GET', 'POST'])
  331. @cross_origin()
  332. def chat_stream_fire():
  333. chat.role = {"role": "system", "content": '你是一个有用的助理'}
  334. query = request.args.get('query', 'Hello')
  335. # 将问题格式化
  336. msg = []
  337. q_arrs = []
  338. query, q_arrs = format_skill_list_zhenhuan(chatbot.skills, query,q_arrs)
  339. msg.append(query)
  340. # 获取一个condition,并将condition存入Ws_Param中
  341. condition = threading.Condition()
  342. # condition.acquire()
  343. print(query)
  344. resp = main(appid="3d9282da",
  345. api_secret="ZTRiNDQwMTRlOTlmZDQwMDUwYTdjMDM0",
  346. api_key="7c217b3a313f4b66fcc14a8e97f85103",
  347. gpt_url="ws://spark-api.xf-yun.com/v1.1/chat",
  348. # question='你是谁')
  349. # question='将给定语段转换为含义最相似的意图 。意图是如下列表中的一项。如果没有对应意图或者语段缺失则返回0.列表为{1、你喜欢的状态是什么。2、公司高管有谁。3、打印机怎么使用。4、员工的福利有哪些。5、公司的价值观是什么。6、工作时间是几点。7、公司的愿景是什么。8、公司的使命是什么。9、公司有哪些产品。10、员工守则是什么。11、介绍一下你们公司。12、洗手间怎么走。13、开门。14、关门。15、取消你的静音。16、调小你的音量。17、调大你的音量。18、把你的声音关掉。19、介绍你自己。20、介绍我。21、预约个访客。22、预约会议。23、大会议室的地点。24.小会议室的地点。25、打招呼。26.停止。27、找人。28、在不在。}。输出为JSON格式,键为number。不要输出任何说明和解释。语段为“[用户]:'
  350. question=query)
  351. # condition.wait()
  352. # condition.release()
  353. # resp = chat_completion_for_multi_turn(msg)
  354. # resp = 'Null'
  355. data = ''
  356. # 将resp用json格式化,获取当中的number字段
  357. resp = json.loads(resp)
  358. resp = resp['number']
  359. if resp == 'Null':
  360. data = "对不起,这个问题我不太清楚呀"
  361. else:
  362. # 根据resp的数字获取q_arrs中对应元素,并将该元素判断chatbot.skills字典是否有对应的key
  363. resp = q_arrs[resp - 1]
  364. if resp in chatbot.skills.keys():
  365. data = chatbot.skills[resp]
  366. else:
  367. print('data:' + data)
  368. if data is None or data == '':
  369. data = "对不起,这个问题我不太清楚呀"
  370. # 循环遍历chatbot.skills,resp如果包含key,则将对应value赋值给data
  371. for key, value in chatbot.skills.items():
  372. if key in resp:
  373. data = value
  374. break
  375. # return Response(do_stream_response(data), mimetype='text/event-stream')
  376. # return Response('data: {}\n\n'.format(json.dumps({'content':data})))
  377. data = {'msg': data}
  378. return data
  379. if __name__ == '__main__':
  380. app.run(debug=True, host=config['ip'], port=config['port'])