diff options
Diffstat (limited to 'g4f/Provider/Bing.py')
-rw-r--r-- | g4f/Provider/Bing.py | 143 |
1 files changed, 80 insertions, 63 deletions
diff --git a/g4f/Provider/Bing.py b/g4f/Provider/Bing.py index 05be27e7..f4275a5f 100644 --- a/g4f/Provider/Bing.py +++ b/g4f/Provider/Bing.py @@ -1,12 +1,28 @@ from __future__ import annotations import random +import uuid import json import os +import uuid +import urllib.parse from aiohttp import ClientSession, ClientTimeout from ..typing import AsyncGenerator -from .base_provider import AsyncGeneratorProvider, get_cookies +from .base_provider import AsyncGeneratorProvider +class Tones(): + creative = "Creative" + balanced = "Balanced" + precise = "Precise" + +default_cookies = { + 'SRCHD' : 'AF=NOFORM', + 'PPLState' : '1', + 'KievRPSSecAuth': '', + 'SUID' : '', + 'SRCHUSR' : '', + 'SRCHHPGUSR' : '', +} class Bing(AsyncGeneratorProvider): url = "https://bing.com/chat" @@ -15,12 +31,12 @@ class Bing(AsyncGeneratorProvider): @staticmethod def create_async_generator( - model: str, - messages: list[dict[str, str]], - cookies: dict = None, **kwargs) -> AsyncGenerator: - - if not cookies: - cookies = get_cookies(".bing.com") + model: str, + messages: list[dict[str, str]], + cookies: dict = None, + tone: str = Tones.creative, + **kwargs + ) -> AsyncGenerator: if len(messages) < 2: prompt = messages[0]["content"] context = None @@ -29,15 +45,8 @@ class Bing(AsyncGeneratorProvider): context = create_context(messages[:-1]) if not cookies or "SRCHD" not in cookies: - cookies = { - 'SRCHD' : 'AF=NOFORM', - 'PPLState' : '1', - 'KievRPSSecAuth': '', - 'SUID' : '', - 'SRCHUSR' : '', - 'SRCHHPGUSR' : '', - } - return stream_generate(prompt, context, cookies) + cookies = default_cookies + return stream_generate(prompt, tone, context, cookies) def create_context(messages: list[dict[str, str]]): context = "".join(f"[{message['role']}](#message)\n{message['content']}\n\n" for message in messages) @@ -51,12 +60,14 @@ class Conversation(): self.conversationSignature = conversationSignature async def create_conversation(session: ClientSession) -> Conversation: - url = 'https://www.bing.com/turing/conversation/create' + url = 'https://www.bing.com/turing/conversation/create?bundleVersion=1.1150.3' + async with await session.get(url) as response: - response = await response.json() - conversationId = response.get('conversationId') - clientId = response.get('clientId') - conversationSignature = response.get('conversationSignature') + data = await response.json() + + conversationId = data.get('conversationId') + clientId = data.get('clientId') + conversationSignature = response.headers.get('X-Sydney-Encryptedconversationsignature') if not conversationId or not clientId or not conversationSignature: raise Exception('Failed to create conversation.') @@ -161,53 +172,56 @@ class Defaults: 'x-forwarded-for': ip_address, } - optionsSets = { - "optionsSets": [ - 'saharasugg', - 'enablenewsfc', - 'clgalileo', - 'gencontentv3', - "nlu_direct_response_filter", - "deepleo", - "disable_emoji_spoken_text", - "responsible_ai_policy_235", - "enablemm", - "h3precise" - "dtappid", - "cricinfo", - "cricinfov2", - "dv3sugg", - "nojbfedge" - ] - } + optionsSets = [ + 'saharasugg', + 'enablenewsfc', + 'clgalileo', + 'gencontentv3', + "nlu_direct_response_filter", + "deepleo", + "disable_emoji_spoken_text", + "responsible_ai_policy_235", + "enablemm", + "h3precise" + "dtappid", + "cricinfo", + "cricinfov2", + "dv3sugg", + "nojbfedge" + ] def format_message(msg: dict) -> str: return json.dumps(msg, ensure_ascii=False) + Defaults.delimiter -def create_message(conversation: Conversation, prompt: str, context: str=None) -> str: +def create_message(conversation: Conversation, prompt: str, tone: str, context: str=None) -> str: + request_id = str(uuid.uuid4()) struct = { 'arguments': [ { - **Defaults.optionsSets, 'source': 'cib', + 'optionsSets': Defaults.optionsSets, 'allowedMessageTypes': Defaults.allowedMessageTypes, 'sliceIds': Defaults.sliceIds, 'traceId': os.urandom(16).hex(), 'isStartOfSession': True, + 'requestId': request_id, 'message': Defaults.location | { 'author': 'user', 'inputMethod': 'Keyboard', 'text': prompt, - 'messageType': 'Chat' + 'messageType': 'Chat', + 'requestId': request_id, + 'messageId': request_id, }, - 'conversationSignature': conversation.conversationSignature, + 'tone': tone, + 'spokenTextMode': 'None', + 'conversationId': conversation.conversationId, 'participant': { 'id': conversation.clientId }, - 'conversationId': conversation.conversationId } ], - 'invocationId': '0', + 'invocationId': '1', 'target': 'chat', 'type': 4 } @@ -224,8 +238,9 @@ def create_message(conversation: Conversation, prompt: str, context: str=None) - async def stream_generate( prompt: str, + tone: str, context: str=None, - cookies: dict=None + cookies: dict=None, ): async with ClientSession( timeout=ClientTimeout(total=900), @@ -235,17 +250,16 @@ async def stream_generate( conversation = await create_conversation(session) try: async with session.ws_connect( - 'wss://sydney.bing.com/sydney/ChatHub', + f'wss://sydney.bing.com/sydney/ChatHub', autoping=False, + params={'sec_access_token': conversation.conversationSignature} ) as wss: await wss.send_str(format_message({'protocol': 'json', 'version': 1})) - msg = await wss.receive(timeout=900) - - await wss.send_str(create_message(conversation, prompt, context)) + await wss.receive(timeout=900) + await wss.send_str(create_message(conversation, prompt, tone, context)) response_txt = '' - result_text = '' returned_text = '' final = False @@ -255,19 +269,23 @@ async def stream_generate( 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'): message = response['arguments'][0]['messages'][0] if (message['contentOrigin'] != 'Apology'): - response_txt = result_text + \ - message['adaptiveCards'][0]['body'][0].get('text', '') - - if message.get('messageType'): - inline_txt = message['adaptiveCards'][0]['body'][0]['inlines'][0].get('text') - response_txt += inline_txt + '\n' - result_text += inline_txt + '\n' - + if 'adaptiveCards' in message: + card = message['adaptiveCards'][0]['body'][0] + if "text" in card: + response_txt = card.get('text') + if message.get('messageType'): + inline_txt = card['inlines'][0].get('text') + response_txt += inline_txt + '\n' + elif message.get('contentType') == "IMAGE": + query = urllib.parse.quote(message.get('text')) + url = f"\nhttps://www.bing.com/images/create?q={query}" + response_txt += url + final = True if response_txt.startswith(returned_text): new = response_txt[len(returned_text):] if new != "\n": @@ -277,7 +295,6 @@ async def stream_generate( result = response['item']['result'] if result.get('error'): raise Exception(f"{result['value']}: {result['message']}") - final = True - break + return finally: await delete_conversation(session, conversation)
\ No newline at end of file |