1
+ '''
2
+ wrtn.py
3
+ reverse proxy api for wrtn
4
+ '''
5
+ import json
6
+ from util import Http , APIRequester
7
+ from fake_useragent import UserAgent
8
+ import inspect
9
+
10
+ class ChunkDecoder :
11
+ def __init__ (self ):
12
+ self .buffer = ""
13
+
14
+ def decode (self , chunk_tuple ):
15
+ for chunk in chunk_tuple :
16
+ if (isinstance (chunk , bytes )):
17
+ return self .decode_chunks (chunk )
18
+
19
+ def decode_chunks (self , chunk_byte ):
20
+ chunk_str = self .buffer + chunk_byte .decode (encoding = "utf-8" , errors = "ignore" )
21
+ chunks = chunk_str .split ('\n \n ' )
22
+ last_chunk = chunks [- 1 ]
23
+ self .buffer = "" if last_chunk == "" else last_chunk
24
+ json_objects = [json .loads ((line .split (": " , 1 )[1 ]))
25
+ for line in chunks [:- 1 ] if line .strip ().startswith ('data: {' )]
26
+ res_text = "" .join (obj ['chunk' ] for obj in json_objects if 'chunk' in obj if obj ['chunk' ] is not None )
27
+ return res_text
28
+
29
+ #TODO: Divide WrtnAPI to Chat, Studio, Tool/ChatBot
30
+ class WrtnAPI :
31
+ '''
32
+ WrtnAPI: needs json path
33
+ '''
34
+ def __init__ (self , debug = False ) -> None :
35
+ self .debug = debug
36
+ self .header = {
37
+ "Init" : {
38
+ "Refresh" : "" ,
39
+ "Content-Type" : "application/json"
40
+ },
41
+ "Auth" : {
42
+ "User-Agent" : UserAgent ().safari
43
+ },
44
+ }
45
+ self .wrtn_requester = APIRequester ("https://api.wow.wrtn.ai" , debug = debug )
46
+ self .wrtn_studio_requester = APIRequester ("https://studio-api.wow.wrtn.ai" , debug = debug )
47
+
48
+ async def login (self , account ):
49
+ response = await self .wrtn_requester .post (
50
+ info = Http (
51
+ url = "/auth/local" ,
52
+ header = self .header ["Init" ],
53
+ payload = {
54
+ "email" : account ['id' ],
55
+ "password" : account ['pw' ]
56
+ },
57
+ ),
58
+ )
59
+ self .header ["Init" ] |= {"Refresh" : response ['data' ]['refreshToken' ]}
60
+ return response ['data' ]['refreshToken' ]
61
+
62
+ async def access_token (self ):
63
+ '''refresh access_token with refresh_key'''
64
+ response = await self .wrtn_requester .post (
65
+ info = Http (
66
+ url = "/auth/refresh" ,
67
+ header = self .header ["Init" ],
68
+ ),
69
+ )
70
+ return {"Authorization" : "Bearer " + response ['data' ]['accessToken' ]}
71
+
72
+ async def chat_by_json (self , _id : str , msg : str , oldmsg : list [dict ], model :str = 'gpt-3.5-turbo' ):
73
+ '''chat method with json. currently: gpt-3.5 and gpt-4, context length is unknown'''
74
+
75
+ self .header ["Auth" ] |= await self .access_token ()
76
+ decoder = ChunkDecoder ()
77
+ async for response in self .wrtn_studio_requester .stream (
78
+ info = Http (
79
+ url = f"/store/chat-bot/{ _id } /generate" ,
80
+ header = self .header ["Auth" ],
81
+ payload = {
82
+ "content" : msg ,
83
+ "model" : model ,
84
+ "oldMessages" : oldmsg ,
85
+ },
86
+ ), callback = decoder .decode
87
+ ):
88
+ yield response
89
+ await self .delete_chatbot (_id )
90
+
91
+ async def get_chatbot (self ) -> list :
92
+ '''loads all chatbots from this user'''
93
+
94
+
95
+ self .header ["Auth" ] |= await self .access_token ()
96
+ response = await self .wrtn_studio_requester .get (
97
+ info = Http (
98
+ url = "/studio/chat-bot" ,
99
+ header = self .header ["Auth" ]
100
+ ),
101
+ )
102
+ return response ['data' ]
103
+
104
+ async def delete_chatbot (self , _id : str ):
105
+ '''delete a chatbot with specific id. You must delete your chatbot after use.'''
106
+
107
+
108
+ self .header ["Auth" ] |= await self .access_token ()
109
+ response = await self .wrtn_studio_requester .delete (
110
+ info = Http (
111
+ url = f"/studio/chat-bot/{ _id } " ,
112
+ header = self .header ["Auth" ],
113
+ ),
114
+ )
115
+ return response
116
+
117
+ async def get_tool (self ) -> list :
118
+ '''loads all tools from this user'''
119
+
120
+
121
+ self .header ["Auth" ] |= await self .access_token ()
122
+ response = await self .wrtn_studio_requester .get (
123
+ info = Http (
124
+ url = "/studio/tool" ,
125
+ header = self .header ["Auth" ],
126
+ ),
127
+ )
128
+ return response ['data' ]
129
+
130
+ async def delete_tool (self , _id : str ):
131
+ '''delete a tool with specific id. You must delete your chatbot after use.'''
132
+
133
+
134
+ self .header ["Auth" ] |= await self .access_token ()
135
+ response = await self .wrtn_studio_requester .delete (
136
+ info = Http (
137
+ url = f"/studio/tool/{ _id } " ,
138
+ header = self .header ["Auth" ],
139
+ ),
140
+ )
141
+ return response
142
+
143
+ async def make_chatbot (self ):
144
+ '''
145
+ make a chatbot with specific option.
146
+ Must register a chatbot with passing an toxicity test, to use a json prompt with system role.
147
+ '''
148
+ # toolList = await self.get_tool()
149
+ # for tool in toolList['toolList']:
150
+ # await self.delete_tool(tool['id'])
151
+ # chatBotList = await self.get_chatbot()
152
+ # for chatBot in chatBotList['chatBotList']:
153
+ # await self.delete_chatbot(chatBot['id'])
154
+
155
+
156
+ self .header ["Auth" ] |= await self .access_token ()
157
+ payload = {
158
+ "difficulty" :"hard" ,
159
+ "icon" :"faceSmile" ,
160
+ "title" :" " ,
161
+ "description" :" " ,
162
+ "category" :[" " ],
163
+ "firstMessage" :" " ,
164
+ "selectTypeForExampleQuestion" :" " ,
165
+ "exampleQuestion" :["" ],
166
+ "promptForEasy" :{
167
+ "role" :"" ,"personality" :"" ,"requirement" :""
168
+ },
169
+ "promptForDifficult" :"" ,
170
+ "userName" :" " ,
171
+ "isDeleted" :False ,
172
+ # "additionalInformation": "",
173
+ "isTemporarySave" :False ,
174
+ "openType" :"비공개" ,
175
+ "priceType" :"무료" ,
176
+ }
177
+ response = await self .wrtn_studio_requester .post (
178
+ info = Http (
179
+ url = "/studio/chat-bot" ,
180
+ header = self .header ["Auth" ],
181
+ ),
182
+ )
183
+
184
+ _id = response ['data' ]['chatBotList' ][0 ]['id' ]
185
+ payload ["userId" ] = response ['data' ]['chatBotList' ][0 ]['userId' ]
186
+ payload ["chatBotId" ] = _id
187
+ chatbot = await self .wrtn_studio_requester .post (
188
+ info = Http (
189
+ url = f"/studio/chat-bot/{ _id } " ,
190
+ payload = payload ,
191
+ header = self .header ["Auth" ],
192
+ ),
193
+ )
194
+ return chatbot ['data' ]['chatBotList' ][0 ]['id' ]
0 commit comments