Spaces:
Sleeping
Sleeping
DevsDoCode
commited on
Upload 10 files
Browse files- .env +9 -0
- API_provider.py +110 -0
- Dockerfile +20 -0
- RUN.py +40 -0
- SERVER.py +135 -0
- core_logic.py +136 -0
- database_initializer.py +26 -0
- problems.md +21 -0
- requirements.txt +9 -0
- test_check.py +68 -0
.env
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
FIREBASE_PROJECT_ID=telegram-storage-d867e
|
2 |
+
FIREBASE_PRIVATE_KEY_ID=ed3500ce80c609b998e45849db7407c24af34290
|
3 |
+
FIREBASE_PRIVATE_KEY="-----BEGIN PRIVATE KEY-----\nMIIEvgIBADANBgkqhkiG9w0BAQEFAASCBKgwggSkAgEAAoIBAQC+u4eVdX4f2Z3o\nrtSRixK1zpf+3qlANP6/oeQ3qYrwGC4YQ5B0Bfxr5EyzHlC4x6i9Vvnge/cb7bh9\n8J4m1yE5trpho4caOPSp63lCznVYcyG1fGVFSb0WJ40EgZvAtbVNC7kS+CzudE3p\nQ/U3iXB4COSlac/fsb1r2Mcbqb5svP/A+6j23jljwD4pgqKOmSgvCesTlpp/KRp8\nG6WZsnXfpP1Jvvd+9HkW3MzC0z24jKC7814JN0vU1yhsPuHZB6TW9FJuTgZPA5yR\ngMeKYDaemyZXpm3sB3A0fTcmOssX2A1h1U4TvOM6PKMJ2hj5B2o2ngsz1zJ7vrQK\n8oQlrDxpAgMBAAECggEASI1qPlqyrufnTucOOgzmgZ0EKXHGfQOLshahiuDl1n3E\nLvuoe9H5Got995a9CwT79YYbyB4vugJ77wA0EL89xsfw7wo27q0iuG43ssd5ULt+\n45vdo/UwRbimxkONHUmhnRyr+oDICq7YIjb1FPqleyua2ic9aTChxt/voWC47IBw\n+Vz586P+Q0+z/NYhHAJy4/MI/Du+6PutQQATVWp0RKS8MhRdxLpNFww/JJo+QaLd\nds39sGZbEy9H6xO1iT/P6i/zZ2vBMoAotGJhKywRgQl7rq6U9uroY0GylaDXd0Mh\nPjWwoxCYUGAcjnioP3VdzKlg89pvNfDX9B0WT8Ed5wKBgQD6PGOudL1uXxUQAcql\nhE8AcYaP49N52HNr+Kk2CPxtybG7yQT5oonW5tRakRFgwDYgfvV25A9j0ceSGmZC\nA4qxHHHgQ9FyZW4P7f9UZSqcgq3HHbcPQkSnUuRNTHG4/tCaqIRWUjWXx9lYkH3x\n6tg4jDATjJzTzsrg1FnR+cRvYwKBgQDDIEGVIxg23WaIzIDkEd4YlEdkK02ZDBlv\n4utVfhM4ckdEkz2myh8l9zDbi498L7ZF+b75jFkizSPbZ9SqHRRm8O5oYDZSTSs7\nlImst71m6tDqGMyuAumCzI4rLGEh6TCu3u6iQlcFhppic4PF6O1p3hIAqB9gkP1Q\njS3EHj5MwwKBgQCDmm0GXCkgOetW3spX4Ey4O/x8AmK/CyIw37cGTxWLG+9YhnES\nZPQ/TGjUNMVB7/THhF3OKEUbx0FBSpcLEtfHK+GMA77MfiGzSQTmusn9RBDmzm7v\nHHgE0+hz6sdIduL447WtvFCpQZbCKEPEjjEnFDtYnLQCBRjXw3Z1ovk3ZwKBgGX4\nkG1o5rmdYH0zKlSGBeQgcWKmwqmtyglPtB58gXzpM9dhf0GPtVF46f6B451Jrd7J\n0oTFVLu8KvX5QAkao1Pcqyq+xQSjsWk0ifJKH2AObNk51pVFjlS9o7pqOeSn4box\nZNJFCwcnPb0fkwi1XoUJ+ayAL82eV9NlxDoOeA5TAoGBAKBAh+QkYWu+Os8ughrJ\n393q6u1Quc1x6ZF/ZZX7WpSA1PvibfNHMHp1ba8cRtMjiXR1NexRfHcfZ6/c4cKf\npWYfMR1km/rKdVzxR6ZKcfGvLjyWdacz9OBKMC5rsZHgcbOeS4HiGt6ogZD46ZXl\nSDWbthk9NAOyllnGt04EAJ7/\n-----END PRIVATE KEY-----\n"
|
4 |
+
FIREBASE_CLIENT_EMAIL=firebase-adminsdk-jne2o@telegram-storage-d867e.iam.gserviceaccount.com
|
5 |
+
FIREBASE_CLIENT_ID=109271910426425629178
|
6 |
+
FIREBASE_CLIENT_X509_CERT_URL=https://www.googleapis.com/robot/v1/metadata/x509/firebase-adminsdk-jne2o%40telegram-storage-d867e.iam.gserviceaccount.com
|
7 |
+
DATABASE_URL=https://telegram-storage-d867e-default-rtdb.firebaseio.com/
|
8 |
+
AIROPS_API_URL=https://app.airops.com/public_api/airops_apps/
|
9 |
+
AMIGO_BASE_URL=https://api.amigochat.io/v1/chat/completions
|
API_provider.py
ADDED
@@ -0,0 +1,110 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import json
|
2 |
+
import uuid
|
3 |
+
from typing import Iterator, Union, List, Dict
|
4 |
+
from dotenv import load_dotenv; load_dotenv()
|
5 |
+
import os
|
6 |
+
import requests
|
7 |
+
|
8 |
+
AVAILABLE_MODELS = [
|
9 |
+
"meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo",
|
10 |
+
"o1-mini",
|
11 |
+
"claude-3-sonnet-20240229",
|
12 |
+
"gemini-1.5-pro",
|
13 |
+
"gemini-1.5-flash",
|
14 |
+
"o1-preview",
|
15 |
+
"gpt-4o"
|
16 |
+
]
|
17 |
+
|
18 |
+
def API_Inference(
|
19 |
+
messages: List[Dict[str, str]],
|
20 |
+
model: str = "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo",
|
21 |
+
stream: bool = False,
|
22 |
+
max_tokens: int = 4000,
|
23 |
+
temperature: float = 0.7,
|
24 |
+
top_p: float = 0.95,
|
25 |
+
) -> Union[str, Iterator[str], None]:
|
26 |
+
if model not in AVAILABLE_MODELS:
|
27 |
+
raise ValueError(
|
28 |
+
f"Model {model} not available. Available models: {', '.join(AVAILABLE_MODELS)}"
|
29 |
+
)
|
30 |
+
|
31 |
+
if model == "claude-3-sonnet-20240229":
|
32 |
+
messages = [{"role": "system", "content": "."}] + [msg for msg in messages if msg["role"] != "system"]
|
33 |
+
|
34 |
+
api_endpoint = os.environ.get("AMIGO_BASE_URL")
|
35 |
+
headers = {
|
36 |
+
"Accept": "*/*",
|
37 |
+
"Accept-Encoding": "gzip, deflate, br, zstd",
|
38 |
+
"Authorization": "Bearer ",
|
39 |
+
"Content-Type": "application/json",
|
40 |
+
"User-Agent": (
|
41 |
+
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
|
42 |
+
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
43 |
+
"Chrome/129.0.0.0 Safari/537.36 Edg/129.0.0.0"
|
44 |
+
),
|
45 |
+
"X-Device-UUID": str(uuid.uuid4()),
|
46 |
+
}
|
47 |
+
|
48 |
+
payload = {
|
49 |
+
"messages": messages,
|
50 |
+
"model": model,
|
51 |
+
"max_tokens": max_tokens,
|
52 |
+
"stream": stream,
|
53 |
+
"presence_penalty": 0,
|
54 |
+
"temperature": temperature,
|
55 |
+
"top_p": top_p,
|
56 |
+
}
|
57 |
+
|
58 |
+
try:
|
59 |
+
response = requests.post(api_endpoint, headers=headers, json=payload, stream=stream)
|
60 |
+
response.raise_for_status()
|
61 |
+
except requests.exceptions.RequestException as e:
|
62 |
+
print("An error occurred while making the request:", e)
|
63 |
+
return None
|
64 |
+
|
65 |
+
def process_response() -> Iterator[str]:
|
66 |
+
for line in response.iter_lines():
|
67 |
+
if line:
|
68 |
+
# Decode the line from bytes to string
|
69 |
+
decoded_line = line.decode('utf-8').strip()
|
70 |
+
if decoded_line.startswith("data: "):
|
71 |
+
data_str = decoded_line[6:]
|
72 |
+
if data_str == "[DONE]":
|
73 |
+
break
|
74 |
+
try:
|
75 |
+
# Load the JSON data
|
76 |
+
data_json = json.loads(data_str)
|
77 |
+
|
78 |
+
# Extract the content from the response
|
79 |
+
choices = data_json.get("choices", [])
|
80 |
+
if choices:
|
81 |
+
delta = choices[0].get("delta", {})
|
82 |
+
content = delta.get("content", "")
|
83 |
+
if content:
|
84 |
+
yield content
|
85 |
+
except json.JSONDecodeError:
|
86 |
+
print(f"Received non-JSON data: {data_str}")
|
87 |
+
|
88 |
+
if stream:
|
89 |
+
return process_response()
|
90 |
+
else:
|
91 |
+
return "".join(process_response())
|
92 |
+
|
93 |
+
if __name__ == "__main__":
|
94 |
+
# Example usage with the new format
|
95 |
+
conversation = [
|
96 |
+
{"role": "system", "content": "You are a helpful and friendly AI assistant."},
|
97 |
+
{"role": "user", "content": "What is the capital of France?"},
|
98 |
+
{"role": "assistant", "content": "Paris"},
|
99 |
+
{"role": "user", "content": "Who are you. Are you GPT-4o or gpt-3.5?"}
|
100 |
+
]
|
101 |
+
|
102 |
+
# For non-streaming response
|
103 |
+
response = API_Inference(conversation, stream=False, model="claude-3-sonnet-20240229")
|
104 |
+
print(response)
|
105 |
+
|
106 |
+
print("--" * 50)
|
107 |
+
|
108 |
+
# # For streaming response
|
109 |
+
for chunk in API_Inference(conversation, stream=True, model="gpt-4o"):
|
110 |
+
print(chunk, end="", flush=True)
|
Dockerfile
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Use an official Python runtime as the base image
|
2 |
+
FROM python:3.9-slim
|
3 |
+
|
4 |
+
# Set the working directory in the container
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Copy the requirements file into the container
|
8 |
+
COPY requirements.txt .
|
9 |
+
|
10 |
+
# Install the required packages
|
11 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
12 |
+
|
13 |
+
# Copy the rest of the application code into the container
|
14 |
+
COPY . .
|
15 |
+
|
16 |
+
# Expose the port that FastAPI will run on
|
17 |
+
EXPOSE 7860
|
18 |
+
|
19 |
+
# Command to run the FastAPI application
|
20 |
+
CMD ["uvicorn", "SERVER:app", "--host", "0.0.0.0", "--port", "7860"]
|
RUN.py
ADDED
@@ -0,0 +1,40 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from openai import OpenAI
|
2 |
+
|
3 |
+
# Set up the client
|
4 |
+
client = OpenAI(
|
5 |
+
base_url="http://localhost:8000/v1", # Update this if you're not running locally
|
6 |
+
api_key="C0TNRcI8EuhmXpRTNiNsGbUHWBG6KFQt" # This can be any string as we're not actually validating it
|
7 |
+
)
|
8 |
+
|
9 |
+
def test_non_streaming():
|
10 |
+
print("Testing non-streaming response:")
|
11 |
+
completion = client.chat.completions.create(
|
12 |
+
model="claude-3.5-sonnet",
|
13 |
+
messages=[
|
14 |
+
{"role": "system", "content": "."},
|
15 |
+
{"role": "user", "content": "how many 'r' are there in strawberry"}
|
16 |
+
]
|
17 |
+
)
|
18 |
+
print(completion)
|
19 |
+
# print(completion.choices[0].message.content)
|
20 |
+
|
21 |
+
def test_streaming():
|
22 |
+
print("\nTesting streaming response:")
|
23 |
+
completion = client.chat.completions.create(
|
24 |
+
model="o1-preview",
|
25 |
+
messages=[
|
26 |
+
{"role": "system", "content": "You are a helpful assistant."},
|
27 |
+
{"role": "user", "content": "how many 'r' are there in strawberry"}
|
28 |
+
],
|
29 |
+
stream=True
|
30 |
+
)
|
31 |
+
for chunk in completion:
|
32 |
+
# print(chunk)
|
33 |
+
if chunk.choices[0].delta.content is not None:
|
34 |
+
print(chunk.choices[0].delta.content, end="", flush=True)
|
35 |
+
print()
|
36 |
+
|
37 |
+
if __name__ == "__main__":
|
38 |
+
test_non_streaming()
|
39 |
+
print("-"*50)
|
40 |
+
test_streaming()
|
SERVER.py
ADDED
@@ -0,0 +1,135 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import uuid
|
2 |
+
from fastapi import FastAPI, HTTPException, Depends
|
3 |
+
from fastapi.security import HTTPBearer, HTTPAuthorizationCredentials
|
4 |
+
from fastapi.responses import StreamingResponse
|
5 |
+
from pydantic import BaseModel
|
6 |
+
from typing import List, Optional
|
7 |
+
import json
|
8 |
+
from API_provider import API_Inference
|
9 |
+
from core_logic import (
|
10 |
+
check_api_key_validity,
|
11 |
+
update_request_count,
|
12 |
+
get_rate_limit_status,
|
13 |
+
get_subscription_status,
|
14 |
+
get_available_models,
|
15 |
+
get_model_info,
|
16 |
+
)
|
17 |
+
|
18 |
+
app = FastAPI()
|
19 |
+
security = HTTPBearer()
|
20 |
+
|
21 |
+
class Message(BaseModel):
|
22 |
+
role: str
|
23 |
+
content: str
|
24 |
+
|
25 |
+
class ChatCompletionRequest(BaseModel):
|
26 |
+
model: str
|
27 |
+
messages: List[Message]
|
28 |
+
stream: Optional[bool] = False
|
29 |
+
max_tokens: Optional[int] = 4000
|
30 |
+
temperature: Optional[float] = 0.5
|
31 |
+
top_p: Optional[float] = 0.95
|
32 |
+
|
33 |
+
def get_api_key(credentials: HTTPAuthorizationCredentials = Depends(security)):
|
34 |
+
return credentials.credentials
|
35 |
+
|
36 |
+
@app.post("/v1/chat/completions")
|
37 |
+
async def chat_completions(request: ChatCompletionRequest, api_key: str = Depends(get_api_key)):
|
38 |
+
try:
|
39 |
+
# Check API key validity and rate limit
|
40 |
+
is_valid, error_message = check_api_key_validity(api_key)
|
41 |
+
if not is_valid:
|
42 |
+
raise HTTPException(status_code=401, detail=error_message)
|
43 |
+
|
44 |
+
messages = [{"role": msg.role, "content": msg.content} for msg in request.messages]
|
45 |
+
|
46 |
+
# Get model info
|
47 |
+
model_info = get_model_info(request.model)
|
48 |
+
if not model_info:
|
49 |
+
raise HTTPException(status_code=400, detail="Invalid model specified")
|
50 |
+
|
51 |
+
if "meta-llama-405b-turbo" in request.model:
|
52 |
+
request.model = "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo"
|
53 |
+
|
54 |
+
if "claude-3.5-sonnet" in request.model:
|
55 |
+
request.model = "claude-3-sonnet-20240229"
|
56 |
+
|
57 |
+
if request.stream:
|
58 |
+
def generate():
|
59 |
+
for chunk in API_Inference(messages, model=request.model, stream=True,
|
60 |
+
max_tokens=request.max_tokens,
|
61 |
+
temperature=request.temperature,
|
62 |
+
top_p=request.top_p):
|
63 |
+
yield f"data: {json.dumps({'choices': [{'delta': {'content': chunk}}]})}\n\n"
|
64 |
+
yield "data: [DONE]\n\nCredits used: 1\n\n"
|
65 |
+
|
66 |
+
|
67 |
+
# Update request count
|
68 |
+
if request.model == "gpt-4o" or request.model == "claude-3-sonnet-20240229" or request.model == "gemini-1.5-pro" or request.model == "gemini-1-5-flash" or request.model == "meta-llama/Meta-Llama-3.1-405B-Instruct-Turbo":
|
69 |
+
update_request_count(api_key, 1)
|
70 |
+
|
71 |
+
elif request.model == "o1-mini":
|
72 |
+
update_request_count(api_key, 2)
|
73 |
+
|
74 |
+
elif request.model == "o1-preview":
|
75 |
+
update_request_count(api_key, 3)
|
76 |
+
|
77 |
+
return StreamingResponse(generate(), media_type="text/event-stream")
|
78 |
+
else:
|
79 |
+
response = API_Inference(messages, model=request.model, stream=False,
|
80 |
+
max_tokens=request.max_tokens,
|
81 |
+
temperature=request.temperature,
|
82 |
+
top_p=request.top_p)
|
83 |
+
|
84 |
+
# Update request count
|
85 |
+
update_request_count(api_key, 1) # Assume 1 credit per request, adjust as needed
|
86 |
+
|
87 |
+
return {
|
88 |
+
"id": f"chatcmpl-{uuid.uuid4()}",
|
89 |
+
"object": "chat.completion",
|
90 |
+
"created": int(uuid.uuid1().time // 1e7),
|
91 |
+
"model": request.model,
|
92 |
+
"choices": [
|
93 |
+
{
|
94 |
+
"index": 0,
|
95 |
+
"message": {
|
96 |
+
"role": "assistant",
|
97 |
+
"content": response
|
98 |
+
},
|
99 |
+
"finish_reason": "stop"
|
100 |
+
}
|
101 |
+
],
|
102 |
+
"usage": {
|
103 |
+
"prompt_tokens": len(' '.join(msg['content'] for msg in messages).split()),
|
104 |
+
"completion_tokens": len(response.split()),
|
105 |
+
"total_tokens": len(' '.join(msg['content'] for msg in messages).split()) + len(response.split())
|
106 |
+
},
|
107 |
+
"credits_used": 1
|
108 |
+
}
|
109 |
+
except Exception as e:
|
110 |
+
raise HTTPException(status_code=500, detail=str(e))
|
111 |
+
|
112 |
+
@app.get("/rate_limit/status")
|
113 |
+
async def get_rate_limit_status_endpoint(api_key: str = Depends(get_api_key)):
|
114 |
+
is_valid, error_message = check_api_key_validity(api_key, check_rate_limit=False)
|
115 |
+
if not is_valid:
|
116 |
+
raise HTTPException(status_code=401, detail=error_message)
|
117 |
+
return get_rate_limit_status(api_key)
|
118 |
+
|
119 |
+
@app.get("/subscription/status")
|
120 |
+
async def get_subscription_status_endpoint(api_key: str = Depends(get_api_key)):
|
121 |
+
is_valid, error_message = check_api_key_validity(api_key, check_rate_limit=False)
|
122 |
+
if not is_valid:
|
123 |
+
raise HTTPException(status_code=401, detail=error_message)
|
124 |
+
return get_subscription_status(api_key)
|
125 |
+
|
126 |
+
@app.get("/models")
|
127 |
+
async def get_available_models_endpoint(api_key: str = Depends(get_api_key)):
|
128 |
+
is_valid, error_message = check_api_key_validity(api_key, check_rate_limit=False)
|
129 |
+
if not is_valid:
|
130 |
+
raise HTTPException(status_code=401, detail=error_message)
|
131 |
+
return {"data": [{"id": model} for model in get_available_models().values()]}
|
132 |
+
|
133 |
+
if __name__ == "__main__":
|
134 |
+
import uvicorn
|
135 |
+
uvicorn.run(app, host="0.0.0.0", port=8000)
|
core_logic.py
ADDED
@@ -0,0 +1,136 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# api_key_manager.py
|
2 |
+
|
3 |
+
from dotenv import load_dotenv; load_dotenv()
|
4 |
+
import os
|
5 |
+
import firebase_admin
|
6 |
+
from firebase_admin import credentials, firestore
|
7 |
+
import datetime
|
8 |
+
from pytz import UTC
|
9 |
+
|
10 |
+
# Initialize Firebase Admin SDK
|
11 |
+
cred = credentials.Certificate({
|
12 |
+
"type": "service_account",
|
13 |
+
"project_id": os.environ.get("FIREBASE_PROJECT_ID"),
|
14 |
+
"private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
|
15 |
+
"private_key": os.environ.get("FIREBASE_PRIVATE_KEY").replace("\\n", "\n"),
|
16 |
+
"client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
|
17 |
+
"client_id": os.environ.get("FIREBASE_CLIENT_ID"),
|
18 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
19 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
20 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
21 |
+
"client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL")
|
22 |
+
})
|
23 |
+
|
24 |
+
try:
|
25 |
+
firebase_admin.get_app()
|
26 |
+
except ValueError:
|
27 |
+
firebase_admin.initialize_app(cred)
|
28 |
+
|
29 |
+
db = firestore.client()
|
30 |
+
|
31 |
+
def get_user_info(api_key):
|
32 |
+
doc = db.collection('Users').document(api_key).get(field_paths=[
|
33 |
+
'subscription_plan', 'requests_remaining', 'paid_models', 'ai_engine_secret_key'
|
34 |
+
])
|
35 |
+
if doc.exists:
|
36 |
+
return doc.to_dict()
|
37 |
+
else:
|
38 |
+
return None
|
39 |
+
|
40 |
+
def check_api_key_validity(api_key, check_rate_limit=True):
|
41 |
+
user_data = get_user_info(api_key)
|
42 |
+
if not user_data:
|
43 |
+
return False, "Invalid API key"
|
44 |
+
|
45 |
+
if check_rate_limit:
|
46 |
+
if user_data.get('requests_remaining', 0) <= 0:
|
47 |
+
return False, "Rate limit exceeded. Kindly Upgrade to Premium for using the Devs Do Code API"
|
48 |
+
return True, ""
|
49 |
+
|
50 |
+
def update_request_count(api_key, credits_used):
|
51 |
+
user_ref = db.collection('Users').document(api_key)
|
52 |
+
user_doc = user_ref.get(field_paths=['requests_remaining'])
|
53 |
+
if user_doc.exists:
|
54 |
+
requests_remaining = user_doc.to_dict().get('requests_remaining', 0)
|
55 |
+
new_requests_remaining = requests_remaining - credits_used # Subtract credits used
|
56 |
+
user_ref.update({'requests_remaining': new_requests_remaining})
|
57 |
+
return True
|
58 |
+
else:
|
59 |
+
return False
|
60 |
+
|
61 |
+
def get_rate_limit_status(api_key):
|
62 |
+
user_doc = db.collection('Users').document(api_key).get(field_paths=['requests_remaining'])
|
63 |
+
if not user_doc.exists:
|
64 |
+
return {"error": "Invalid API key"}
|
65 |
+
|
66 |
+
requests_remaining = user_doc.to_dict().get('requests_remaining', 0)
|
67 |
+
return {"requests_remaining": requests_remaining}
|
68 |
+
|
69 |
+
def get_subscription_status(api_key):
|
70 |
+
user_doc = db.collection('Users').document(api_key).get(field_paths=['subscription_plan'])
|
71 |
+
if not user_doc.exists:
|
72 |
+
return {"error": "Invalid API key"}
|
73 |
+
|
74 |
+
subscription_plan = user_doc.to_dict().get('subscription_plan', 'Free')
|
75 |
+
return {"subscription_plan": subscription_plan}
|
76 |
+
|
77 |
+
def get_available_models():
|
78 |
+
models = {
|
79 |
+
"gpt-4o": {
|
80 |
+
"name": "gpt-4o-2024-08-06",
|
81 |
+
"description": "Our high-intelligence flagship model for complex, multi-step tasks. GPT-4o is multimodal, processing text, audio, and images, and is faster and 50% cheaper than its predecessor. It has a maximum output of 16,384 tokens, if o1-mini is used",
|
82 |
+
"max_tokens": 4096,
|
83 |
+
"context_window": 128000,
|
84 |
+
"training_data": "Up to October 2023"
|
85 |
+
},
|
86 |
+
"o1-preview": {
|
87 |
+
"name": "o1-preview-2024-09-12",
|
88 |
+
"description": "OpenAI o1 is a new large language model optimized for complex reasoning tasks, utilizing reinforcement learning to enhance its problem-solving capabilities. It excels in STEM subjects and demonstrates impressive performance on challenging benchmarks, including achieving 83% accuracy on the AIME mathematics competition, significantly outperforming previous models like GPT-4o.",
|
89 |
+
"max_tokens": 32768,
|
90 |
+
"context_window": 128000,
|
91 |
+
"training_data": "Up to September 2024"
|
92 |
+
},
|
93 |
+
"claude-3.5-sonnet": {
|
94 |
+
"name": "claude-3.5-sonnet-latest",
|
95 |
+
"description": "Claude 3.5 Sonnet is a highly capable model developed by Anthropic, optimized for complex reasoning tasks and demonstrating significant advancements in performance compared to its predecessors. It excels in areas such as coding, multi-step workflows, and interpreting visual data.",
|
96 |
+
"context_window": 8192,
|
97 |
+
"max_tokens": 200000,
|
98 |
+
"training_data": "Up to April 2024"
|
99 |
+
},
|
100 |
+
"gemini-1.5-pro": {
|
101 |
+
"name": "Gemini-1.5-Pro",
|
102 |
+
"description": "Gemini is an AI chatbot developed by Google. Formerly known as Bard, it was released to the public in 2023. Gemini-1.5-Pro is an improved version of the model, offering more accurate and informative responses.",
|
103 |
+
"max_tokens": 4096,
|
104 |
+
"context_window": 131072,
|
105 |
+
"training_data": "Up to 2023"
|
106 |
+
},
|
107 |
+
"gemini-1-5-flash": {
|
108 |
+
"name": "Gemini 1.5 Flash",
|
109 |
+
"description": "A lighter-weight model than 1.5 Pro, designed to be fast and efficient to serve at scale. It's optimized for high-volume, high-frequency tasks and features a breakthrough long context window, making it highly capable of multimodal reasoning across vast amounts of information.",
|
110 |
+
"max_tokens": 4096,
|
111 |
+
"context_window": 131072,
|
112 |
+
"training_data": "Up to 2024"
|
113 |
+
},
|
114 |
+
"o1-mini": {
|
115 |
+
"name": "o1-mini",
|
116 |
+
"description": "The o1-mini model is a cost-effective and efficient AI model designed for quick reasoning tasks, particularly in STEM fields such as coding and mathematics. It is optimized for speed and lower resource consumption, making it an ideal choice for applications requiring fast responses without the need for extensive world knowledge.",
|
117 |
+
"max_tokens": 65536,
|
118 |
+
"context_window": 128000,
|
119 |
+
"training_data": "Up to October 2023"
|
120 |
+
},
|
121 |
+
"meta-llama-405b-turbo": {
|
122 |
+
"name": "Meta-Llama-3.1-405B-Instruct-Turbo",
|
123 |
+
"description": "Meta-Llama-3.1-405B-Instruct-Turbo is a state-of-the-art AI model designed for instruction-based tasks. It excels in generating coherent and contextually relevant responses, making it suitable for applications in conversational AI, content creation, and more. This model leverages advanced techniques in natural language processing to provide high-quality outputs.",
|
124 |
+
"max_tokens": 4096,
|
125 |
+
"context_window": 128000,
|
126 |
+
"training_data": "Up to October 2023"
|
127 |
+
}
|
128 |
+
}
|
129 |
+
return models
|
130 |
+
|
131 |
+
def get_model_info(model_name):
|
132 |
+
models = get_available_models()
|
133 |
+
return models.get(model_name)
|
134 |
+
|
135 |
+
if __name__ == "__main__":
|
136 |
+
print(get_model_info("gpt4o"))
|
database_initializer.py
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import firebase_admin
|
3 |
+
from firebase_admin import credentials, firestore
|
4 |
+
from dotenv import load_dotenv; load_dotenv()
|
5 |
+
|
6 |
+
# Initialize Firebase Admin SDK
|
7 |
+
|
8 |
+
# Initialize Firebase app with credentials and options
|
9 |
+
cred = credentials.Certificate({
|
10 |
+
"type": "service_account",
|
11 |
+
"project_id": os.environ.get("FIREBASE_PROJECT_ID"),
|
12 |
+
"private_key_id": os.environ.get("FIREBASE_PRIVATE_KEY_ID"),
|
13 |
+
"private_key": os.environ.get("FIREBASE_PRIVATE_KEY").replace("\\n", "\n"),
|
14 |
+
"client_email": os.environ.get("FIREBASE_CLIENT_EMAIL"),
|
15 |
+
"client_id": os.environ.get("FIREBASE_CLIENT_ID"),
|
16 |
+
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
|
17 |
+
"token_uri": "https://oauth2.googleapis.com/token",
|
18 |
+
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
|
19 |
+
"client_x509_cert_url": os.environ.get("FIREBASE_CLIENT_X509_CERT_URL")
|
20 |
+
})
|
21 |
+
try:
|
22 |
+
firebase_admin.get_app()
|
23 |
+
except ValueError:
|
24 |
+
firebase_admin.initialize_app(cred, {
|
25 |
+
'databaseURL': os.environ.get("DATABASE_URL")
|
26 |
+
})
|
problems.md
ADDED
@@ -0,0 +1,21 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
```json
|
2 |
+
"gemini-1.5-pro": {
|
3 |
+
"name": "gemini-1.5-pro",
|
4 |
+
"description": "",
|
5 |
+
},
|
6 |
+
```
|
7 |
+
|
8 |
+
|
9 |
+
I am providing you the name of the AI model and Google. I am providing you how to fill the extra details -->
|
10 |
+
|
11 |
+
```json
|
12 |
+
"gpt-4o": {
|
13 |
+
"name": "gpt-4o-2024-08-06",
|
14 |
+
"description": "Our high-intelligence flagship model for complex, multi-step tasks. GPT-4o is multimodal, processing text, audio, and images, and is faster and 50% cheaper than its predecessor. It has a maximum output of 16,384 tokens, if o1-mini is used",
|
15 |
+
"max_tokens": 4096,
|
16 |
+
"context_window": 128000,
|
17 |
+
"training_data": "Up to October 2023"
|
18 |
+
},
|
19 |
+
```
|
20 |
+
|
21 |
+
You have to provide the complete json data along with name description, max token, context, window and training data of that specific ai model. After searching on Internet
|
requirements.txt
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
fastapi==0.110.2
|
2 |
+
Flask==3.0.3
|
3 |
+
Requests==2.31.0
|
4 |
+
uvicorn==0.29.0
|
5 |
+
python-dotenv==1.0.1
|
6 |
+
firebase-admin
|
7 |
+
colorama
|
8 |
+
pytz
|
9 |
+
pydantic==2.9.2
|
test_check.py
ADDED
@@ -0,0 +1,68 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import requests
|
2 |
+
import json
|
3 |
+
|
4 |
+
BASE_URL = "http://localhost:8000"
|
5 |
+
API_KEY = "C0TNRcI8EuhmXpRTNiNsGbUHWBG6KFQt" # Replace with a valid API key
|
6 |
+
|
7 |
+
headers = {
|
8 |
+
"Content-Type": "application/json",
|
9 |
+
"Authorization": f"Bearer {API_KEY}" # Use Bearer token authentication
|
10 |
+
}
|
11 |
+
|
12 |
+
def test_chat_completions_non_stream():
|
13 |
+
url = f"{BASE_URL}/v1/chat/completions"
|
14 |
+
payload = {
|
15 |
+
"model": "meta-llama-405b-turbo",
|
16 |
+
"messages": [
|
17 |
+
{"role": "user", "content": "Hello, how are you?"},
|
18 |
+
],
|
19 |
+
}
|
20 |
+
print("Chat Completions Non Streaming Response:")
|
21 |
+
response = requests.post(url, headers=headers, json=payload)
|
22 |
+
print(json.dumps(response.json(), indent=2))
|
23 |
+
print("\n")
|
24 |
+
|
25 |
+
def test_chat_completions_stream():
|
26 |
+
url = f"{BASE_URL}/v1/chat/completions"
|
27 |
+
payload = {
|
28 |
+
"model": "meta-llama-405b-turbo",
|
29 |
+
"messages": [
|
30 |
+
{"role": "user", "content": "Hello, how are you?"},
|
31 |
+
],
|
32 |
+
"stream": True,
|
33 |
+
}
|
34 |
+
print("Chat Completions Streaming Response:")
|
35 |
+
response = requests.post(url, headers=headers, json=payload, stream=True)
|
36 |
+
for chunk in response.iter_lines():
|
37 |
+
if chunk:
|
38 |
+
print(chunk.decode("utf-8").replace("data: ", "").strip(), end="\n", flush=True)
|
39 |
+
|
40 |
+
print("\n")
|
41 |
+
|
42 |
+
def test_rate_limit_status():
|
43 |
+
url = f"{BASE_URL}/rate_limit/status" # Updated endpoint
|
44 |
+
response = requests.get(url, headers=headers)
|
45 |
+
print("Rate Limit Status Response:")
|
46 |
+
print(json.dumps(response.json(), indent=2))
|
47 |
+
print("\n")
|
48 |
+
|
49 |
+
def test_subscription_status():
|
50 |
+
url = f"{BASE_URL}/subscription/status" # Updated endpoint
|
51 |
+
response = requests.get(url, headers=headers)
|
52 |
+
print("Subscription Status Response:")
|
53 |
+
print(json.dumps(response.json(), indent=2))
|
54 |
+
print("\n")
|
55 |
+
|
56 |
+
def test_available_models():
|
57 |
+
url = f"{BASE_URL}/models" # Updated endpoint
|
58 |
+
response = requests.get(url, headers=headers)
|
59 |
+
print("Available Models Response:")
|
60 |
+
print(json.dumps(response.json(), indent=2))
|
61 |
+
print("\n")
|
62 |
+
|
63 |
+
if __name__ == "__main__":
|
64 |
+
test_chat_completions_non_stream()
|
65 |
+
test_chat_completions_stream()
|
66 |
+
test_rate_limit_status()
|
67 |
+
test_subscription_status()
|
68 |
+
test_available_models()
|