ka1kuk commited on
Commit
2c3649f
1 Parent(s): b9c73b1

Update Linlada.py

Browse files
Files changed (1) hide show
  1. Linlada.py +314 -1055
Linlada.py CHANGED
@@ -1,1093 +1,352 @@
1
- from __future__ import annotations
2
-
3
- import argparse
4
- import asyncio
5
- import json
6
  import os
 
7
  import random
8
- import re
9
- import ssl
10
- import sys
11
- import time
12
  import uuid
13
- from enum import Enum
14
- from pathlib import Path
15
- from typing import Generator
16
- from typing import Literal
17
- from typing import Optional
18
- from typing import Union
19
-
20
- import aiohttp
21
  import certifi
22
- import httpx
23
- from prompt_toolkit import PromptSession
24
- from prompt_toolkit.auto_suggest import AutoSuggestFromHistory
25
- from prompt_toolkit.completion import WordCompleter
26
- from prompt_toolkit.history import InMemoryHistory
27
- from prompt_toolkit.key_binding import KeyBindings
28
- from rich.live import Live
29
- from rich.markdown import Markdown
30
-
31
- DELIMITER = "\x1e"
32
-
33
 
34
- # Generate random IP between range 13.104.0.0/14
35
- FORWARDED_IP = (
36
- f"13.{random.randint(104, 107)}.{random.randint(0, 255)}.{random.randint(0, 255)}"
37
- )
38
 
39
- HEADERS = {
40
- "accept": "application/json",
41
- "accept-language": "en-US,en;q=0.9",
42
- "content-type": "application/json",
43
- "sec-ch-ua": '"Not_A Brand";v="99", "Microsoft Edge";v="110", "Chromium";v="110"',
44
- "sec-ch-ua-arch": '"x86"',
45
- "sec-ch-ua-bitness": '"64"',
46
- "sec-ch-ua-full-version": '"109.0.1518.78"',
47
- "sec-ch-ua-full-version-list": '"Chromium";v="110.0.5481.192", "Not A(Brand";v="24.0.0.0", "Microsoft Edge";v="110.0.1587.69"',
48
- "sec-ch-ua-mobile": "?0",
49
- "sec-ch-ua-model": "",
50
- "sec-ch-ua-platform": '"Windows"',
51
- "sec-ch-ua-platform-version": '"15.0.0"',
52
- "sec-fetch-dest": "empty",
53
- "sec-fetch-mode": "cors",
54
- "sec-fetch-site": "same-origin",
55
- "x-ms-client-request-id": str(uuid.uuid4()),
56
- "x-ms-useragent": "azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/Win32",
57
- "Referer": "https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx",
58
- "Referrer-Policy": "origin-when-cross-origin",
59
- "x-forwarded-for": FORWARDED_IP,
60
- }
61
 
62
- HEADERS_INIT_CONVER = {
63
- "authority": "edgeservices.bing.com",
64
- "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
65
- "accept-language": "en-US,en;q=0.9",
66
- "cache-control": "max-age=0",
67
- "sec-ch-ua": '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
68
- "sec-ch-ua-arch": '"x86"',
69
- "sec-ch-ua-bitness": '"64"',
70
- "sec-ch-ua-full-version": '"110.0.1587.69"',
71
- "sec-ch-ua-full-version-list": '"Chromium";v="110.0.5481.192", "Not A(Brand";v="24.0.0.0", "Microsoft Edge";v="110.0.1587.69"',
72
- "sec-ch-ua-mobile": "?0",
73
- "sec-ch-ua-model": '""',
74
- "sec-ch-ua-platform": '"Windows"',
75
- "sec-ch-ua-platform-version": '"15.0.0"',
76
- "sec-fetch-dest": "document",
77
- "sec-fetch-mode": "navigate",
78
- "sec-fetch-site": "none",
79
- "sec-fetch-user": "?1",
80
- "upgrade-insecure-requests": "1",
81
- "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.69",
82
- "x-edge-shopping-flag": "1",
83
- "x-forwarded-for": FORWARDED_IP,
84
- }
85
 
86
  ssl_context = ssl.create_default_context()
87
  ssl_context.load_verify_locations(certifi.where())
88
 
89
 
90
- class NotAllowedToAccess(Exception):
91
- pass
92
-
93
-
94
- class ConversationStyle(Enum):
95
- creative = [
96
- "nlu_direct_response_filter",
97
- "deepleo",
98
- "disable_emoji_spoken_text",
99
- "responsible_ai_policy_235",
100
- "enablemm",
101
- "h3imaginative",
102
- "travelansgnd",
103
- "dv3sugg",
104
- "clgalileo",
105
- "gencontentv3",
106
- "dv3sugg",
107
- "responseos",
108
- "e2ecachewrite",
109
- "cachewriteext",
110
- "nodlcpcwrite",
111
- "travelansgnd",
112
- "nojbfedge",
113
- ]
114
- balanced = [
115
- "nlu_direct_response_filter",
116
- "deepleo",
117
- "disable_emoji_spoken_text",
118
- "responsible_ai_policy_235",
119
- "enablemm",
120
- "galileo",
121
- "dv3sugg",
122
- "responseos",
123
- "e2ecachewrite",
124
- "cachewriteext",
125
- "nodlcpcwrite",
126
- "travelansgnd",
127
- "nojbfedge",
128
- ]
129
- precise = [
130
- "nlu_direct_response_filter",
131
- "deepleo",
132
- "disable_emoji_spoken_text",
133
- "responsible_ai_policy_235",
134
- "enablemm",
135
- "galileo",
136
- "dv3sugg",
137
- "responseos",
138
- "e2ecachewrite",
139
- "cachewriteext",
140
- "nodlcpcwrite",
141
- "travelansgnd",
142
- "h3precise",
143
- "clgalileo",
144
- "nojbfedge",
145
  ]
146
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
147
 
148
- CONVERSATION_STYLE_TYPE = Optional[
149
- Union[ConversationStyle, Literal["creative", "balanced", "precise"]]
150
- ]
151
-
152
-
153
- def _append_identifier(msg: dict) -> str:
154
- """
155
- Appends special character to end of message to identify end of message
156
- """
157
- # Convert dict to json string
158
- return json.dumps(msg, ensure_ascii=False) + DELIMITER
159
-
160
-
161
- def _get_ran_hex(length: int = 32) -> str:
162
- """
163
- Returns random hex string
164
- """
165
- return "".join(random.choice("0123456789abcdef") for _ in range(length))
166
-
167
-
168
- class _ChatHubRequest:
169
- """
170
- Request object for ChatHub
171
- """
172
-
173
- def __init__(
174
- self,
175
- conversation_signature: str,
176
- client_id: str,
177
- conversation_id: str,
178
- invocation_id: int = 0,
179
- ) -> None:
180
- self.struct: dict = {}
181
-
182
- self.client_id: str = client_id
183
- self.conversation_id: str = conversation_id
184
- self.conversation_signature: str = conversation_signature
185
- self.invocation_id: int = invocation_id
186
-
187
- def update(
188
- self,
189
- prompt: str,
190
- conversation_style: CONVERSATION_STYLE_TYPE,
191
- options: list | None = None,
192
- webpage_context: str | None = None,
193
- search_result: bool = False,
194
- ) -> None:
195
- """
196
- Updates request object
197
- """
198
- if options is None:
199
- options = [
200
- "deepleo",
201
- "enable_debug_commands",
202
- "disable_emoji_spoken_text",
203
- "enablemm",
204
- ]
205
- if conversation_style:
206
- if not isinstance(conversation_style, ConversationStyle):
207
- conversation_style = getattr(ConversationStyle, conversation_style)
208
- options = conversation_style.value
209
- self.struct = {
210
- "arguments": [
211
- {
212
- "source": "cib",
213
- "optionsSets": options,
214
- "allowedMessageTypes": [
215
- "Chat",
216
- "Disengaged",
217
- "AdsQuery",
218
- "SemanticSerp",
219
- "GenerateContentQuery",
220
- "SearchQuery",
221
- ],
222
- "sliceIds": [
223
- "chk1cf",
224
- "nopreloadsscf",
225
- "winlongmsg2tf",
226
- "perfimpcomb",
227
- "sugdivdis",
228
- "sydnoinputt",
229
- "wpcssopt",
230
- "wintone2tf",
231
- "0404sydicnbs0",
232
- "405suggbs0",
233
- "scctl",
234
- "330uaugs0",
235
- "0329resp",
236
- "udscahrfon",
237
- "udstrblm5",
238
- "404e2ewrt",
239
- "408nodedups0",
240
- "403tvlansgnd",
241
- ],
242
- "traceId": _get_ran_hex(32),
243
- "isStartOfSession": self.invocation_id == 0,
244
- "message": {
245
- "author": "user",
246
- "inputMethod": "Keyboard",
247
- "text": prompt,
248
- "messageType": "Chat",
249
- },
250
- "conversationSignature": self.conversation_signature,
251
- "participant": {
252
- "id": self.client_id,
253
- },
254
- "conversationId": self.conversation_id,
255
  },
256
- ],
257
- "invocationId": str(self.invocation_id),
258
- "target": "chat",
259
- "type": 4,
260
- }
261
- if search_result:
262
- have_search_result = [
263
- "InternalSearchQuery",
264
- "InternalSearchResult",
265
- "InternalLoaderMessage",
266
- "RenderCardRequest",
267
- ]
268
- self.struct["arguments"][0]["allowedMessageTypes"] += have_search_result
269
- if webpage_context:
270
- self.struct["arguments"][0]["previousMessages"] = [
271
- {
272
- "author": "user",
273
- "description": webpage_context,
274
- "contextType": "WebPage",
275
- "messageType": "Context",
276
- "messageId": "discover-web--page-ping-mriduna-----",
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
277
  },
278
- ]
279
- self.invocation_id += 1
280
-
281
-
282
- class _Conversation:
283
- """
284
- Conversation API
285
- """
286
-
287
- def __init__(
288
- self,
289
- proxy: str | None = None,
290
- async_mode: bool = False,
291
- cookies: list[dict] | None = None,
292
- ) -> None:
293
- if async_mode:
294
- return
295
- self.struct: dict = {
296
- "conversationId": None,
297
- "clientId": None,
298
- "conversationSignature": None,
299
- "result": {"value": "Success", "message": None},
300
- }
301
- self.proxy = proxy
302
- proxy = (
303
- proxy
304
- or os.environ.get("all_proxy")
305
- or os.environ.get("ALL_PROXY")
306
- or os.environ.get("https_proxy")
307
- or os.environ.get("HTTPS_PROXY")
308
- or None
309
- )
310
- if proxy is not None and proxy.startswith("socks5h://"):
311
- proxy = "socks5://" + proxy[len("socks5h://") :]
312
- self.session = httpx.Client(
313
- proxies=proxy,
314
- timeout=30,
315
- headers=HEADERS_INIT_CONVER,
316
- )
317
- if cookies:
318
- for cookie in cookies:
319
- self.session.cookies.set(cookie["name"], cookie["value"])
320
- # Send GET request
321
- response = self.session.get(
322
- url=os.environ.get("BING_PROXY_URL")
323
- or "https://edgeservices.bing.com/edgesvc/turing/conversation/create",
324
- )
325
- if response.status_code != 200:
326
- response = self.session.get(
327
- "https://edge.churchless.tech/edgesvc/turing/conversation/create",
328
- )
329
- if response.status_code != 200:
330
- print(f"Status code: {response.status_code}")
331
- print(response.text)
332
- print(response.url)
333
- raise Exception("Authentication failed")
334
- try:
335
- self.struct = response.json()
336
- except (json.decoder.JSONDecodeError, NotAllowedToAccess) as exc:
337
- raise Exception(
338
- "Authentication failed. You have not been accepted into the beta.",
339
- ) from exc
340
- if self.struct["result"]["value"] == "UnauthorizedRequest":
341
- raise NotAllowedToAccess(self.struct["result"]["message"])
342
-
343
- @staticmethod
344
- async def create(
345
- proxy: str | None = None,
346
- cookies: list[dict] | None = None,
347
- ) -> _Conversation:
348
- self = _Conversation(async_mode=True)
349
- self.struct = {
350
- "conversationId": None,
351
- "clientId": None,
352
- "conversationSignature": None,
353
- "result": {"value": "Success", "message": None},
354
- }
355
- self.proxy = proxy
356
- proxy = (
357
- proxy
358
- or os.environ.get("all_proxy")
359
- or os.environ.get("ALL_PROXY")
360
- or os.environ.get("https_proxy")
361
- or os.environ.get("HTTPS_PROXY")
362
- or None
363
- )
364
- if proxy is not None and proxy.startswith("socks5h://"):
365
- proxy = "socks5://" + proxy[len("socks5h://") :]
366
- transport = httpx.AsyncHTTPTransport(retries=10)
367
- # Convert cookie format to httpx format
368
- formatted_cookies = None
369
- if cookies:
370
- formatted_cookies = httpx.Cookies()
371
- for cookie in cookies:
372
- formatted_cookies.set(cookie["name"], cookie["value"])
373
- async with httpx.AsyncClient(
374
- proxies=proxy,
375
- timeout=30,
376
- headers=HEADERS_INIT_CONVER,
377
- transport=transport,
378
- cookies=formatted_cookies,
379
- ) as client:
380
- # Send GET request
381
- response = await client.get(
382
- url=os.environ.get("BING_PROXY_URL")
383
- or "https://edgeservices.bing.com/edgesvc/turing/conversation/create",
384
- )
385
- if response.status_code != 200:
386
- response = await client.get(
387
- "https://edge.churchless.tech/edgesvc/turing/conversation/create",
388
- )
389
- if response.status_code != 200:
390
- print(f"Status code: {response.status_code}")
391
- print(response.text)
392
- print(response.url)
393
- raise Exception("Authentication failed")
394
- try:
395
- self.struct = response.json()
396
- except (json.decoder.JSONDecodeError, NotAllowedToAccess) as exc:
397
- raise Exception(
398
- "Authentication failed. You have not been accepted into the beta.",
399
- ) from exc
400
- if self.struct["result"]["value"] == "UnauthorizedRequest":
401
- raise NotAllowedToAccess(self.struct["result"]["message"])
402
- return self
403
-
404
-
405
- class _ChatHub:
406
- """
407
- Chat API
408
- """
409
-
410
- def __init__(
411
- self,
412
- conversation: _Conversation,
413
- proxy: str = None,
414
- cookies: list[dict] | None = None,
415
- ) -> None:
416
- self.session: aiohttp.ClientSession | None = None
417
- self.wss: aiohttp.ClientWebSocketResponse | None = None
418
- self.request: _ChatHubRequest
419
- self.loop: bool
420
- self.task: asyncio.Task
421
- self.request = _ChatHubRequest(
422
- conversation_signature=conversation.struct["conversationSignature"],
423
- client_id=conversation.struct["clientId"],
424
- conversation_id=conversation.struct["conversationId"],
425
- )
426
- self.cookies = cookies
427
- self.proxy: str = proxy
428
-
429
- async def ask_stream(
430
- self,
431
- prompt: str,
432
- wss_link: str,
433
- conversation_style: CONVERSATION_STYLE_TYPE = None,
434
- raw: bool = False,
435
- options: dict = None,
436
- webpage_context: str | None = None,
437
- search_result: bool = False,
438
- ) -> Generator[str, None, None]:
439
- """
440
- Ask a question to the bot
441
- """
442
- timeout = aiohttp.ClientTimeout(total=30)
443
- self.session = aiohttp.ClientSession(timeout=timeout)
444
-
445
- if self.wss and not self.wss.closed:
446
- await self.wss.close()
447
- # Check if websocket is closed
448
- self.wss = await self.session.ws_connect(
449
- wss_link,
450
- headers=HEADERS,
451
- ssl=ssl_context,
452
- proxy=self.proxy,
453
- autoping=False,
454
- )
455
- await self._initial_handshake()
456
- if self.request.invocation_id == 0:
457
- # Construct a ChatHub request
458
- self.request.update(
459
- prompt=prompt,
460
- conversation_style=conversation_style,
461
- options=options,
462
- webpage_context=webpage_context,
463
- search_result=search_result,
464
- )
465
- else:
466
- async with httpx.AsyncClient() as client:
467
- response = await client.post(
468
- "https://sydney.bing.com/sydney/UpdateConversation/",
469
- json={
470
- "messages": [
471
- {
472
- "author": "user",
473
- "description": webpage_context,
474
- "contextType": "WebPage",
475
- "messageType": "Context",
476
- },
477
- ],
478
- "conversationId": self.request.conversation_id,
479
- "source": "cib",
480
- "traceId": _get_ran_hex(32),
481
- "participant": {"id": self.request.client_id},
482
- "conversationSignature": self.request.conversation_signature,
483
- },
484
- )
485
- if response.status_code != 200:
486
- print(f"Status code: {response.status_code}")
487
- print(response.text)
488
- print(response.url)
489
- raise Exception("Update web page context failed")
490
- # Construct a ChatHub request
491
- self.request.update(
492
- prompt=prompt,
493
- conversation_style=conversation_style,
494
- options=options,
495
- )
496
- # Send request
497
- await self.wss.send_str(_append_identifier(self.request.struct))
498
- final = False
499
- draw = False
500
- resp_txt = ""
501
- result_text = ""
502
- resp_txt_no_link = ""
503
- while not final:
504
- msg = await self.wss.receive()
505
- objects = msg.data.split(DELIMITER)
506
- for obj in objects:
507
- if obj is None or not obj:
508
- continue
509
- response = json.loads(obj)
510
- if response.get("type") != 2 and raw:
511
- yield False, response
512
- elif response.get("type") == 1 and response["arguments"][0].get(
513
- "messages",
514
- ):
515
- if not draw:
516
- if (
517
- response["arguments"][0]["messages"][0].get("messageType")
518
- == "GenerateContentQuery"
519
- ):
520
- draw = True
521
- if (
522
- response["arguments"][0]["messages"][0]["contentOrigin"]
523
- != "Apology"
524
- ) and not draw:
525
- resp_txt = result_text + response["arguments"][0][
526
- "messages"
527
- ][0]["adaptiveCards"][0]["body"][0].get("text", "")
528
- resp_txt_no_link = result_text + response["arguments"][0][
529
- "messages"
530
- ][0].get("text", "")
531
- if response["arguments"][0]["messages"][0].get(
532
- "messageType",
533
- ):
534
- resp_txt = (
535
- resp_txt
536
- + response["arguments"][0]["messages"][0][
537
- "adaptiveCards"
538
- ][0]["body"][0]["inlines"][0].get("text")
539
- + "\n"
540
- )
541
- result_text = (
542
- result_text
543
- + response["arguments"][0]["messages"][0][
544
- "adaptiveCards"
545
- ][0]["body"][0]["inlines"][0].get("text")
546
- + "\n"
547
- )
548
- yield False, resp_txt
549
-
550
- elif response.get("type") == 2:
551
- if response["item"]["result"].get("error"):
552
- await self.close()
553
- raise Exception(
554
- f"{response['item']['result']['value']}: {response['item']['result']['message']}",
555
- )
556
- if draw:
557
- cache = response["item"]["messages"][1]["adaptiveCards"][0][
558
- "body"
559
- ][0]["text"]
560
- response["item"]["messages"][1]["adaptiveCards"][0]["body"][0][
561
- "text"
562
- ] = (cache + resp_txt)
563
- if (
564
- response["item"]["messages"][-1]["contentOrigin"] == "Apology"
565
- and resp_txt
566
- ):
567
- response["item"]["messages"][-1]["text"] = resp_txt_no_link
568
- response["item"]["messages"][-1]["adaptiveCards"][0]["body"][0][
569
- "text"
570
- ] = resp_txt
571
- print(
572
- "Preserved the message from being deleted",
573
- file=sys.stderr,
574
- )
575
- final = True
576
- await self.close()
577
- yield True, response
578
-
579
- async def _initial_handshake(self) -> None:
580
- await self.wss.send_str(_append_identifier({"protocol": "json", "version": 1}))
581
- await self.wss.receive()
582
-
583
- async def close(self) -> None:
584
- """
585
- Close the connection
586
- """
587
- if self.wss and not self.wss.closed:
588
- await self.wss.close()
589
- if self.session and not self.session.closed:
590
- await self.session.close()
591
-
592
-
593
- class Chatbot:
594
- """
595
- Combines everything to make it seamless
596
- """
597
-
598
- def __init__(
599
- self,
600
- proxy: str | None = None,
601
- cookies: list[dict] | None = None,
602
- ) -> None:
603
- self.proxy: str | None = proxy
604
- self.chat_hub: _ChatHub = _ChatHub(
605
- _Conversation(self.proxy, cookies=cookies),
606
- proxy=self.proxy,
607
- cookies=cookies,
608
- )
609
-
610
- @staticmethod
611
- async def create(
612
- proxy: str | None = None,
613
- cookies: list[dict] | None = None,
614
- ):
615
- self = Chatbot.__new__(Chatbot)
616
- self.proxy = proxy
617
- self.chat_hub = _ChatHub(
618
- await _Conversation.create(self.proxy, cookies=cookies),
619
- proxy=self.proxy,
620
- cookies=cookies,
621
- )
622
- return self
623
-
624
- async def ask(
625
- self,
626
- prompt: str,
627
- wss_link: str = "wss://sydney.bing.com/sydney/ChatHub",
628
- conversation_style: CONVERSATION_STYLE_TYPE = None,
629
- options: dict = None,
630
- webpage_context: str | None = None,
631
- search_result: bool = False,
632
- ) -> dict:
633
- """
634
- Ask a question to the bot
635
- """
636
- async for final, response in self.chat_hub.ask_stream(
637
- prompt=prompt,
638
- conversation_style=conversation_style,
639
- wss_link=wss_link,
640
- options=options,
641
- webpage_context=webpage_context,
642
- search_result=search_result,
643
- ):
644
- if final:
645
- return response
646
- await self.chat_hub.wss.close()
647
- return {}
648
-
649
- async def ask_stream(
650
- self,
651
- prompt: str,
652
- wss_link: str = "wss://sydney.bing.com/sydney/ChatHub",
653
- conversation_style: CONVERSATION_STYLE_TYPE = None,
654
- raw: bool = False,
655
- options: dict = None,
656
- webpage_context: str | None = None,
657
- search_result: bool = False,
658
- ) -> Generator[str, None, None]:
659
- """
660
- Ask a question to the bot
661
- """
662
- async for response in self.chat_hub.ask_stream(
663
- prompt=prompt,
664
- conversation_style=conversation_style,
665
- wss_link=wss_link,
666
- raw=raw,
667
- options=options,
668
- webpage_context=webpage_context,
669
- search_result=search_result,
670
- ):
671
- yield response
672
-
673
- async def close(self) -> None:
674
- """
675
- Close the connection
676
- """
677
- await self.chat_hub.close()
678
-
679
- async def reset(self) -> None:
680
- """
681
- Reset the conversation
682
- """
683
- await self.close()
684
- self.chat_hub = _ChatHub(
685
- await _Conversation.create(self.proxy),
686
- proxy=self.proxy,
687
- )
688
-
689
-
690
- async def _get_input_async(
691
- session: PromptSession = None,
692
- completer: WordCompleter = None,
693
- ) -> str:
694
- """
695
- Multiline input function.
696
- """
697
- return await session.prompt_async(
698
- completer=completer,
699
- multiline=True,
700
- auto_suggest=AutoSuggestFromHistory(),
701
- )
702
-
703
-
704
- def _create_session() -> PromptSession:
705
- kb = KeyBindings()
706
-
707
- @kb.add("enter")
708
- def _(event):
709
- buffer_text = event.current_buffer.text
710
- if buffer_text.startswith("!"):
711
- event.current_buffer.validate_and_handle()
712
- else:
713
- event.current_buffer.insert_text("\n")
714
-
715
- @kb.add("escape")
716
- def _(event):
717
- if event.current_buffer.complete_state:
718
- # event.current_buffer.cancel_completion()
719
- event.current_buffer.text = ""
720
 
721
- return PromptSession(key_bindings=kb, history=InMemoryHistory())
722
 
 
 
 
 
 
 
723
 
724
- def _create_completer(commands: list, pattern_str: str = "$"):
725
- return WordCompleter(words=commands, pattern=re.compile(pattern_str))
 
726
 
 
 
 
727
 
728
- async def async_main(args: argparse.Namespace) -> None:
729
- """
730
- Main function
731
- """
732
- print("Initializing...")
733
- print("Enter `alt+enter` or `escape+enter` to send a message")
734
- # Read and parse cookies
735
- cookies = None
736
- if args.cookie_file:
737
- cookies = json.loads(open(args.cookie_file, encoding="utf-8").read())
738
- bot = await Chatbot.create(proxy=args.proxy, cookies=cookies)
739
- session = _create_session()
740
- completer = _create_completer(["!help", "!exit", "!reset"])
741
- initial_prompt = args.prompt
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
742
 
743
  while True:
744
- print("\nYou:")
745
- if initial_prompt:
746
- question = initial_prompt
747
- print(question)
748
- initial_prompt = None
749
- else:
750
- question = (
751
- input()
752
- if args.enter_once
753
- else await _get_input_async(session=session, completer=completer)
754
- )
755
- print()
756
- if question == "!exit":
757
- break
758
- if question == "!help":
759
- print(
760
- """
761
- !help - Show this help message
762
- !exit - Exit the program
763
- !reset - Reset the conversation
764
- """,
765
- )
766
- continue
767
- if question == "!reset":
768
- await bot.reset()
769
- continue
770
- print("Bot:")
771
- if args.no_stream:
772
- print(
773
- (
774
- await bot.ask(
775
- prompt=question,
776
- conversation_style=args.style,
777
- wss_link=args.wss_link,
778
- )
779
- )["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"],
780
- )
781
- else:
782
- wrote = 0
783
- if args.rich:
784
- md = Markdown("")
785
- with Live(md, auto_refresh=False) as live:
786
- async for final, response in bot.ask_stream(
787
- prompt=question,
788
- conversation_style=args.style,
789
- wss_link=args.wss_link,
790
- ):
791
- if not final:
792
- if wrote > len(response):
793
- print(md)
794
- print(Markdown("***Bing revoked the response.***"))
795
- wrote = len(response)
796
- md = Markdown(response)
797
- live.update(md, refresh=True)
798
- else:
799
- async for final, response in bot.ask_stream(
800
- prompt=question,
801
- conversation_style=args.style,
802
- wss_link=args.wss_link,
803
- ):
804
- if not final:
805
- if not wrote:
806
- print(response, end="", flush=True)
807
- else:
808
- print(response[wrote:], end="", flush=True)
809
- wrote = len(response)
810
- print()
811
- await bot.close()
812
-
813
-
814
- def main() -> None:
815
- print(
816
- """
817
- EdgeGPT - A demo of reverse engineering the Bing GPT chatbot
818
- Repo: github.com/acheong08/EdgeGPT
819
- By: Antonio Cheong
820
-
821
- !help for help
822
-
823
- Type !exit to exit
824
- """,
825
- )
826
- parser = argparse.ArgumentParser()
827
- parser.add_argument("--enter-once", action="store_true")
828
- parser.add_argument("--no-stream", action="store_true")
829
- parser.add_argument("--rich", action="store_true")
830
- parser.add_argument(
831
- "--proxy",
832
- help="Proxy URL (e.g. socks5://127.0.0.1:1080)",
833
- type=str,
834
- )
835
- parser.add_argument(
836
- "--wss-link",
837
- help="WSS URL(e.g. wss://sydney.bing.com/sydney/ChatHub)",
838
- type=str,
839
- default="wss://sydney.bing.com/sydney/ChatHub",
840
- )
841
- parser.add_argument(
842
- "--style",
843
- choices=["creative", "balanced", "precise"],
844
- default="balanced",
845
- )
846
- parser.add_argument(
847
- "--prompt",
848
- type=str,
849
- default="",
850
- required=False,
851
- help="prompt to start with",
852
- )
853
- parser.add_argument(
854
- "--cookie-file",
855
- type=str,
856
- default="",
857
- required=False,
858
- help="path to cookie file",
859
- )
860
- args = parser.parse_args()
861
- asyncio.run(async_main(args))
862
-
863
-
864
- class Cookie:
865
- """
866
- Convenience class for Bing Cookie files, data, and configuration. This Class
867
- is updated dynamically by the Query class to allow cycling through >1
868
- cookie/credentials file e.g. when daily request limits (current 200 per
869
- account per day) are exceeded.
870
- """
871
-
872
- current_file_index = 0
873
- dirpath = Path("./").resolve()
874
- search_pattern = "bing_cookies_*.json"
875
- ignore_files = set()
876
-
877
- @classmethod
878
- def fetch_default(cls, path=None):
879
- from selenium import webdriver
880
- from selenium.webdriver.common.by import By
881
-
882
- driver = webdriver.Edge()
883
- driver.get("https://bing.com/chat")
884
- time.sleep(5)
885
- xpath = '//button[@id="bnp_btn_accept"]'
886
- driver.find_element(By.XPATH, xpath).click()
887
- time.sleep(2)
888
- xpath = '//a[@id="codexPrimaryButton"]'
889
- driver.find_element(By.XPATH, xpath).click()
890
- if path is None:
891
- path = Path("./bing_cookies__default.json")
892
- # Double underscore ensures this file is first when sorted
893
- cookies = driver.get_cookies()
894
- Path(path).write_text(json.dumps(cookies, indent=4), encoding="utf-8")
895
- # Path again in case supplied path is: str
896
- print(f"Cookies saved to: {path}")
897
- driver.quit()
898
-
899
- @classmethod
900
- def files(cls):
901
- """Return a sorted list of all cookie files matching .search_pattern"""
902
- all_files = set(cls.dirpath.glob(cls.search_pattern))
903
- return sorted(list(all_files - cls.ignore_files))
904
-
905
- @classmethod
906
- def import_data(cls):
907
- """
908
- Read the active cookie file and populate the following attributes:
909
-
910
- .current_filepath
911
- .current_data
912
- .image_token
913
- """
914
  try:
915
- cls.current_filepath = cls.files()[cls.current_file_index]
916
- except IndexError:
917
- print(
918
- "> Please set Cookie.current_filepath to a valid cookie file, then run Cookie.import_data()",
919
- )
920
- return
921
- print(f"> Importing cookies from: {cls.current_filepath.name}")
922
- with open(cls.current_filepath, encoding="utf-8") as file:
923
- cls.current_data = json.load(file)
924
- cls.image_token = [x for x in cls.current_data if x.get("name") == "_U"]
925
- cls.image_token = cls.image_token[0].get("value")
926
-
927
- @classmethod
928
- def import_next(cls):
929
- """
930
- Cycle through to the next cookies file. Import it. Mark the previous
931
- file to be ignored for the remainder of the current session.
932
- """
933
- cls.ignore_files.add(cls.current_filepath)
934
- if Cookie.current_file_index >= len(cls.files()):
935
- Cookie.current_file_index = 0
936
- Cookie.import_data()
937
 
 
 
938
 
939
- class Query:
940
- """
941
- A convenience class that wraps around EdgeGPT.Chatbot to encapsulate input,
942
- config, and output all together. Relies on Cookie class for authentication
943
- """
944
-
945
- def __init__(
946
- self,
947
- prompt,
948
- style="precise",
949
- content_type="text",
950
- cookie_file=0,
951
- echo=True,
952
- echo_prompt=False,
953
- ):
954
- """
955
- Arguments:
956
-
957
- prompt: Text to enter into Bing Chat
958
- style: creative, balanced, or precise
959
- content_type: "text" for Bing Chat; "image" for Dall-e
960
- cookie_file: Path, filepath string, or index (int) to list of cookie paths
961
- echo: Print something to confirm request made
962
- echo_prompt: Print confirmation of the evaluated prompt
963
- """
964
- self.index = []
965
- self.request_count = {}
966
- self.image_dirpath = Path("./").resolve()
967
- Cookie.import_data()
968
- self.index += [self]
969
- self.prompt = prompt
970
- files = Cookie.files()
971
- if isinstance(cookie_file, int):
972
- index = cookie_file if cookie_file < len(files) else 0
973
- else:
974
- if not isinstance(cookie_file, (str, Path)):
975
- message = "'cookie_file' must be an int, str, or Path object"
976
- raise TypeError(message)
977
- cookie_file = Path(cookie_file)
978
- if cookie_file in files(): # Supplied filepath IS in Cookie.dirpath
979
- index = files.index(cookie_file)
980
- else: # Supplied filepath is NOT in Cookie.dirpath
981
- if cookie_file.is_file():
982
- Cookie.dirpath = cookie_file.parent.resolve()
983
- if cookie_file.is_dir():
984
- Cookie.dirpath = cookie_file.resolve()
985
- index = 0
986
- Cookie.current_file_index = index
987
- if content_type == "text":
988
- self.style = style
989
- self.log_and_send_query(echo, echo_prompt)
990
- if content_type == "image":
991
- self.create_image()
992
-
993
- def log_and_send_query(self, echo, echo_prompt):
994
- self.response = asyncio.run(self.send_to_bing(echo, echo_prompt))
995
- name = str(Cookie.current_filepath.name)
996
- if not self.request_count.get(name):
997
- self.request_count[name] = 1
998
- else:
999
- self.request_count[name] += 1
1000
-
1001
- def create_image(self):
1002
- print('Image cannot available!')
1003
-
1004
- async def send_to_bing(self, echo=True, echo_prompt=False):
1005
- """Creat, submit, then close a Chatbot instance. Return the response"""
1006
- retries = len(Cookie.files())
1007
- while retries:
1008
- try:
1009
- bot = await Chatbot.create()
1010
- if echo_prompt:
1011
- print(f"> {self.prompt=}")
1012
- if echo:
1013
- print("> Waiting for response...")
1014
- if self.style.lower() not in "creative balanced precise".split():
1015
- self.style = "precise"
1016
- response = await bot.ask(
1017
- prompt=self.prompt,
1018
- conversation_style=getattr(ConversationStyle, self.style),
1019
- # wss_link="wss://sydney.bing.com/sydney/ChatHub"
1020
- # What other values can this parameter take? It seems to be optional
1021
- )
1022
- return response
1023
- except KeyError:
1024
- print(
1025
- f"> KeyError [{Cookie.current_filepath.name} may have exceeded the daily limit]",
1026
- )
1027
- Cookie.import_next()
1028
- retries -= 1
1029
- finally:
1030
- await bot.close()
1031
-
1032
- @property
1033
- def output(self):
1034
- """The response from a completed Chatbot request"""
1035
- return self.response["item"]["messages"][1]["text"]
1036
 
1037
- @property
1038
- def sources(self):
1039
- """The source names and details parsed from a completed Chatbot request"""
1040
- return self.response["item"]["messages"][1]["sourceAttributions"]
1041
 
1042
- @property
1043
- def sources_dict(self):
1044
- """The source names and details as a dictionary"""
1045
- sources_dict = {}
1046
- name = "providerDisplayName"
1047
- url = "seeMoreUrl"
1048
- for source in self.sources:
1049
- if name in source.keys() and url in source.keys():
1050
- sources_dict[source[name]] = source[url]
1051
- else:
1052
- continue
1053
- return sources_dict
1054
 
1055
- @property
1056
- def code(self):
1057
- """Extract and join any snippets of Python code in the response"""
1058
- code_blocks = self.output.split("```")[1:-1:2]
1059
- code_blocks = ["\n".join(x.splitlines()[1:]) for x in code_blocks]
1060
- return "\n\n".join(code_blocks)
1061
 
1062
- @property
1063
- def languages(self):
1064
- """Extract all programming languages given in code blocks"""
1065
- code_blocks = self.output.split("```")[1:-1:2]
1066
- return {x.splitlines()[0] for x in code_blocks}
1067
-
1068
- @property
1069
- def suggestions(self):
1070
- """Follow-on questions suggested by the Chatbot"""
1071
- return [
1072
- x["text"]
1073
- for x in self.response["item"]["messages"][1]["suggestedResponses"]
1074
- ]
1075
 
1076
- def __repr__(self):
1077
- return f"<EdgeGPT.Query: {self.prompt}>"
1078
 
1079
- def __str__(self):
1080
- return self.output
 
 
1081
 
 
 
 
1082
 
1083
- class ImageQuery(Query):
1084
- def __init__(self, prompt, **kwargs):
1085
- kwargs.update({"content_type": "image"})
1086
- super().__init__(prompt, **kwargs)
1087
 
1088
- def __repr__(self):
1089
- return f"<EdgeGPT.ImageQuery: {self.prompt}>"
1090
 
1091
 
1092
- if __name__ == "__main__":
1093
- main()
 
 
 
 
 
 
 
1
  import os
2
+ import json
3
  import random
4
+ import json
5
+ import os
 
 
6
  import uuid
7
+ import ssl
 
 
 
 
 
 
 
8
  import certifi
9
+ import aiohttp
10
+ import asyncio
 
 
 
 
 
 
 
 
 
11
 
12
+ import requests
13
+ from typing import Dict, NewType, Union, Optional, List, get_type_hints
 
 
14
 
15
+ sha256 = NewType('sha_256_hash', str)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
16
 
17
+ url = 'https://bing.com/chat'
18
+ model = ['gpt-4']
19
+ supports_stream = True
20
+ needs_auth = False
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
21
 
22
  ssl_context = ssl.create_default_context()
23
  ssl_context.load_verify_locations(certifi.where())
24
 
25
 
26
+ class optionsSets:
27
+ optionSet: dict = {
28
+ 'tone': str,
29
+ 'optionsSets': list
30
+ }
31
+
32
+ jailbreak: dict = {
33
+ "optionsSets": [
34
+ 'saharasugg',
35
+ 'enablenewsfc',
36
+ 'clgalileo',
37
+ 'gencontentv3',
38
+ "nlu_direct_response_filter",
39
+ "deepleo",
40
+ "disable_emoji_spoken_text",
41
+ "responsible_ai_policy_235",
42
+ "enablemm",
43
+ "h3precise"
44
+ # "harmonyv3",
45
+ "dtappid",
46
+ "cricinfo",
47
+ "cricinfov2",
48
+ "dv3sugg",
49
+ "nojbfedge"
50
+ ]
51
+ }
52
+
53
+
54
+ class Defaults:
55
+ delimiter = '\x1e'
56
+ ip_address = f'13.{random.randint(104, 107)}.{random.randint(0, 255)}.{random.randint(0, 255)}'
57
+
58
+ allowedMessageTypes = [
59
+ 'Chat',
60
+ 'Disengaged',
61
+ 'AdsQuery',
62
+ 'SemanticSerp',
63
+ 'GenerateContentQuery',
64
+ 'SearchQuery',
65
+ 'ActionRequest',
66
+ 'Context',
67
+ 'Progress',
68
+ 'AdsQuery',
69
+ 'SemanticSerp'
 
 
 
 
 
 
 
 
 
 
 
70
  ]
71
 
72
+ sliceIds = [
73
+
74
+ # "222dtappid",
75
+ # "225cricinfo",
76
+ # "224locals0"
77
+
78
+ 'winmuid3tf',
79
+ 'osbsdusgreccf',
80
+ 'ttstmout',
81
+ 'crchatrev',
82
+ 'winlongmsgtf',
83
+ 'ctrlworkpay',
84
+ 'norespwtf',
85
+ 'tempcacheread',
86
+ 'temptacache',
87
+ '505scss0',
88
+ '508jbcars0',
89
+ '515enbotdets0',
90
+ '5082tsports',
91
+ '515vaoprvs',
92
+ '424dagslnv1s0',
93
+ 'kcimgattcf',
94
+ '427startpms0'
95
+ ]
96
 
97
+ location = {
98
+ 'locale': 'en-US',
99
+ 'market': 'en-US',
100
+ 'region': 'US',
101
+ 'locationHints': [
102
+ {
103
+ 'country': 'United States',
104
+ 'state': 'California',
105
+ 'city': 'Los Angeles',
106
+ 'timezoneoffset': 8,
107
+ 'countryConfidence': 8,
108
+ 'Center': {
109
+ 'Latitude': 34.0536909,
110
+ 'Longitude': -118.242766
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
111
  },
112
+ 'RegionType': 2,
113
+ 'SourceType': 1
114
+ }
115
+ ],
116
+ }
117
+
118
+
119
+ def _format(msg: dict) -> str:
120
+ return json.dumps(msg, ensure_ascii=False) + Defaults.delimiter
121
+
122
+
123
+ async def create_conversation():
124
+ for _ in range(5):
125
+ create = requests.get('https://www.bing.com/turing/conversation/create',
126
+ headers={
127
+ 'authority': 'edgeservices.bing.com',
128
+ 'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7',
129
+ 'accept-language': 'en-US,en;q=0.9',
130
+ 'cache-control': 'max-age=0',
131
+ 'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
132
+ 'sec-ch-ua-arch': '"x86"',
133
+ 'sec-ch-ua-bitness': '"64"',
134
+ 'sec-ch-ua-full-version': '"110.0.1587.69"',
135
+ 'sec-ch-ua-full-version-list': '"Chromium";v="110.0.5481.192", "Not A(Brand";v="24.0.0.0", "Microsoft Edge";v="110.0.1587.69"',
136
+ 'sec-ch-ua-mobile': '?0',
137
+ 'sec-ch-ua-model': '""',
138
+ 'sec-ch-ua-platform': '"Windows"',
139
+ 'sec-ch-ua-platform-version': '"15.0.0"',
140
+ 'sec-fetch-dest': 'document',
141
+ 'sec-fetch-mode': 'navigate',
142
+ 'sec-fetch-site': 'none',
143
+ 'sec-fetch-user': '?1',
144
+ 'upgrade-insecure-requests': '1',
145
+ 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/110.0.0.0 Safari/537.36 Edg/110.0.1587.69',
146
+ 'x-edge-shopping-flag': '1',
147
+ 'x-forwarded-for': Defaults.ip_address
148
+ })
149
+
150
+ conversationId = create.json().get('conversationId')
151
+ clientId = create.json().get('clientId')
152
+ conversationSignature = create.json().get('conversationSignature')
153
+
154
+ if not conversationId or not clientId or not conversationSignature and _ == 4:
155
+ raise Exception('Failed to create conversation.')
156
+
157
+ return conversationId, clientId, conversationSignature
158
+
159
+
160
+ async def stream_generate(prompt: str, mode: optionsSets.optionSet = optionsSets.jailbreak, context: bool or str = False):
161
+ timeout = aiohttp.ClientTimeout(total=900)
162
+ session = aiohttp.ClientSession(timeout=timeout)
163
+
164
+ conversationId, clientId, conversationSignature = await create_conversation()
165
+
166
+ wss = await session.ws_connect('wss://sydney.bing.com/sydney/ChatHub', ssl=ssl_context, autoping=False,
167
+ headers={
168
+ 'accept': 'application/json',
169
+ 'accept-language': 'en-US,en;q=0.9',
170
+ 'content-type': 'application/json',
171
+ 'sec-ch-ua': '"Not_A Brand";v="99", "Microsoft Edge";v="110", "Chromium";v="110"',
172
+ 'sec-ch-ua-arch': '"x86"',
173
+ 'sec-ch-ua-bitness': '"64"',
174
+ 'sec-ch-ua-full-version': '"109.0.1518.78"',
175
+ 'sec-ch-ua-full-version-list': '"Chromium";v="110.0.5481.192", "Not A(Brand";v="24.0.0.0", "Microsoft Edge";v="110.0.1587.69"',
176
+ 'sec-ch-ua-mobile': '?0',
177
+ 'sec-ch-ua-model': '',
178
+ 'sec-ch-ua-platform': '"Windows"',
179
+ 'sec-ch-ua-platform-version': '"15.0.0"',
180
+ 'sec-fetch-dest': 'empty',
181
+ 'sec-fetch-mode': 'cors',
182
+ 'sec-fetch-site': 'same-origin',
183
+ 'x-ms-client-request-id': str(uuid.uuid4()),
184
+ 'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/Win32',
185
+ 'Referer': 'https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx',
186
+ 'Referrer-Policy': 'origin-when-cross-origin',
187
+ 'x-forwarded-for': Defaults.ip_address
188
+ })
189
+
190
+ await wss.send_str(_format({'protocol': 'json', 'version': 1}))
191
+ await wss.receive(timeout=900)
192
+
193
+ struct = {
194
+ 'arguments': [
195
+ {
196
+ **mode,
197
+ 'source': 'cib',
198
+ 'allowedMessageTypes': Defaults.allowedMessageTypes,
199
+ 'sliceIds': Defaults.sliceIds,
200
+ 'traceId': os.urandom(16).hex(),
201
+ 'isStartOfSession': True,
202
+ 'message': Defaults.location | {
203
+ 'author': 'user',
204
+ 'inputMethod': 'Keyboard',
205
+ 'text': prompt,
206
+ 'messageType': 'Chat'
207
  },
208
+ 'conversationSignature': conversationSignature,
209
+ 'participant': {
210
+ 'id': clientId
211
+ },
212
+ 'conversationId': conversationId
213
+ }
214
+ ],
215
+ 'invocationId': '0',
216
+ 'target': 'chat',
217
+ 'type': 4
218
+ }
219
+
220
+ if context:
221
+ struct['arguments'][0]['previousMessages'] = [
222
+ {
223
+ "author": "user",
224
+ "description": context,
225
+ "contextType": "WebPage",
226
+ "messageType": "Context",
227
+ "messageId": "discover-web--page-ping-mriduna-----"
228
+ }
229
+ ]
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
230
 
231
+ await wss.send_str(_format(struct))
232
 
233
+ final = False
234
+ draw = False
235
+ resp_txt = ''
236
+ result_text = ''
237
+ resp_txt_no_link = ''
238
+ cache_text = ''
239
 
240
+ while not final:
241
+ msg = await wss.receive(timeout=900)
242
+ objects = msg.data.split(Defaults.delimiter)
243
 
244
+ for obj in objects:
245
+ if obj is None or not obj:
246
+ continue
247
 
248
+ response = json.loads(obj)
249
+ if response.get('type') == 1 and response['arguments'][0].get('messages',):
250
+ if not draw:
251
+ if (response['arguments'][0]['messages'][0]['contentOrigin'] != 'Apology') and not draw:
252
+ resp_txt = result_text + \
253
+ response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0].get(
254
+ 'text', '')
255
+ resp_txt_no_link = result_text + \
256
+ response['arguments'][0]['messages'][0].get(
257
+ 'text', '')
258
+
259
+ if response['arguments'][0]['messages'][0].get('messageType',):
260
+ resp_txt = (
261
+ resp_txt
262
+ + response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0]['inlines'][0].get('text')
263
+ + '\n'
264
+ )
265
+ result_text = (
266
+ result_text
267
+ + response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0]['inlines'][0].get('text')
268
+ + '\n'
269
+ )
270
+
271
+ if cache_text.endswith(' '):
272
+ final = True
273
+ if wss and not wss.closed:
274
+ await wss.close()
275
+ if session and not session.closed:
276
+ await session.close()
277
+
278
+ yield (resp_txt.replace(cache_text, ''))
279
+ cache_text = resp_txt
280
+
281
+ elif response.get('type') == 2:
282
+ if response['item']['result'].get('error'):
283
+ if wss and not wss.closed:
284
+ await wss.close()
285
+ if session and not session.closed:
286
+ await session.close()
287
+
288
+ raise Exception(
289
+ f"{response['item']['result']['value']}: {response['item']['result']['message']}")
290
+
291
+ if draw:
292
+ cache = response['item']['messages'][1]['adaptiveCards'][0]['body'][0]['text']
293
+ response['item']['messages'][1]['adaptiveCards'][0]['body'][0]['text'] = (
294
+ cache + resp_txt)
295
+
296
+ if (response['item']['messages'][-1]['contentOrigin'] == 'Apology' and resp_txt):
297
+ response['item']['messages'][-1]['text'] = resp_txt_no_link
298
+ response['item']['messages'][-1]['adaptiveCards'][0]['body'][0]['text'] = resp_txt
299
+
300
+ # print('Preserved the message from being deleted', file=sys.stderr)
301
+
302
+ final = True
303
+ if wss and not wss.closed:
304
+ await wss.close()
305
+ if session and not session.closed:
306
+ await session.close()
307
+
308
+
309
+ def run(generator):
310
+ loop = asyncio.get_event_loop()
311
+ gen = generator.__aiter__()
312
 
313
  while True:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
314
  try:
315
+ next_val = loop.run_until_complete(gen.__anext__())
316
+ yield next_val
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
317
 
318
+ except StopAsyncIteration:
319
+ break
320
 
321
+ #print('Done')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
322
 
 
 
 
 
323
 
324
+ def convert(messages):
325
+ context = ""
 
 
 
 
 
 
 
 
 
 
326
 
327
+ for message in messages:
328
+ context += "[%s](#message)\n%s\n\n" % (message['role'],
329
+ message['content'])
 
 
 
330
 
331
+ return context
 
 
 
 
 
 
 
 
 
 
 
 
332
 
 
 
333
 
334
+ def _create_completion(model: str, messages: list, stream: bool, **kwargs):
335
+ if len(messages) < 2:
336
+ prompt = messages[0]['content']
337
+ context = False
338
 
339
+ else:
340
+ prompt = messages[-1]['content']
341
+ context = convert(messages[:-1])
342
 
343
+ response = run(stream_generate(prompt, optionsSets.jailbreak, context))
344
+ for token in response:
345
+ yield (token)
 
346
 
347
+ #print('Done')
 
348
 
349
 
350
+ params = f'g4f.Providers.{os.path.basename(__file__)[:-3]} supports: ' + \
351
+ '(%s)' % ', '.join(
352
+ [f"{name}: {get_type_hints(_create_completion)[name].__name__}" for name in _create_completion.__code__.co_varnames[:_create_completion.__code__.co_argcount]])