chatgpt.py 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. # -*- coding:utf-8 -*-
  2. import requests
  3. import json
  4. import time
  5. from tools.loglog import logger,simple_logger,log_err_e,annotation_logger
  6. from tools.new_mysql import MySQLUploader
  7. from typing import Optional, Dict, Any,Union
  8. from gpt.gpt_check import Article,Annotation
  9. from pydantic import ValidationError
  10. import ujson
  11. m = MySQLUploader()
  12. def get_openai_model(model_text:str):
  13. """模糊获得模型名"""
  14. if "3.5" in model_text or "3.5-turbo" in model_text or "3.5turbo" in model_text:
  15. model = "gpt-3.5-turbo"
  16. elif "4o" in model_text or "gpt4o" in model_text:
  17. model = "gpt-4o"
  18. elif "4turbo" in model_text or "4-turbo" in model_text:
  19. model = "gpt-4-turbo"
  20. else:
  21. model = "gpt-4o"
  22. return model
  23. def insert_ip_token(ip,demo_name,gpt_content,prompt_tokens,completion_tokens,total_tokens):
  24. sql = "insert into consumer_token (ip,demo_name,gpt_content,prompt_tokens,completion_tokens,total_tokens) values (%s,%s,%s,%s,%s,%s)"
  25. m.execute_(sql,(ip,demo_name,str(gpt_content),prompt_tokens,completion_tokens,total_tokens))
  26. def get_answer_from_gpt(question,real_ip="localhost",demo_name="无",model="gpt-4o",max_tokens=3500,temperature:float=0,
  27. json_resp:Union[Dict[Any, Any],bool]=False,n=1,check_fucn=None,sys_prompt=None):
  28. model = get_openai_model(model)
  29. d2 = {"model": model,"messages": [],"max_tokens": max_tokens,"temperature": temperature,'n': n}
  30. if sys_prompt:
  31. d2['messages'].append({"role": "system", "content": sys_prompt})
  32. d2['messages'].append({"role": "user", "content": question})
  33. if json_resp is True:
  34. d2["response_format"] = {"type": "json_object"}
  35. elif json_resp is False:
  36. pass
  37. else:
  38. d2["response_format"] = json_resp
  39. for num_count in range(3):
  40. try:
  41. response = requests.post(f'http://170.106.108.95/v1/chat/completions', json=d2)
  42. r_json = response.json()
  43. if r2:= r_json.get("choices",None):
  44. if n>1:
  45. gpt_res = []
  46. for i in r2:
  47. gpt_res.append(i["message"]["content"])
  48. else:
  49. gpt_res= r2[0]["message"]["content"]
  50. gpt_content = str(gpt_res)
  51. prompt_tokens = r_json["usage"]["prompt_tokens"]
  52. completion_tokens = r_json["usage"]["completion_tokens"]
  53. total_tokens = r_json["usage"]["total_tokens"]
  54. insert_ip_token(real_ip,demo_name,gpt_content,prompt_tokens,completion_tokens,total_tokens)
  55. simple_logger.info(f"问题日志:\n{question}\n回答日志:\n{gpt_res}")
  56. if not check_fucn:
  57. return gpt_res
  58. check_result = check_fucn(str(gpt_res))
  59. if check_result:
  60. return gpt_res
  61. else:
  62. raise Exception(f"忽略,第{num_count+1}次共3次,GPT的校验没有通过,校验函数:{check_fucn.__name__}")
  63. elif r_json.get("message") == "IP address blocked":
  64. print("IP address blocked")
  65. raise Exception("IP address blocked")
  66. else:
  67. print(f"小错误:{question[:10]}")
  68. logger.error(response.text)
  69. except Exception as e:
  70. logger.info(f"忽略小报错{e}")
  71. time.sleep(10)
  72. logger.critical("get_answer_from_gpt 严重错误,3次后都失败了")
  73. def get_article_gpt_pydantic(question, real_ip="localhost", demo_name="无", model="gpt-4.1", max_tokens=3500, temperature:float=0, n=1,
  74. check_fucn=None, sys_prompt=None,task_id=0,exercise_id=0):
  75. """
  76. 异步获取文章
  77. :param question: 问题
  78. :param real_ip: 真实IP
  79. :param demo_name: 项目名称
  80. :param model: 模型名称
  81. :param max_tokens: 最大token数
  82. :param temperature: 温度
  83. :param n: 生成数量
  84. :param check_fucn: 校验函数
  85. :param sys_prompt: 系统提示
  86. :param task_id: 任务id
  87. :param exercise_id: 学案id
  88. :return: 文章内容
  89. """
  90. d2 = {"model": model, "messages": [], "max_tokens": max_tokens, "temperature": temperature,"n":n,
  91. "response_format":{'type': 'json_schema', 'json_schema': {'name': 'Article', 'schema': {'$defs': {'Candidate': {'properties': {'label': {'allOf': [{'$ref': '#/$defs/Options'}], 'description': 'ABCD序号的一种', 'title': '序号'}, 'text': {'description': '英文,ABCD选项的文本', 'title': '选项文本', 'type': 'string'}, 'isRight': {'allOf': [{'$ref': '#/$defs/IsRight'}], 'description': '1是正确,0是错误', 'title': '是否是正确答案'}}, 'required': ['label', 'text', 'isRight'], 'title': 'Candidate', 'type': 'object'}, 'DifficultSentence': {'properties': {'english': {'description': '文章中的一句难句', 'title': '英语难句', 'type': 'string'}, 'chinese': {'description': '对英语难句的翻译', 'title': '中文难句', 'type': 'string'}}, 'required': ['english', 'chinese'], 'title': 'DifficultSentence', 'type': 'object'}, 'IsRight': {'enum': [1, 0], 'title': 'IsRight', 'type': 'integer'}, 'Options': {'enum': ['A', 'B', 'C', 'D'], 'title': 'Options', 'type': 'string'}, 'Question': {'properties': {'trunk': {'description': '用英语给出的选择题题目', 'title': '选择题题目', 'type': 'string'}, 'analysis': {'description': '中文,选择题的分析思路;不要给出答案的ABCD序号', 'title': '选择题分析', 'type': 'string'}, 'candidates': {'description': '一共4个选择题', 'items': {'$ref': '#/$defs/Candidate'}, 'title': '选项对象', 'type': 'array'}}, 'required': ['trunk', 'analysis', 'candidates'], 'title': 'Question', 'type': 'object'}}, 'properties': {'difficultSentences': {'description': '挑选一句难句对象', 'items': {'$ref': '#/$defs/DifficultSentence'}, 'title': '难句对象', 'type': 'array'}, 'usedMeanIds': {'items': {'type': 'integer'}, 'title': '用到的词义id', 'type': 'array'}, 'questions': {'description': '针对英语文章的选择题', 'items': {'$ref': '#/$defs/Question'}, 'title': '问题对象', 'type': 'array'}, 'englishArticle': {'description': '', 'title': '英语文章', 'type': 'string'}, 'chineseArticle': {'description': '', 'title': '中文翻译', 'type': 'string'}}, 'required': ['difficultSentences', 'usedMeanIds', 'questions', 'englishArticle', 'chineseArticle'], 'title': 'Article', 'type': 'object'}}}
  92. }
  93. if sys_prompt:
  94. d2['messages'].append({"role": "system", "content": sys_prompt})
  95. d2['messages'].append({"role": "user", "content": question})
  96. for num_count in range(3):
  97. answer = ""
  98. try:
  99. response = requests.post('http://170.106.108.95/v1/chat/completions', json=d2)
  100. r_json = response.json()
  101. for choice in r_json["choices"]:
  102. answer = ujson.dumps(ujson.loads(choice["message"]["content"]),ensure_ascii=False)
  103. Article.model_validate_json(answer)
  104. check_result = check_fucn(str(answer))
  105. if not check_result:
  106. logger.error(answer)
  107. raise Exception(f"忽略,第{num_count + 1}次共3次,GPT的校验没有通过,校验函数:{check_fucn.__name__}")
  108. simple_logger.info(f"问题日志task_id:{task_id},exercise_id:{exercise_id}\n回答日志:\n{r_json}")
  109. return r_json
  110. except ValidationError as e:
  111. logger.error(f"gpt回复校验失败task_id:{task_id},exercise_id:{exercise_id}:")
  112. logger.error(answer)
  113. except requests.exceptions.RequestException as e:
  114. logger.error(f"HTTP请求错误task_id:{task_id},exercise_id:{exercise_id}: {str(e)}")
  115. time.sleep(1)
  116. except json.decoder.JSONDecodeError as e:
  117. if 'response' in locals() and response is not None:
  118. logger.error(f"json格式化错误task_id:{task_id},exercise_id:{exercise_id}:{response.text}")
  119. except Exception as e:
  120. log_err_e(e,f"其他错误task_id:{task_id},exercise_id:{exercise_id}")
  121. def get_annotation_gpt_pydantic(question, real_ip="localhost", demo_name="无", model="gpt-4.1", max_tokens=3500, temperature:float=0, n=1,
  122. check_fucn=None, sys_prompt=None,task_id=0,exercise_id=0):
  123. """
  124. 异步获取文章
  125. :param question: 问题
  126. :param real_ip: 真实IP
  127. :param demo_name: 项目名称
  128. :param model: 模型名称
  129. :param max_tokens: 最大token数
  130. :param temperature: 温度
  131. :param n: 生成数量
  132. :param check_fucn: 校验函数
  133. :param sys_prompt: 系统提示
  134. :param task_id: 任务id
  135. :param exercise_id: 学案id
  136. :return: 标注内容
  137. """
  138. d2 = {"model": model, "messages": [], "max_tokens": max_tokens, "temperature": temperature,"n":n,
  139. "response_format":{'type': 'json_schema', 'json_schema': {'name': 'Annotation', 'schema': {'properties': {'annotation_text': {'description': '对句子或文章的每个单词进行词义id的标注', 'examples': ['an[33] apple[123]'], 'title': '标注文本', 'type': 'string'}}, 'required': ['annotation_text'], 'title': 'Annotation', 'type': 'object'}}}
  140. }
  141. if sys_prompt:
  142. d2['messages'].append({"role": "system", "content": sys_prompt})
  143. d2['messages'].append({"role": "user", "content": question})
  144. for num_count in range(3):
  145. try:
  146. response = requests.post('http://170.106.108.95/v1/chat/completions', json=d2)
  147. r_json = response.json()
  148. for choice in r_json["choices"]:
  149. Annotation.model_validate_json(choice["message"]["content"])
  150. annotation_logger.info(f"日志task_id:{task_id},exercise_id:{exercise_id}:\n问题日志:\n{question}\n回答日志:\n{r_json}")
  151. return r_json
  152. except ValidationError as e:
  153. logger.error(f"gpt回复校验失败task_id:{task_id},exercise_id:{exercise_id}:")
  154. except requests.exceptions.RequestException as e:
  155. logger.error(f"HTTP请求错误task_id:{task_id},exercise_id:{exercise_id}: {str(e)}")
  156. time.sleep(1)
  157. except json.decoder.JSONDecodeError as e:
  158. if 'response' in locals() and response is not None:
  159. logger.error(f"json格式化错误task_id:{task_id},exercise_id:{exercise_id}:{response.text}")
  160. except Exception as e:
  161. log_err_e(e,f"其他错误task_id:{task_id},exercise_id:{exercise_id}")
  162. def parse_gpt_phon_to_tuplelist(text:str) -> list:
  163. """解析gpt返回的音标数据"""
  164. result = []
  165. if not text:
  166. return []
  167. for i in text.split("\n"):
  168. ii = i.split("***")
  169. if len(ii)>=3:
  170. result.append((ii[0].strip(),ii[1].strip(),ii[2].strip()))
  171. return result