wnum commited on
Commit
f7dc7b8
·
verified ·
1 Parent(s): 848499e

Upload 2 files

Browse files
Files changed (2) hide show
  1. Dockerfile +6 -0
  2. main.py +99 -0
Dockerfile ADDED
@@ -0,0 +1,6 @@
 
 
 
 
 
 
 
1
+ FROM python:3.11
2
+
3
+ COPY main.py /app/main.py
4
+ WORKDIR /app
5
+ RUN pip install --break-system-packages fastapi uvicorn uvloop fastapi_poe
6
+
main.py ADDED
@@ -0,0 +1,99 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ DEFAULT_MODEL = os.getenv("BOT", default="Claude-3-Sonnet")
4
+ LISTEN_PORT = int(os.getenv("PORT", default=7860))
5
+ BASE_URL = os.getenv("BASE", default="https://api.poe.com/bot/")
6
+ POE_API_KEY = os.getenv("POE_API_KEY","")
7
+ AUTHORIZATION_API_KEY = os.getenv("AUTHORIZATION_API_KEY","")
8
+ if not POE_API_KEY or not AUTHORIZATION_API_KEY:
9
+ raise ValueError("POE_API_KEY and AUTHORIZATION_API_KEY must be set in the environment variables")
10
+
11
+ from fastapi import FastAPI, Request, Header, HTTPException
12
+ from fastapi.responses import StreamingResponse
13
+ from fastapi.middleware.cors import CORSMiddleware
14
+
15
+ import uvicorn
16
+ from typing import AsyncGenerator
17
+ import json
18
+
19
+ from fastapi_poe.types import ProtocolMessage
20
+ from fastapi_poe.client import get_bot_response
21
+
22
+
23
+ app = FastAPI()
24
+ app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_credentials=True, allow_methods=["*"], allow_headers=["*"])
25
+
26
+ async def generate_responses(api_key: str, formatted_messages: list, bot_name: str) -> AsyncGenerator[str, None]:
27
+ """An async generator to stream responses from the POE API."""
28
+
29
+ # Create a base response template
30
+ response_template = {
31
+ "id": "chatcmpl-123",
32
+ "object": "chat.completion.chunk",
33
+ "created": 1694268190,
34
+ "model": bot_name,
35
+ "choices": [{
36
+ "index": 0,
37
+ "delta": {
38
+ "content": "", # Placeholder, to be filled for each partial response
39
+ "logprobs": None,
40
+ "finish_reason": None
41
+ }
42
+ }]
43
+ }
44
+
45
+ async for partial in get_bot_response(messages=formatted_messages, bot_name=bot_name, api_key=api_key,
46
+ base_url=BASE_URL,
47
+ skip_system_prompt=False,
48
+ logit_bias={'24383':-100}):
49
+
50
+ # Fill the required field for this partial response
51
+ response_template["choices"][0]["delta"]["content"] = partial.text
52
+
53
+ # Create the SSE formatted string, and then yield
54
+ yield f"data: {json.dumps(response_template)}\n\n"
55
+
56
+ # Send termination sequence
57
+ response_template["choices"][0]["delta"] = {} # Empty 'delta' field
58
+ response_template["choices"][0]["finish_reason"] = "stop" # Set 'finish_reason' to 'stop'
59
+
60
+ yield f"data: {json.dumps(response_template)}\n\ndata: [DONE]\n\n"
61
+
62
+
63
+ @app.post("/v1/chat/completions")
64
+ async def chat_completions(request: Request, authorization: str = Header(None)):
65
+ if not authorization:
66
+ raise HTTPException(status_code=401, detail="Authorization header is missing")
67
+
68
+ api_key = authorization.split(" ")[1] # Assuming the header follows the standard format: "Bearer $API_KEY"
69
+ if api_key != AUTHORIZATION_API_KEY:
70
+ return HTTPException(status_code=401, detail="Invalid API Key")
71
+ body = await request.json()
72
+
73
+ # Extract bot_name (model) and messages from the request body
74
+ bot_name = body.get("model", DEFAULT_MODEL) # Defaulting to a specific bot if not provided
75
+ messages = body.get("messages", [])
76
+
77
+ formatted_messages = [ProtocolMessage(role=msg["role"].lower().replace("assistant", "bot"),
78
+ content=msg["content"],
79
+ temperature=msg.get("temperature", 0.95))
80
+ for msg in messages]
81
+
82
+ async def response_stream() -> AsyncGenerator[str, None]:
83
+ async for response_content in generate_responses(api_key, formatted_messages, bot_name):
84
+ # Assuming each response_content is a complete "message" response from the bot.
85
+ # Adjust according to actual response pattern if needed.
86
+ yield response_content
87
+
88
+ # Stream responses back to the client
89
+ # Wrap the streamed content to fit the desired response format
90
+ return StreamingResponse(response_stream(), media_type="application/json")
91
+
92
+ if __name__ == '__main__':
93
+ try:
94
+ import uvloop
95
+ except ImportError:
96
+ uvloop = None
97
+ if uvloop:
98
+ uvloop.install()
99
+ uvicorn.run(app, host="0.0.0.0", port=LISTEN_PORT)