bing-chat-api / apis /chat_api.py
Hansimov's picture
:gem: [Feature] ChatAPIApp: argparser for dev, and hide schema for some routes
4107531
raw
history blame
6.33 kB
import argparse
import sys
import uvicorn
from fastapi import FastAPI
from pydantic import BaseModel, Field
from sse_starlette.sse import EventSourceResponse
from conversations import (
ConversationConnector,
ConversationCreator,
MessageComposer,
)
from utils.logger import logger
class ChatAPIApp:
def __init__(self):
self.app = FastAPI(
docs_url="/",
title="Bing Chat API",
swagger_ui_parameters={"defaultModelsExpandDepth": -1},
version="1.0",
)
self.setup_routes()
def get_available_models(self):
self.available_models = {
"object": "list",
"data": [
{
"id": "precise",
"description": "Bing (Precise): Concise and straightforward.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
{
"id": "balanced",
"description": "Bing (Balanced): Informative and friendly.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
{
"id": "creative",
"description": "Bing (Creative): Original and imaginative.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
{
"id": "precise-offline",
"description": "Bing (Precise): (No Internet) Concise and straightforward.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
{
"id": "balanced-offline",
"description": "Bing (Balanced): (No Internet) Informative and friendly.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
{
"id": "creative-offline",
"description": "Bing (Creative): (No Internet) Original and imaginative.",
"object": "model",
"created": 1700000000,
"owned_by": "bing",
},
],
}
return self.available_models
class CreateConversationSessionPostItem(BaseModel):
model: str = Field(
default="precise",
description="(str) `precise`, `balanced`, `creative`, `precise-offline`, `balanced-offline`, `creative-offline`",
)
def create_conversation_session(self, item: CreateConversationSessionPostItem):
creator = ConversationCreator()
creator.create()
return {
"model": item.model,
"sec_access_token": creator.sec_access_token,
"client_id": creator.client_id,
"conversation_id": creator.conversation_id,
}
class ChatCompletionsPostItem(BaseModel):
model: str = Field(
default="precise",
description="(str) `precise`, `balanced`, `creative`, `precise-offline`, `balanced-offline`, `creative-offline`",
)
messages: list = Field(
default=[{"role": "user", "content": "Hello, who are you?"}],
description="(list) Messages",
)
def chat_completions(self, item: ChatCompletionsPostItem):
creator = ConversationCreator()
creator.create()
connector = ConversationConnector(
conversation_style=item.model,
sec_access_token=creator.sec_access_token,
client_id=creator.client_id,
conversation_id=creator.conversation_id,
cookies=creator.request_cookies,
invocation_id=0,
)
message_composer = MessageComposer()
prompt = message_composer.merge(item.messages)
logger.mesg(item.messages[-1]["content"])
system_prompt = message_composer.system_prompt
return EventSourceResponse(
connector.stream_chat(
prompt=prompt, system_prompt=system_prompt, yield_output=True
),
ping=2000,
media_type="text/event-stream",
)
def setup_routes(self):
for prefix in ["", "/v1", "/api", "/api/v1"]:
include_in_schema = True if prefix == "" else False
self.app.get(
prefix + "/models",
summary="Get available models",
include_in_schema=include_in_schema,
)(self.get_available_models)
self.app.post(
prefix + "/create",
summary="Create a conversation session",
include_in_schema=include_in_schema,
)(self.create_conversation_session)
self.app.post(
prefix + "/chat/completions",
summary="Chat completions in conversation session",
include_in_schema=include_in_schema,
)(self.chat_completions)
class ArgParser(argparse.ArgumentParser):
def __init__(self, *args, **kwargs):
super(ArgParser, self).__init__(*args, **kwargs)
self.add_argument(
"-s",
"--server",
type=str,
default="0.0.0.0",
help="Server IP for Bing Chat API",
)
self.add_argument(
"-p",
"--port",
type=int,
default=22222,
help="Server Port for Bing Chat API",
)
self.add_argument(
"-d",
"--dev",
default=False,
action="store_true",
help="Run in dev mode",
)
self.args = self.parse_args(sys.argv[1:])
app = ChatAPIApp().app
if __name__ == "__main__":
args = ArgParser().args
if args.dev:
uvicorn.run("__main__:app", host=args.server, port=args.port, reload=True)
else:
uvicorn.run("__main__:app", host=args.server, port=args.port, reload=False)
# python -m apis.chat_api # [Docker] on product mode
# python -m apis.chat_api -d # [Dev] on develop mode