Linon

popai

May 12th, 2024
199
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.20 KB | None | 0 0
  1. import json
  2. import os
  3.  
  4. import requests
  5. import uvicorn
  6. from fastapi import Request, Response, FastAPI
  7. from starlette.middleware.cors import CORSMiddleware
  8.  
  9. from chat2api import ChatServer, Chat2API
  10. from chat2api.api import OpenaiAPI
  11. from chat2api.util import now, LRUCache, is_summary
  12.  
  13.  
  14. class PopAi(ChatServer):
  15.     MODELS = {
  16.         'gpt-3.5': 'Standard',
  17.         'gpt-3.5-turbo': 'Standard',
  18.         'gpt-4': 'GPT-4',
  19.         'internet': 'Web Search',
  20.         'draw': 'Image generation',
  21.     }
  22.  
  23.     def __init__(self, client: OpenaiAPI, authorization, gtoken):
  24.         self.client = client
  25.         self.authorization = authorization
  26.         self.gtoken = gtoken
  27.  
  28.     def convert_messages_to_prompt(self, messages):
  29.         # Initialize an empty string to store concatenated content
  30.         concatenated_content = ""
  31.         for message in messages:
  32.             content = message["content"]
  33.             # Split the text into a list of lines
  34.             content_lines = content.splitlines()
  35.             # Remove the first line and rejoin the remaining lines
  36.             content_wo_first_line = '\n'.join(content_lines[1:])
  37.             print(content_wo_first_line)
  38.             # If the content is not empty, add it to the concatenated_content string
  39.             if content_wo_first_line:
  40.                 # Add the content to the string with an additional newline as a separator
  41.                 concatenated_content += content_wo_first_line + "\n"
  42.         # Remove the last newline character to avoid an extra empty line at the end
  43.         concatenated_content = concatenated_content.strip('\n')
  44.         return concatenated_content
  45.    
  46.  
  47.     def answer_stream(self):
  48.         question = self.client.question
  49.         text = self.convert_messages_to_prompt(self.client.messages)
  50.         print(text)
  51.         if is_summary(question):
  52.             model = PopAi.MODELS['gpt-3.5']
  53.         else:
  54.             model = PopAi.MODELS.get(self.client.model, 'GPT-4')
  55.         proxy = os.environ.get("PROXY")
  56.         if proxy:
  57.             proxies = {'all': proxy}
  58.         else:
  59.             proxies = None
  60.         context_id = None
  61.         if len(self.client.messages) > 2 and not is_summary(question):
  62.             # 上下文
  63.             for msg in self.client.messages:
  64.                 if msg['role'] == 'user':
  65.                     context_id = FIND_CHAT_BY_QUESTION.get(msg['content'])
  66.                     if context_id:
  67.                         break
  68.         isNewChat = context_id is None
  69.  
  70.         if context_id is None:
  71.             channel_resp = requests.post(
  72.                 'https://api.popai.pro/api/v1/chat/getChannel',
  73.                 headers={'Authorization': self.authorization},
  74.                 json={
  75.                     "model": model,
  76.                     "templateId": "",
  77.                     "message": question,
  78.                     "language": "English",
  79.                     "fileType": None
  80.                 },
  81.                 proxies=proxies,
  82.             )
  83.             channel_resp.raise_for_status()
  84.             context_id = channel_resp.json()['data']['channelId']
  85.  
  86.         print('-' * 30, '\n')
  87.         print('question: \n', question)
  88.         print('-' * 30, '\n')
  89.         print('answer: ')
  90.  
  91.         url = 'https://api.popai.pro/api/v1/chat/send'
  92.         headers = {
  93.             "accept": "text/event-stream",
  94.             "accept-language": "zh-CN,zh;q=0.9,en;q=0.8,zh-TW;q=0.7,zh-HK;q=0.6",
  95.             "app-name": "popai-web",
  96.             "authorization": self.authorization,
  97.             "content-type": "application/json",
  98.             "device-info": "{web_id:k-s8Xp4S9LEmrHghBhT2m,baidu_id:18f1ff567e243687188711}",
  99.             "gtoken": self.gtoken,
  100.             "language": "en",
  101.             "origin": "https://www.popai.pro",
  102.             "priority": "u=1, i",
  103.             "referer": "https://www.popai.pro/",
  104.             "sec-ch-ua-mobile": "?0",
  105.             "sec-ch-ua-platform": "Windows",
  106.             "sec-fetch-mode": "cors",
  107.             "sec-fetch-site": "same-site",
  108.         }
  109.  
  110.         req_json = {
  111.             "isGetJson": True,
  112.             "version": "1.3.6",
  113.             "language": "zh-CN",
  114.             "channelId": context_id,
  115.             "isNewChat": isNewChat,
  116.             "message": text if isNewChat else question,
  117.             "model": model,
  118.             "messageIds": [],
  119.             "improveId": None,
  120.             "richMessageId": None,
  121.             "isNewChat": False,
  122.             "action": None,
  123.             "isGeneratePpt": False,
  124.             "isSlidesChat": False,
  125.             "imageUrls": [],
  126.             "roleEnum": None,
  127.             "pptCoordinates": "",
  128.             "translateLanguage": None,
  129.             "docPromptTemplateId": None
  130.         }
  131.        
  132.         if isNewChat:
  133.             # 第一次 POST 请求,使用 text
  134.             req_json['message'] = text+"\nIf understand,answer OK."
  135.             resp = requests.post(url, json=req_json, headers=headers, proxies=proxies, stream=True)
  136.  
  137.             # 第二次 POST 请求,使用 question
  138.             req_json['message'] = question
  139.             resp = requests.post(url, json=req_json, headers=headers, proxies=proxies, stream=True)
  140.         else:
  141.             # 如果不是新对话,只发送一次 POST 请求
  142.             req_json['message'] = question
  143.             resp = requests.post(url, json=req_json, headers=headers, proxies=proxies, stream=True)
  144.         resp.raise_for_status()
  145.         resp.encoding = 'utf-8'
  146.         lines = resp.iter_lines(decode_unicode=True)
  147.         for data in lines:
  148.             # 首条消息是用户提问,舍掉
  149.             if data.startswith('data:'):
  150.                 infos = json.loads(data[5:])
  151.                 context_id = infos[0].get('channelId')
  152.                 FIND_CHAT_BY_QUESTION[question] = context_id
  153.                 break
  154.         for data in lines:
  155.             if data.startswith('data:'):
  156.                 infos = json.loads(data[5:])
  157.                 for info in infos:
  158.                     # msg_id = info.get('messageId')
  159.                     word = info.get('content')
  160.                     if word:
  161.                         print(word, end='')
  162.                         yield word
  163.         print()
  164.  
  165.  
  166. app = FastAPI(title="PopAi Chat", description="PopAi Chat")
  167.  
  168. app.add_middleware(
  169.     CORSMiddleware,
  170.     allow_origins=["*"],
  171.     allow_credentials=True,
  172.     allow_methods=["*"],
  173.     allow_headers=["*"],
  174. )
  175.  
  176.  
  177. @app.get('/v1/models')
  178. def list_models():
  179.     return {
  180.         "object": "list",
  181.         "data": [{
  182.             "id": m,
  183.             "object": "model",
  184.             "created": now(),
  185.             "owned_by": "popai"
  186.         } for m in PopAi.MODELS]
  187.     }
  188.  
  189.  
  190. @app.options('/v1/chat/completions')
  191. async def pre_chat():
  192.     return Response()
  193.  
  194.  
  195. @app.post('/v1/chat/completions')
  196. async def chat(request: Request):
  197.     cli = OpenaiAPI()
  198.     ser = PopAi(cli, AUTHORIZATION, GTOKEN)
  199.     return await Chat2API(cli, ser).response(request)
  200.  
  201.  
  202. if __name__ == '__main__':
  203.     AUTHORIZATION = os.environ.get('AUTHORIZATION')
  204.     GTOKEN = os.environ.get('GTOKEN')
  205.     assert not AUTHORIZATION or GTOKEN, 'AUTHORIZATION and GTOKEN must be set'
  206.     FIND_CHAT_BY_QUESTION = LRUCache(1000)
  207.  
  208.     uvicorn.run(app, host='0.0.0.0', port=5005)
  209.  
Advertisement
Add Comment
Please, Sign In to add comment