Abhaykoul commited on
Commit
b68d341
1 Parent(s): fc223bf

Create v1.py

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