3030# created by an external call.
3131# 3) This app runs on a separate thread meaning it won't block the test app.
3232
33+ STREAMED_RESPONSES = {
34+ "Stream parsing error." : [
35+ {
36+ "Content-Type" : "text/event-stream" ,
37+ "openai-model" : "gpt-3.5-turbo-0613" ,
38+ "openai-organization" : "new-relic-nkmd8b" ,
39+ "openai-processing-ms" : "516" ,
40+ "openai-version" : "2020-10-01" ,
41+ "x-ratelimit-limit-requests" : "200" ,
42+ "x-ratelimit-limit-tokens" : "40000" ,
43+ "x-ratelimit-remaining-requests" : "199" ,
44+ "x-ratelimit-remaining-tokens" : "39940" ,
45+ "x-ratelimit-reset-requests" : "7m12s" ,
46+ "x-ratelimit-reset-tokens" : "90ms" ,
47+ "x-request-id" : "49dbbffbd3c3f4612aa48def69059ccd" ,
48+ },
49+ 200 ,
50+ [
51+ {
52+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
53+ "object" : "chat.completion.chunk" ,
54+ "created" : 1706565311 ,
55+ "model" : "gpt-3.5-turbo-0613" ,
56+ "system_fingerprint" : None ,
57+ "choices" : [
58+ {"index" : 0 , "delta" : {"role" : "assistant" , "content" : "" }, "logprobs" : None , "finish_reason" : None }
59+ ],
60+ },
61+ {
62+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
63+ "object" : "chat.completion.chunk" ,
64+ "created" : 1706565311 ,
65+ "model" : "gpt-3.5-turbo-0613" ,
66+ "system_fingerprint" : None ,
67+ "choices" : [{"index" : 0 , "delta" : {"content" : "212" }, "logprobs" : None , "finish_reason" : None }],
68+ },
69+ ],
70+ ],
71+ "Invalid API key." : [
72+ {"Content-Type" : "application/json; charset=utf-8" , "x-request-id" : "4f8f61a7d0401e42a6760ea2ca2049f6" },
73+ 401 ,
74+ {
75+ "error" : {
76+ "message" : "Incorrect API key provided: DEADBEEF. You can find your API key at https://platform.openai.com/account/api-keys." ,
77+ "type" : "invalid_request_error" ,
78+ "param" : None ,
79+ "code" : "invalid_api_key" ,
80+ }
81+ },
82+ ],
83+ "Model does not exist." : [
84+ {
85+ "Content-Type" : "application/json; charset=utf-8" ,
86+ "x-request-id" : "cfdf51fb795362ae578c12a21796262c" ,
87+ },
88+ 404 ,
89+ {
90+ "error" : {
91+ "message" : "The model `does-not-exist` does not exist" ,
92+ "type" : "invalid_request_error" ,
93+ "param" : None ,
94+ "code" : "model_not_found" ,
95+ }
96+ },
97+ ],
98+ "You are a scientist." : [
99+ {
100+ "Content-Type" : "text/event-stream" ,
101+ "openai-model" : "gpt-3.5-turbo-0613" ,
102+ "openai-organization" : "new-relic-nkmd8b" ,
103+ "openai-processing-ms" : "516" ,
104+ "openai-version" : "2020-10-01" ,
105+ "x-ratelimit-limit-requests" : "200" ,
106+ "x-ratelimit-limit-tokens" : "40000" ,
107+ "x-ratelimit-remaining-requests" : "199" ,
108+ "x-ratelimit-remaining-tokens" : "39940" ,
109+ "x-ratelimit-reset-requests" : "7m12s" ,
110+ "x-ratelimit-reset-tokens" : "90ms" ,
111+ "x-request-id" : "49dbbffbd3c3f4612aa48def69059ccd" ,
112+ },
113+ 200 ,
114+ [
115+ {
116+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
117+ "object" : "chat.completion.chunk" ,
118+ "created" : 1706565311 ,
119+ "model" : "gpt-3.5-turbo-0613" ,
120+ "system_fingerprint" : None ,
121+ "choices" : [
122+ {"index" : 0 , "delta" : {"role" : "assistant" , "content" : "" }, "logprobs" : None , "finish_reason" : None }
123+ ],
124+ },
125+ {
126+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
127+ "object" : "chat.completion.chunk" ,
128+ "created" : 1706565311 ,
129+ "model" : "gpt-3.5-turbo-0613" ,
130+ "system_fingerprint" : None ,
131+ "choices" : [{"index" : 0 , "delta" : {"content" : "212" }, "logprobs" : None , "finish_reason" : None }],
132+ },
133+ {
134+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
135+ "object" : "chat.completion.chunk" ,
136+ "created" : 1706565311 ,
137+ "model" : "gpt-3.5-turbo-0613" ,
138+ "system_fingerprint" : None ,
139+ "choices" : [{"index" : 0 , "delta" : {"content" : " degrees" }, "logprobs" : None , "finish_reason" : None }],
140+ },
141+ {
142+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
143+ "object" : "chat.completion.chunk" ,
144+ "created" : 1706565311 ,
145+ "model" : "gpt-3.5-turbo-0613" ,
146+ "system_fingerprint" : None ,
147+ "choices" : [{"index" : 0 , "delta" : {"content" : " Fahrenheit" }, "logprobs" : None , "finish_reason" : None }],
148+ },
149+ {
150+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
151+ "object" : "chat.completion.chunk" ,
152+ "created" : 1706565311 ,
153+ "model" : "gpt-3.5-turbo-0613" ,
154+ "system_fingerprint" : None ,
155+ "choices" : [{"index" : 0 , "delta" : {"content" : " is" }, "logprobs" : None , "finish_reason" : None }],
156+ },
157+ {
158+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
159+ "object" : "chat.completion.chunk" ,
160+ "created" : 1706565311 ,
161+ "model" : "gpt-3.5-turbo-0613" ,
162+ "system_fingerprint" : None ,
163+ "choices" : [{"index" : 0 , "delta" : {"content" : " equal" }, "logprobs" : None , "finish_reason" : None }],
164+ },
165+ {
166+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
167+ "object" : "chat.completion.chunk" ,
168+ "created" : 1706565311 ,
169+ "model" : "gpt-3.5-turbo-0613" ,
170+ "system_fingerprint" : None ,
171+ "choices" : [{"index" : 0 , "delta" : {"content" : " to" }, "logprobs" : None , "finish_reason" : None }],
172+ },
173+ {
174+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
175+ "object" : "chat.completion.chunk" ,
176+ "created" : 1706565311 ,
177+ "model" : "gpt-3.5-turbo-0613" ,
178+ "system_fingerprint" : None ,
179+ "choices" : [{"index" : 0 , "delta" : {"content" : " " }, "logprobs" : None , "finish_reason" : None }],
180+ },
181+ {
182+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
183+ "object" : "chat.completion.chunk" ,
184+ "created" : 1706565311 ,
185+ "model" : "gpt-3.5-turbo-0613" ,
186+ "system_fingerprint" : None ,
187+ "choices" : [{"index" : 0 , "delta" : {"content" : "100" }, "logprobs" : None , "finish_reason" : None }],
188+ },
189+ {
190+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
191+ "object" : "chat.completion.chunk" ,
192+ "created" : 1706565311 ,
193+ "model" : "gpt-3.5-turbo-0613" ,
194+ "system_fingerprint" : None ,
195+ "choices" : [{"index" : 0 , "delta" : {"content" : " degrees" }, "logprobs" : None , "finish_reason" : None }],
196+ },
197+ {
198+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
199+ "object" : "chat.completion.chunk" ,
200+ "created" : 1706565311 ,
201+ "model" : "gpt-3.5-turbo-0613" ,
202+ "system_fingerprint" : None ,
203+ "choices" : [{"index" : 0 , "delta" : {"content" : " Celsius" }, "logprobs" : None , "finish_reason" : None }],
204+ },
205+ {
206+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
207+ "object" : "chat.completion.chunk" ,
208+ "created" : 1706565311 ,
209+ "model" : "gpt-3.5-turbo-0613" ,
210+ "system_fingerprint" : None ,
211+ "choices" : [{"index" : 0 , "delta" : {"content" : "." }, "logprobs" : None , "finish_reason" : None }],
212+ },
213+ {
214+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
215+ "object" : "chat.completion.chunk" ,
216+ "created" : 1706565311 ,
217+ "model" : "gpt-3.5-turbo-0613" ,
218+ "system_fingerprint" : None ,
219+ "choices" : [{"index" : 0 , "delta" : {}, "logprobs" : None , "finish_reason" : "stop" }],
220+ },
221+ ],
222+ ],
223+ }
224+
225+ RESPONSES_V1 = {
226+ "You are a scientist." : [
227+ {
228+ "Content-Type" : "text/event-stream" ,
229+ "openai-model" : "gpt-3.5-turbo-0613" ,
230+ "openai-organization" : "foobar-jtbczk" ,
231+ "openai-processing-ms" : "516" ,
232+ "openai-version" : "2020-10-01" ,
233+ "x-ratelimit-limit-requests" : "200" ,
234+ "x-ratelimit-limit-tokens" : "40000" ,
235+ "x-ratelimit-remaining-requests" : "196" ,
236+ "x-ratelimit-remaining-tokens" : "39880" ,
237+ "x-ratelimit-reset-requests" : "23m5.129s" ,
238+ "x-ratelimit-reset-tokens" : "180ms" ,
239+ "x-request-id" : "5c53c9b80af57a1c9b38568f01dcde7f" ,
240+ },
241+ 200 ,
242+ [
243+ {
244+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
245+ "object" : "chat.completion.chunk" ,
246+ "created" : 1706565311 ,
247+ "model" : "gpt-3.5-turbo-0613" ,
248+ "system_fingerprint" : None ,
249+ "choices" : [
250+ {"index" : 0 , "delta" : {"role" : "assistant" , "content" : "" }, "logprobs" : None , "finish_reason" : None }
251+ ],
252+ },
253+ {
254+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
255+ "object" : "chat.completion.chunk" ,
256+ "created" : 1706565311 ,
257+ "model" : "gpt-3.5-turbo-0613" ,
258+ "system_fingerprint" : None ,
259+ "choices" : [{"index" : 0 , "delta" : {"content" : "212" }, "logprobs" : None , "finish_reason" : None }],
260+ },
261+ {
262+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
263+ "object" : "chat.completion.chunk" ,
264+ "created" : 1706565311 ,
265+ "model" : "gpt-3.5-turbo-0613" ,
266+ "system_fingerprint" : None ,
267+ "choices" : [{"index" : 0 , "delta" : {"content" : " degrees" }, "logprobs" : None , "finish_reason" : None }],
268+ },
269+ {
270+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
271+ "object" : "chat.completion.chunk" ,
272+ "created" : 1706565311 ,
273+ "model" : "gpt-3.5-turbo-0613" ,
274+ "system_fingerprint" : None ,
275+ "choices" : [{"index" : 0 , "delta" : {"content" : " Fahrenheit" }, "logprobs" : None , "finish_reason" : None }],
276+ },
277+ {
278+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
279+ "object" : "chat.completion.chunk" ,
280+ "created" : 1706565311 ,
281+ "model" : "gpt-3.5-turbo-0613" ,
282+ "system_fingerprint" : None ,
283+ "choices" : [{"index" : 0 , "delta" : {"content" : " is" }, "logprobs" : None , "finish_reason" : None }],
284+ },
285+ {
286+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
287+ "object" : "chat.completion.chunk" ,
288+ "created" : 1706565311 ,
289+ "model" : "gpt-3.5-turbo-0613" ,
290+ "system_fingerprint" : None ,
291+ "choices" : [{"index" : 0 , "delta" : {"content" : " equal" }, "logprobs" : None , "finish_reason" : None }],
292+ },
293+ {
294+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
295+ "object" : "chat.completion.chunk" ,
296+ "created" : 1706565311 ,
297+ "model" : "gpt-3.5-turbo-0613" ,
298+ "system_fingerprint" : None ,
299+ "choices" : [{"index" : 0 , "delta" : {"content" : " to" }, "logprobs" : None , "finish_reason" : None }],
300+ },
301+ {
302+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
303+ "object" : "chat.completion.chunk" ,
304+ "created" : 1706565311 ,
305+ "model" : "gpt-3.5-turbo-0613" ,
306+ "system_fingerprint" : None ,
307+ "choices" : [{"index" : 0 , "delta" : {"content" : " " }, "logprobs" : None , "finish_reason" : None }],
308+ },
309+ {
310+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
311+ "object" : "chat.completion.chunk" ,
312+ "created" : 1706565311 ,
313+ "model" : "gpt-3.5-turbo-0613" ,
314+ "system_fingerprint" : None ,
315+ "choices" : [{"index" : 0 , "delta" : {"content" : "100" }, "logprobs" : None , "finish_reason" : None }],
316+ },
317+ {
318+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
319+ "object" : "chat.completion.chunk" ,
320+ "created" : 1706565311 ,
321+ "model" : "gpt-3.5-turbo-0613" ,
322+ "system_fingerprint" : None ,
323+ "choices" : [{"index" : 0 , "delta" : {"content" : " degrees" }, "logprobs" : None , "finish_reason" : None }],
324+ },
325+ {
326+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
327+ "object" : "chat.completion.chunk" ,
328+ "created" : 1706565311 ,
329+ "model" : "gpt-3.5-turbo-0613" ,
330+ "system_fingerprint" : None ,
331+ "choices" : [{"index" : 0 , "delta" : {"content" : " Celsius" }, "logprobs" : None , "finish_reason" : None }],
332+ },
333+ {
334+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
335+ "object" : "chat.completion.chunk" ,
336+ "created" : 1706565311 ,
337+ "model" : "gpt-3.5-turbo-0613" ,
338+ "system_fingerprint" : None ,
339+ "choices" : [{"index" : 0 , "delta" : {"content" : "." }, "logprobs" : None , "finish_reason" : None }],
340+ },
341+ {
342+ "id" : "chatcmpl-87sb95K4EF2nuJRcTs43Tm9ntTemv" ,
343+ "object" : "chat.completion.chunk" ,
344+ "created" : 1706565311 ,
345+ "model" : "gpt-3.5-turbo-0613" ,
346+ "system_fingerprint" : None ,
347+ "choices" : [{"index" : 0 , "delta" : {}, "logprobs" : None , "finish_reason" : "stop" }],
348+ },
349+ ],
350+ ]
351+ }
33352RESPONSES_V1 = {
34353 "You are a scientist." : [
35354 {
@@ -380,7 +699,7 @@ def simple_get(openai_version, extract_shortened_prompt):
380699 def _simple_get (self ):
381700 content_len = int (self .headers .get ("content-length" ))
382701 content = json .loads (self .rfile .read (content_len ).decode ("utf-8" ))
383-
702+ stream = content . get ( "stream" , False )
384703 prompt = extract_shortened_prompt (content )
385704 if not prompt :
386705 self .send_response (500 )
@@ -392,6 +711,8 @@ def _simple_get(self):
392711
393712 if openai_version < (1 , 0 ):
394713 mocked_responses = RESPONSES
714+ if stream :
715+ mocked_responses = STREAMED_RESPONSES
395716 else :
396717 mocked_responses = RESPONSES_V1
397718
@@ -414,7 +735,16 @@ def _simple_get(self):
414735 self .end_headers ()
415736
416737 # Send response body
417- self .wfile .write (json .dumps (response ).encode ("utf-8" ))
738+ if stream and status_code < 400 :
739+ for resp in response :
740+ data = json .dumps (resp ).encode ("utf-8" )
741+ if prompt == "Stream parsing error." :
742+ # Force a parsing error by writing an invalid streamed response.
743+ self .wfile .write (b"data: %s" % data )
744+ else :
745+ self .wfile .write (b"data: %s\n \n " % data )
746+ else :
747+ self .wfile .write (json .dumps (response ).encode ("utf-8" ))
418748 return
419749
420750 return _simple_get
0 commit comments