chatgpt.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266
  1. # -*- coding:utf-8 -*-
  2. if __name__ == '__main__':
  3. import os
  4. os.chdir("..")
  5. import time
  6. from typing import Dict, Any, Union
  7. import httpx
  8. import requests
  9. from tools.loglog import logger, simple_logger, log_err_e
  10. from tools.new_mysql import MySQLUploader
  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):
  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. :return: 文章内容
  87. """
  88. d2 = {"model": model, "messages": [], "max_tokens": max_tokens, "temperature": temperature, "n": n, "response_format": {'type': 'json_schema',
  89. 'json_schema': {
  90. 'name': 'Article',
  91. 'schema': {'$defs': {
  92. 'Candidate': {
  93. 'properties': {
  94. 'label': {
  95. 'title': 'Label',
  96. 'type': 'string'},
  97. 'text': {
  98. 'title': 'Text',
  99. 'type': 'string'},
  100. 'isRight': {
  101. 'title': 'Isright',
  102. 'type': 'integer'}},
  103. 'required': [
  104. 'label',
  105. 'text',
  106. 'isRight'],
  107. 'title': 'Candidate',
  108. 'type': 'object'},
  109. 'DifficultSentence': {
  110. 'properties': {
  111. 'english': {
  112. 'title': 'English',
  113. 'type': 'string'},
  114. 'chinese': {
  115. 'title': 'Chinese',
  116. 'type': 'string'}},
  117. 'required': [
  118. 'english',
  119. 'chinese'],
  120. 'title': 'DifficultSentence',
  121. 'type': 'object'},
  122. 'Question': {
  123. 'properties': {
  124. 'trunk': {
  125. 'title': 'Trunk',
  126. 'type': 'string'},
  127. 'analysis': {
  128. 'title': 'Analysis',
  129. 'type': 'string'},
  130. 'candidates': {
  131. 'items': {
  132. '$ref': '#/$defs/Candidate'},
  133. 'title': 'Candidates',
  134. 'type': 'array'}},
  135. 'required': [
  136. 'trunk',
  137. 'analysis',
  138. 'candidates'],
  139. 'title': 'Question',
  140. 'type': 'object'}},
  141. 'properties': {
  142. 'difficultSentences': {
  143. 'items': {
  144. '$ref': '#/$defs/DifficultSentence'},
  145. 'title': 'Difficultsentences',
  146. 'type': 'array'},
  147. 'usedMeanIds': {
  148. 'items': {
  149. 'type': 'integer'},
  150. 'title': 'Usedmeanids',
  151. 'type': 'array'},
  152. 'questions': {
  153. 'items': {
  154. '$ref': '#/$defs/Question'},
  155. 'title': 'Questions',
  156. 'type': 'array'},
  157. 'englishArticle': {
  158. 'title': 'Englisharticle',
  159. 'type': 'string'},
  160. 'chineseArticle': {
  161. 'title': 'Chinesearticle',
  162. 'type': 'string'},
  163. 'allWordAmount': {
  164. 'title': 'Allwordamount',
  165. 'type': 'integer'}},
  166. 'required': [
  167. 'difficultSentences',
  168. 'usedMeanIds',
  169. 'questions',
  170. 'englishArticle',
  171. 'chineseArticle',
  172. 'allWordAmount'],
  173. 'title': 'Article',
  174. 'type': 'object'}}}}
  175. if sys_prompt:
  176. d2['messages'].append({"role": "system", "content": sys_prompt})
  177. d2['messages'].append({"role": "user", "content": question})
  178. for num_count in range(3):
  179. try:
  180. response = requests.post('http://170.106.108.95/v1/chat/completions', json=d2)
  181. r_json = response.json()
  182. simple_logger.info(f"问题日志:\n{question}\n回答日志:\n{r_json}")
  183. return r_json
  184. #
  185. #
  186. except httpx.HTTPError as e:
  187. logger.error(f"HTTP请求错误: {str(e)}")
  188. if num_count < 2:
  189. time.sleep(10)
  190. else:
  191. raise
  192. except Exception as e:
  193. log_err_e(e, "其他错误")
  194. if num_count < 2:
  195. time.sleep(10)
  196. else:
  197. raise
  198. logger.critical("get_article_gpt_pydantic 严重错误,3次后都失败了")
  199. raise Exception("获取文章失败,已达到最大重试次数")
  200. def parse_gpt_phon_to_tuplelist(text: str) -> list:
  201. """解析gpt返回的音标数据"""
  202. result = []
  203. if not text:
  204. return []
  205. for i in text.split("\n"):
  206. ii = i.split("***")
  207. if len(ii) >= 3:
  208. result.append((ii[0].strip(), ii[1].strip(), ii[2].strip()))
  209. return result
  210. if __name__ == '__main__':
  211. question = "hello"
  212. sys_prompt = "你是一个专业的英语老师,擅长根据用户提供的词汇生成对应的英语文章和中文翻译和4个配套选择题。"
  213. q = """下面我会为你提供两组数据,[单词组1]和[单词组2](里面包含词义id,英语单词,中文词义),优先使用[单词组1]内的单词,请根据这些单词的中文词义,生成一篇带中文翻译的考场英语文章,英语文章和中文翻译要有[标题]。注意这个单词有多个词义时,生成的英语文章一定要用提供的中文词义。并挑选一句复杂的句子和其中文翻译,放入difficultSentences。英语文章,放入"englishArticle"中。中文翻译,放入"chineseArticle"中。最终文中使用到的单词id放入"usedMeanIds"中。4个选择题,放入questions字段。questions结构下有4个选择题对象,其中trunk是[英语]问题文本,analysis是[中文]的问题分析,candidates是4个ABCD选项,内部有label是指选项序号A B C D ,text是[英语]选项文本,isRight是否正确答案1是正确0是错误。
  214. 要求:
  215. 1.必须用提供的这个词义的单词,其他单词使用常见、高中难度的的单词。文章整体难度适中,大约和中国的高中生,中国CET-6,雅思6分这样的难度标准。
  216. 2.优先保证文章语句通顺,意思不要太生硬。不要为了使用特定的单词,造成文章语义前后不搭,允许不使用个别词义。
  217. 3.文章中使用提供单词,一定要和提供单词的中文词义匹配,尤其是一词多义时,务必使用提供单词的词义。必须要用提供单词的词义。如果用到的词义与提供单词词义不一致,请不要使用这个单词。
  218. 4.生成的文章要求600词左右,可以用\\n\\n字符分段,一般5个段落左右。第一段是文章标题。
  219. 5.生成文章优先使用[单词组1]的词义,其次可以挑选使用[单词组2]的词义。允许不使用[单词组1]的个别单词,优先保证文章整体意思通顺连贯和故事完整。
  220. 提供[单词组1]:4238 penalty:惩罚, 刑罚;4591 bare:赤裸的, 无遮蔽的;4227 stable:畜舍, 马厩;4236 psychology:心理学;4245 offense:进攻, 攻势, 冒犯, 触怒, 过错;4237 innocent:清白的, 无辜的, 天真的;4228 refrigerator:冰箱, 冷库;4247 tissue:(动植物)组织;4250 awareness:察觉, 觉悟, 意识;4234 mode:方式, 模式;4224 neat:整洁, 利索;4225 statistics:统计;4251 random:任意的, 随机的;4201 laundry:洗衣房;4545 barrel:桶, 一桶之量;4249 recruit:招募, 新成员;4229 pregnant:怀孕的, 孕育的;4235 relevant:有关的, 相关联的;4252 incentive:刺激, 激励, 鼓励;4194 grave:坟墓, 墓穴;
  221. 提供[单词组2]:;
  222. """
  223. resp = get_answer_from_gpt(question=question, temperature=0.9, sys_prompt=sys_prompt, model="gpt-4.1")
  224. print(type(resp))
  225. print(resp)