大模型接口远程访问
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.
 
 
 
 
 

177 lines
6.9 KiB

  1. import _thread as thread
  2. import base64
  3. import datetime
  4. import hashlib
  5. import hmac
  6. import json
  7. from urllib.parse import urlparse
  8. import ssl
  9. from datetime import datetime
  10. from time import mktime
  11. from urllib.parse import urlencode
  12. from wsgiref.handlers import format_date_time
  13. import websocket
  14. import threading
  15. from threading import Condition
  16. class Ws_Param(object):
  17. # 初始化
  18. def __init__(self, APPID, APIKey, APISecret, gpt_url, condition):
  19. self.APPID = APPID
  20. self.APIKey = APIKey
  21. self.APISecret = APISecret
  22. self.host = urlparse(gpt_url).netloc
  23. self.path = urlparse(gpt_url).path
  24. self.gpt_url = gpt_url
  25. self.resp = ''
  26. self.condition = condition
  27. # 生成url
  28. def create_url(self):
  29. # 生成RFC1123格式的时间戳
  30. now = datetime.now()
  31. date = format_date_time(mktime(now.timetuple()))
  32. # 拼接字符串
  33. signature_origin = "host: " + self.host + "\n"
  34. signature_origin += "date: " + date + "\n"
  35. signature_origin += "GET " + self.path + " HTTP/1.1"
  36. # 进行hmac-sha256进行加密
  37. signature_sha = hmac.new(self.APISecret.encode('utf-8'), signature_origin.encode('utf-8'),
  38. digestmod=hashlib.sha256).digest()
  39. signature_sha_base64 = base64.b64encode(signature_sha).decode(encoding='utf-8')
  40. authorization_origin = f'api_key="{self.APIKey}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha_base64}"'
  41. authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode(encoding='utf-8')
  42. # 将请求的鉴权参数组合为字典
  43. v = {
  44. "authorization": authorization,
  45. "date": date,
  46. "host": self.host
  47. }
  48. # 拼接鉴权参数,生成url
  49. url = self.gpt_url + '?' + urlencode(v)
  50. # 此处打印出建立连接时候的url,参考本demo的时候可取消上方打印的注释,比对相同参数时生成的url与自己代码生成的url是否一致
  51. return url
  52. # 收到websocket消息的处理
  53. def on_message(self, ws, message):
  54. # print(message)
  55. data = json.loads(message)
  56. code = data['header']['code']
  57. if code != 0:
  58. print(f'请求错误: {code}, {data}')
  59. ws.close()
  60. else:
  61. choices = data["payload"]["choices"]
  62. status = choices["status"]
  63. content = choices["text"][0]["content"]
  64. print(content, end='')
  65. self.resp += content
  66. if status == 2:
  67. ws.close()
  68. def on_close(self, ws, *args):
  69. print("### closed ###")
  70. # self.condition.notify()
  71. # 收到websocket错误的处理
  72. def on_error(ws, error):
  73. print("### error:", error)
  74. # 收到websocket关闭的处理
  75. def on_close(ws, *args):
  76. print("### closed ###")
  77. # 收到websocket连接建立的处理
  78. def on_open(ws):
  79. thread.start_new_thread(run, (ws,))
  80. def run(ws, *args):
  81. data = json.dumps(gen_params(appid=ws.appid, question=ws.question))
  82. ws.send(data)
  83. # 收到websocket消息的处理
  84. def on_message(ws, message):
  85. # print(message)
  86. data = json.loads(message)
  87. code = data['header']['code']
  88. if code != 0:
  89. print(f'请求错误: {code}, {data}')
  90. ws.close()
  91. else:
  92. choices = data["payload"]["choices"]
  93. status = choices["status"]
  94. content = choices["text"][0]["content"]
  95. print(content, end='')
  96. if status == 2:
  97. ws.close()
  98. def gen_params(appid, question):
  99. """
  100. 通过appid和用户的提问来生成请参数
  101. """
  102. data = {
  103. "header": {
  104. "app_id": appid,
  105. "uid": "1234"
  106. },
  107. "parameter": {
  108. "chat": {
  109. "domain": "general",
  110. "temperature": 0.01,
  111. "max_tokens": 2048,
  112. "auditing": "default"
  113. }
  114. },
  115. "payload": {
  116. "message": {
  117. "text": [
  118. # {"role": "user", "content": question},
  119. {"role": "user", "content": question}
  120. ]
  121. }
  122. }
  123. }
  124. return data
  125. def main(appid, api_key, api_secret, gpt_url, question):
  126. condition = threading.Condition()
  127. condition.acquire()
  128. wsParam = Ws_Param(appid, api_key, api_secret, gpt_url, condition)
  129. websocket.enableTrace(False)
  130. wsUrl = wsParam.create_url()
  131. print(wsUrl)
  132. ws = websocket.WebSocketApp(wsUrl, on_message=wsParam.on_message, on_error=on_error, on_close=wsParam.on_close, on_open=on_open)
  133. ws.appid = appid
  134. ws.question = question
  135. ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})
  136. # condition.wait()
  137. print("回答:" + wsParam.resp)
  138. return wsParam.resp
  139. if __name__ == "__main__":
  140. # 测试时候在此处正确填写相关信息即可运行
  141. main(appid="3d9282da",
  142. api_secret="ZTRiNDQwMTRlOTlmZDQwMDUwYTdjMDM0",
  143. api_key="7c217b3a313f4b66fcc14a8e97f85103",
  144. gpt_url="ws://spark-api.xf-yun.com/v1.1/chat",
  145. # question='你是谁')
  146. # 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。不要输出任何说明和解释。语段为“[用户]:' \
  147. 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、怎么联系财务。}。输出为JSON格式,键只有number,代表应对的编号。不要输出任何说明和解释。语段为:产品介绍')