Abhaykoul commited on
Commit
2b872cb
·
verified ·
1 Parent(s): 374b792

Create app.py

Browse files
Files changed (1) hide show
  1. app.py +113 -0
app.py ADDED
@@ -0,0 +1,113 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import requests
2
+ import json
3
+ from typing import Generator
4
+ from fastapi import FastAPI, HTTPException
5
+ from fastapi.responses import StreamingResponse
6
+ import uvicorn
7
+ from dotenv import load_dotenv
8
+ import os
9
+
10
+ load_dotenv()
11
+
12
+ app = FastAPI()
13
+
14
+ class v1:
15
+ """
16
+ A class to interact with the Prefind AI API.
17
+ """
18
+
19
+ AVAILABLE_MODELS = ["llama", "claude"]
20
+
21
+ def __init__(
22
+ self,
23
+ model: str = "claude",
24
+ timeout: int = 30,
25
+ proxies: dict = {},
26
+ ):
27
+ """
28
+ Initializes the Prefind AI API with given parameters.
29
+
30
+ Args:
31
+ model (str, optional): The AI model to use for text generation. Defaults to "claude".
32
+ Options: "llama", "claude".
33
+ timeout (int, optional): Http request timeout. Defaults to 30.
34
+ proxies (dict, optional): Http request proxies. Defaults to {}.
35
+ """
36
+ if model not in self.AVAILABLE_MODELS:
37
+ raise ValueError(f"Model '{model}' is not supported. Choose from {self.AVAILABLE_MODELS}.")
38
+
39
+ self.session = requests.Session()
40
+ self.api_endpoint = os.getenv("API_ENDPOINT")
41
+ self.timeout = timeout
42
+ self.model = model
43
+ self.device_token = self.get_device_token()
44
+
45
+ self.session.headers.update(
46
+ {
47
+ "Content-Type": "application/json",
48
+ "Accept": "text/event-stream",
49
+ }
50
+ )
51
+ self.session.proxies = proxies
52
+
53
+ def get_device_token(self) -> str:
54
+ device_token_url = os.getenv("DEVICE_TOKEN_URL")
55
+ headers = {"Content-Type": "application/json; charset=utf-8"}
56
+ data = {}
57
+ response = requests.post(
58
+ device_token_url, headers=headers, data=json.dumps(data)
59
+ )
60
+
61
+ if response.status_code == 200:
62
+ device_token_data = response.json()
63
+ return device_token_data["sessionToken"]
64
+ else:
65
+ raise Exception(
66
+ f"Failed to get device token - ({response.status_code}, {response.reason}) - {response.text}"
67
+ )
68
+
69
+ def ask(self, prompt: str) -> Generator[str, None, None]:
70
+ search_data = {"query": prompt, "deviceToken": self.device_token}
71
+
72
+ response = self.session.post(
73
+ self.api_endpoint, json=search_data, stream=True, timeout=self.timeout
74
+ )
75
+ if not response.ok:
76
+ raise Exception(
77
+ f"Failed to generate response - ({response.status_code}, {response.reason}) - {response.text}"
78
+ )
79
+
80
+ for line in response.iter_lines(decode_unicode=True):
81
+ if line:
82
+ if line.startswith("data: "):
83
+ data_str = line[6:]
84
+ data = json.loads(data_str)
85
+ if data['type'] == 'chunk':
86
+ model = data['model']
87
+ if (self.model == "llama" and model == 'OPENROUTER_LLAMA_3') or \
88
+ (self.model == "claude" and model == 'OPENROUTER_CLAUDE'):
89
+ content = data['chunk']['content']
90
+ if content:
91
+ yield content
92
+
93
+ def chat(self, prompt: str) -> Generator[str, None, None]:
94
+ """Stream responses as string chunks"""
95
+ return self.ask(prompt)
96
+
97
+
98
+ @app.get("/Search/pro")
99
+ async def chat(prompt: str, model: str = "claude"):
100
+ if model not in v1.AVAILABLE_MODELS:
101
+ raise HTTPException(status_code=400, detail=f"Model '{model}' is not supported. Choose from {v1.AVAILABLE_MODELS}.")
102
+
103
+ ai = v1(model=model)
104
+
105
+ def response_generator():
106
+ for chunk in ai.chat(prompt):
107
+ yield f"data: {chunk}\n\n"
108
+
109
+ return StreamingResponse(response_generator(), media_type="text/event-stream")
110
+
111
+
112
+ if __name__ == "__main__":
113
+ uvicorn.run(app, host="0.0.0.0", port=7860)