summaryrefslogtreecommitdiffstats
path: root/g4f/Provider/Providers/Bing.py
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--g4f/Provider/Providers/Bing.py350
1 files changed, 350 insertions, 0 deletions
diff --git a/g4f/Provider/Providers/Bing.py b/g4f/Provider/Providers/Bing.py
new file mode 100644
index 00000000..1d33cda5
--- /dev/null
+++ b/g4f/Provider/Providers/Bing.py
@@ -0,0 +1,350 @@
+import os
+import json
+import random
+import json
+import os
+import uuid
+import ssl
+import certifi
+import aiohttp
+import asyncio
+
+import requests
+from ...typing import sha256, Dict, get_type_hints
+
+url = 'https://bing.com/chat'
+model = ['gpt-4']
+supports_stream = True
+needs_auth = False
+
+ssl_context = ssl.create_default_context()
+ssl_context.load_verify_locations(certifi.where())
+
+
+class optionsSets:
+ optionSet: dict = {
+ 'tone': str,
+ 'optionsSets': list
+ }
+
+ jailbreak: dict = {
+ "optionsSets": [
+ 'saharasugg',
+ 'enablenewsfc',
+ 'clgalileo',
+ 'gencontentv3',
+ "nlu_direct_response_filter",
+ "deepleo",
+ "disable_emoji_spoken_text",
+ "responsible_ai_policy_235",
+ "enablemm",
+ "h3precise"
+ # "harmonyv3",
+ "dtappid",
+ "cricinfo",
+ "cricinfov2",
+ "dv3sugg",
+ "nojbfedge"
+ ]
+ }
+
+
+class Defaults:
+ delimiter = '\x1e'
+ ip_address = f'13.{random.randint(104, 107)}.{random.randint(0, 255)}.{random.randint(0, 255)}'
+
+ allowedMessageTypes = [
+ 'Chat',
+ 'Disengaged',
+ 'AdsQuery',
+ 'SemanticSerp',
+ 'GenerateContentQuery',
+ 'SearchQuery',
+ 'ActionRequest',
+ 'Context',
+ 'Progress',
+ 'AdsQuery',
+ 'SemanticSerp'
+ ]
+
+ sliceIds = [
+
+ # "222dtappid",
+ # "225cricinfo",
+ # "224locals0"
+
+ 'winmuid3tf',
+ 'osbsdusgreccf',
+ 'ttstmout',
+ 'crchatrev',
+ 'winlongmsgtf',
+ 'ctrlworkpay',
+ 'norespwtf',
+ 'tempcacheread',
+ 'temptacache',
+ '505scss0',
+ '508jbcars0',
+ '515enbotdets0',
+ '5082tsports',
+ '515vaoprvs',
+ '424dagslnv1s0',
+ 'kcimgattcf',
+ '427startpms0'
+ ]
+
+ location = {
+ 'locale': 'en-US',
+ 'market': 'en-US',
+ 'region': 'US',
+ 'locationHints': [
+ {
+ 'country': 'United States',
+ 'state': 'California',
+ 'city': 'Los Angeles',
+ 'timezoneoffset': 8,
+ 'countryConfidence': 8,
+ 'Center': {
+ 'Latitude': 34.0536909,
+ 'Longitude': -118.242766
+ },
+ 'RegionType': 2,
+ 'SourceType': 1
+ }
+ ],
+ }
+
+
+def _format(msg: dict) -> str:
+ return json.dumps(msg, ensure_ascii=False) + Defaults.delimiter
+
+
+async def create_conversation():
+ for _ in range(5):
+ create = requests.get('https://www.bing.com/turing/conversation/create',
+ headers={
+ 'authority': 'edgeservices.bing.com',
+ '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',
+ 'accept-language': 'en-US,en;q=0.9',
+ 'cache-control': 'max-age=0',
+ 'sec-ch-ua': '"Chromium";v="110", "Not A(Brand";v="24", "Microsoft Edge";v="110"',
+ 'sec-ch-ua-arch': '"x86"',
+ 'sec-ch-ua-bitness': '"64"',
+ 'sec-ch-ua-full-version': '"110.0.1587.69"',
+ '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"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-model': '""',
+ 'sec-ch-ua-platform': '"Windows"',
+ 'sec-ch-ua-platform-version': '"15.0.0"',
+ 'sec-fetch-dest': 'document',
+ 'sec-fetch-mode': 'navigate',
+ 'sec-fetch-site': 'none',
+ 'sec-fetch-user': '?1',
+ 'upgrade-insecure-requests': '1',
+ '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',
+ 'x-edge-shopping-flag': '1',
+ 'x-forwarded-for': Defaults.ip_address
+ })
+
+ conversationId = create.json().get('conversationId')
+ clientId = create.json().get('clientId')
+ conversationSignature = create.json().get('conversationSignature')
+
+ if not conversationId or not clientId or not conversationSignature and _ == 4:
+ raise Exception('Failed to create conversation.')
+
+ return conversationId, clientId, conversationSignature
+
+
+async def stream_generate(prompt: str, mode: optionsSets.optionSet = optionsSets.jailbreak, context: bool or str = False):
+ timeout = aiohttp.ClientTimeout(total=900)
+ session = aiohttp.ClientSession(timeout=timeout)
+
+ conversationId, clientId, conversationSignature = await create_conversation()
+
+ wss = await session.ws_connect('wss://sydney.bing.com/sydney/ChatHub', ssl=ssl_context, autoping=False,
+ headers={
+ 'accept': 'application/json',
+ 'accept-language': 'en-US,en;q=0.9',
+ 'content-type': 'application/json',
+ 'sec-ch-ua': '"Not_A Brand";v="99", "Microsoft Edge";v="110", "Chromium";v="110"',
+ 'sec-ch-ua-arch': '"x86"',
+ 'sec-ch-ua-bitness': '"64"',
+ 'sec-ch-ua-full-version': '"109.0.1518.78"',
+ '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"',
+ 'sec-ch-ua-mobile': '?0',
+ 'sec-ch-ua-model': '',
+ 'sec-ch-ua-platform': '"Windows"',
+ 'sec-ch-ua-platform-version': '"15.0.0"',
+ 'sec-fetch-dest': 'empty',
+ 'sec-fetch-mode': 'cors',
+ 'sec-fetch-site': 'same-origin',
+ 'x-ms-client-request-id': str(uuid.uuid4()),
+ 'x-ms-useragent': 'azsdk-js-api-client-factory/1.0.0-beta.1 core-rest-pipeline/1.10.0 OS/Win32',
+ 'Referer': 'https://www.bing.com/search?q=Bing+AI&showconv=1&FORM=hpcodx',
+ 'Referrer-Policy': 'origin-when-cross-origin',
+ 'x-forwarded-for': Defaults.ip_address
+ })
+
+ await wss.send_str(_format({'protocol': 'json', 'version': 1}))
+ await wss.receive(timeout=900)
+
+ struct = {
+ 'arguments': [
+ {
+ **mode,
+ 'source': 'cib',
+ 'allowedMessageTypes': Defaults.allowedMessageTypes,
+ 'sliceIds': Defaults.sliceIds,
+ 'traceId': os.urandom(16).hex(),
+ 'isStartOfSession': True,
+ 'message': Defaults.location | {
+ 'author': 'user',
+ 'inputMethod': 'Keyboard',
+ 'text': prompt,
+ 'messageType': 'Chat'
+ },
+ 'conversationSignature': conversationSignature,
+ 'participant': {
+ 'id': clientId
+ },
+ 'conversationId': conversationId
+ }
+ ],
+ 'invocationId': '0',
+ 'target': 'chat',
+ 'type': 4
+ }
+
+ if context:
+ struct['arguments'][0]['previousMessages'] = [
+ {
+ "author": "user",
+ "description": context,
+ "contextType": "WebPage",
+ "messageType": "Context",
+ "messageId": "discover-web--page-ping-mriduna-----"
+ }
+ ]
+
+ await wss.send_str(_format(struct))
+
+ final = False
+ draw = False
+ resp_txt = ''
+ result_text = ''
+ resp_txt_no_link = ''
+ cache_text = ''
+
+ while not final:
+ msg = await wss.receive(timeout=900)
+ objects = msg.data.split(Defaults.delimiter)
+
+ for obj in objects:
+ if obj is None or not obj:
+ continue
+
+ response = json.loads(obj)
+ if response.get('type') == 1 and response['arguments'][0].get('messages',):
+ if not draw:
+ if (response['arguments'][0]['messages'][0]['contentOrigin'] != 'Apology') and not draw:
+ resp_txt = result_text + \
+ response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0].get(
+ 'text', '')
+ resp_txt_no_link = result_text + \
+ response['arguments'][0]['messages'][0].get(
+ 'text', '')
+
+ if response['arguments'][0]['messages'][0].get('messageType',):
+ resp_txt = (
+ resp_txt
+ + response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0]['inlines'][0].get('text')
+ + '\n'
+ )
+ result_text = (
+ result_text
+ + response['arguments'][0]['messages'][0]['adaptiveCards'][0]['body'][0]['inlines'][0].get('text')
+ + '\n'
+ )
+
+ if cache_text.endswith(' '):
+ final = True
+ if wss and not wss.closed:
+ await wss.close()
+ if session and not session.closed:
+ await session.close()
+
+ yield (resp_txt.replace(cache_text, ''))
+ cache_text = resp_txt
+
+ elif response.get('type') == 2:
+ if response['item']['result'].get('error'):
+ if wss and not wss.closed:
+ await wss.close()
+ if session and not session.closed:
+ await session.close()
+
+ raise Exception(
+ f"{response['item']['result']['value']}: {response['item']['result']['message']}")
+
+ if draw:
+ cache = response['item']['messages'][1]['adaptiveCards'][0]['body'][0]['text']
+ response['item']['messages'][1]['adaptiveCards'][0]['body'][0]['text'] = (
+ cache + resp_txt)
+
+ if (response['item']['messages'][-1]['contentOrigin'] == 'Apology' and resp_txt):
+ response['item']['messages'][-1]['text'] = resp_txt_no_link
+ response['item']['messages'][-1]['adaptiveCards'][0]['body'][0]['text'] = resp_txt
+
+ # print('Preserved the message from being deleted', file=sys.stderr)
+
+ final = True
+ if wss and not wss.closed:
+ await wss.close()
+ if session and not session.closed:
+ await session.close()
+
+
+def run(generator):
+ loop = asyncio.get_event_loop()
+ gen = generator.__aiter__()
+
+ while True:
+ try:
+ next_val = loop.run_until_complete(gen.__anext__())
+ yield next_val
+
+ except StopAsyncIteration:
+ break
+
+ #print('Done')
+
+
+def convert(messages):
+ context = ""
+
+ for message in messages:
+ context += "[%s](#message)\n%s\n\n" % (message['role'],
+ message['content'])
+
+ return context
+
+
+def _create_completion(model: str, messages: list, stream: bool, **kwargs):
+ if len(messages) < 2:
+ prompt = messages[0]['content']
+ context = False
+
+ else:
+ prompt = messages[-1]['content']
+ context = convert(messages[:-1])
+
+ response = run(stream_generate(prompt, optionsSets.jailbreak, context))
+ for token in response:
+ yield (token)
+
+ #print('Done')
+
+
+params = f'g4f.Providers.{os.path.basename(__file__)[:-3]} supports: ' + \
+ '(%s)' % ', '.join(
+ [f"{name}: {get_type_hints(_create_completion)[name].__name__}" for name in _create_completion.__code__.co_varnames[:_create_completion.__code__.co_argcount]])