diff --git a/README.md b/README.md index a71c008..12ee066 100644 --- a/README.md +++ b/README.md @@ -1,17 +1,17 @@ # Sydney.py -[![Latest Release](https://img.shields.io/github/v/release/vsakkas/sydney.py.svg)](https://github.com/vsakkas/sydney.py/releases/tag/v0.17.5) +[![Latest Release](https://img.shields.io/github/v/release/vsakkas/sydney.py.svg)](https://github.com/vsakkas/sydney.py/releases/tag/v0.17.6) [![Python](https://img.shields.io/badge/python-3.9+-blue.svg)](https://www.python.org/downloads/) [![MIT License](https://img.shields.io/badge/license-MIT-blue)](https://github.com/vsakkas/sydney.py/blob/master/LICENSE) -Python Client for Bing Chat, also known as Sydney. +Python Client for Copilot (formerly named Bing Chat), also known as Sydney. > **Note** > This is an **unofficial** client. ## Features -- Connect to Bing Chat, Microsoft's AI-powered personal assistant. +- Connect to Copilot, Microsoft's AI-powered personal assistant. - Ask questions and have a conversation in various conversation styles. - Compose content in various formats and tones. - Stream response tokens for real-time communication. @@ -22,7 +22,7 @@ Python Client for Bing Chat, also known as Sydney. ## Requirements - Python 3.9 or newer -- Microsoft account with access to [Bing Chat](https://bing.com/chat) *(optional)* +- Microsoft account with access to [Copilot](https://copilot.microsoft.com/) *(optional)* ## Installation @@ -39,19 +39,19 @@ poetry add sydney-py ``` > **Note** -> Make sure you're using the latest version of Sydney.py to ensure best compatibility with Bing Chat. +> Make sure you're using the latest version of Sydney.py to ensure best compatibility with Copilot. ## Usage ### Prerequisites -To use Sydney.py you first need to extract the `_U` cookie from the Bing Chat sidebar. The `_U` cookie is used to authenticate your requests to the Bing Chat API. +To use Sydney.py you first need to extract the `_U` cookie from the Copilot web page. The `_U` cookie is used to authenticate your requests to the Copilot API. To get the `_U` cookie, follow these steps on Microsoft Edge: -- Open the Bing Chat side bar by clicking the top right Bing button. +- Go to the [Copilot web page](https://copilot.microsoft.com/). - Write a message on the chat dialog that appears. - Open the developer tools in your browser (usually by pressing `F12` or right-clicking on the chat dialog and selecting `Inspect`). -- Select the `Application` tab and click on the `Cookies` option to view all cookies associated with `https://edgeservices.bing.com`. +- Select the `Application` tab and click on the `Cookies` option to view all cookies associated with `https://www.bing.com`. - Look for the `_U` cookie and click on it to expand its details. - Copy the value of the `_U` cookie (it should look like a long string of letters and numbers). @@ -70,9 +70,12 @@ os.environ["BING_U_COOKIE"] = "" > **Note** > In some regions, using the `_U` cookie is not required, in which case the above instructions can be skipped. +> **Note** +> For regions where a cookie is required, it is recommended to manually write messages to Copilot until a message box containing a `Verifying` message, which will then switch to `Success!` Without this step, it is possible that Sydney.py will fail with a `CaptchaChallenge` error. + ### Example -You can use Sydney.py to easily create a CLI client for Bing Chat: +You can use Sydney.py to easily create a CLI client for Copilot: ```python import asyncio @@ -103,7 +106,7 @@ if __name__ == "__main__": ### Sydney Client -You can create a Sydney Client and initialize a connection with Bing Chat which starts a conversation: +You can create a Sydney Client and initialize a connection with Copilot which starts a conversation: ```python sydney = SydneyClient() @@ -144,7 +147,7 @@ async with SydneyClient() as sydney: ### Ask -You can ask Bing Chat questions and (optionally) include citations in the results: +You can ask Copilot questions and (optionally) include citations in the results: ```python async with SydneyClient() as sydney: @@ -186,7 +189,7 @@ async with SydneyClient() as sydney: ### Compose -You can ask Bing Chat to compose different types of content, such emails, articles, ideas and more: +You can ask Copilot to compose different types of content, such emails, articles, ideas and more: ```python async with SydneyClient() as sydney: @@ -226,7 +229,7 @@ Both versions of the `compose` method support the same parameters. ### Suggested Responses -You can also receive the suggested user responses as generated by Bing Chat along with the text answer. Both `ask`, `ask_stream` support this feature: +You can also receive the suggested user responses as generated by Copilot along with the text answer. Both `ask`, `ask_stream` support this feature: ```python async with SydneyClient() as sydney: @@ -275,7 +278,7 @@ async with SydneyClient() as sydney: ### Raw Response -You can also receive the raw JSON response that comes from Bing Chat instead of a text answer. Both `ask` and `compose` support this feature: +You can also receive the raw JSON response that comes from Copilot instead of a text answer. Both `ask` and `compose` support this feature: ```python async with SydneyClient() as sydney: @@ -299,9 +302,9 @@ When something goes wrong, Sydney.py might throw one of the following exceptions | Exception | Meaning | Solution | |-------------------------------|-------------------------------------------|-------------------------| -| `NoConnectionException` | No connection to Bing Chat was found | Retry | -| `ConnectionTimeoutException` | Attempt to connect to Bing Chat timed out | Retry | -| `NoResponseException` | No response was returned from Bing Chat | Retry or use new cookie | +| `NoConnectionException` | No connection to Copilot was found | Retry | +| `ConnectionTimeoutException` | Attempt to connect to Copilot timed out | Retry | +| `NoResponseException` | No response was returned from Copilot | Retry or use new cookie | | `ThrottledRequestException` | Request is throttled | Wait and retry | | `CaptchaChallengeException` | Captcha challenge must be solved | Use new cookie | | `ConversationLimitException` | Reached conversation limit of N messages | Start new conversation | diff --git a/images/logo.svg b/images/logo.svg index 5780b65..53990f0 100644 --- a/images/logo.svg +++ b/images/logo.svg @@ -1,65 +1,40 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/pyproject.toml b/pyproject.toml index dc9a2c2..bace951 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [tool.poetry] name = "sydney-py" -version = "0.17.5" +version = "0.17.6" description = "Python Client for Bing Chat, also known as Sydney." authors = ["vsakkas "] license = "MIT" diff --git a/sydney/constants.py b/sydney/constants.py index 63f669a..50e8539 100644 --- a/sydney/constants.py +++ b/sydney/constants.py @@ -23,7 +23,7 @@ "User-Agent": USER_AGENT, } -BUNDLE_VERSION = "1.1326.5" +BUNDLE_VERSION = "1.1342.3-cplt.7" BING_CREATE_CONVERSATION_URL = ( f"https://www.bing.com/turing/conversation/create?bundleVersion={BUNDLE_VERSION}" diff --git a/sydney/enums.py b/sydney/enums.py index 2d5c28d..eea50a2 100644 --- a/sydney/enums.py +++ b/sydney/enums.py @@ -3,7 +3,7 @@ class ConversationStyle(Enum): """ - Bing Chat conversation styles. Supported options are: + Copilot conversation styles. Supported options are: - `creative` for original and imaginative chat - `balanced` for informative and friendly chat - `precise` for concise and straightforward chat @@ -16,7 +16,7 @@ class ConversationStyle(Enum): class ConversationStyleOptionSets(Enum): """ - Bing Chat conversation styles. Supported options are: + Copilot conversation styles. Supported options are: - `creative` for original and imaginative chat - `balanced` for informative and friendly chat - `precise` for concise and straightforward chat @@ -36,7 +36,7 @@ class ConversationHistoryOptionsSets(Enum): class DefaultOptions(Enum): """ - Options that are used in all API requests to Bing Chat. + Options that are used in all API requests to Copilot. """ NLU_DIRECT_RESPONSE_FILTER = "nlu_direct_response_filter" @@ -53,7 +53,7 @@ class DefaultOptions(Enum): class DefaultComposeOptions(Enum): """ - Options that are used in all compose API requests to Bing Chat. + Options that are used in all compose API requests to Copilot. """ NLU_DIRECT_RESPONSE_FILTER = "nlu_direct_response_filter" @@ -69,7 +69,7 @@ class DefaultComposeOptions(Enum): class CookieOptions(Enum): """ Options that are used only when the user is logged in - and using cookies to use in requests to Bing Chat. + and using cookies to use in requests to Copilot. """ AUTOSAVE = "autosave" @@ -77,7 +77,7 @@ class CookieOptions(Enum): class ComposeTone(Enum): """ - Bing Chat compose tones. Supported options are: + Copilot compose tones. Supported options are: - `professional` for formal conversations in a professional setting - `casual` for informal conversations between friends or family members - `enthusiastic` for conversations where the writer wants to convey excitement or passion @@ -94,7 +94,7 @@ class ComposeTone(Enum): class ComposeFormat(Enum): """ - Bing Chat compose formats. Supported options are: + Copilot compose formats. Supported options are: - `paragraph` for longer messages that are composed of multiple sentences or paragraphs - `email` for messages that are structured like emails, with a clear subject line and formal greeting and closing - `blogpost` for messages that are structured like blog posts, with clear headings and subheadings and a more informal tone @@ -109,7 +109,7 @@ class ComposeFormat(Enum): class ComposeLength(Enum): """ - Bing Chat compose lengths. Supported options are: + Copilot compose lengths. Supported options are: - `short` for messages that are only a few words or sentences long - `medium` for messages that are a few paragraphs long - `long` for messages that are several paragraphs or pages long @@ -122,7 +122,7 @@ class ComposeLength(Enum): class CustomComposeTone: """ - Class to represent custom Bing Chat compose tones. + Class to represent custom Copilot compose tones. """ def __init__(self, value) -> None: @@ -154,7 +154,7 @@ class MessageType(Enum): class ResultValue(Enum): """ - Bing Chat result values on raw responses. Supported options are: + Copilot result values on raw responses. Supported options are: - `Success` - `Throttled` - `CaptchaChallenge` diff --git a/sydney/sydney.py b/sydney/sydney.py index cae4e46..71bf08d 100644 --- a/sydney/sydney.py +++ b/sydney/sydney.py @@ -56,18 +56,18 @@ def __init__( use_proxy: bool = False, ) -> None: """ - Client for Bing Chat. + Client for Copilot (formerly named Bing Chat), also known as Sydney. Parameters ---------- style : str - The conversation style that Bing Chat will adopt. Must be one of the options listed + The conversation style that Copilot will adopt. Must be one of the options listed in the `ConversationStyle` enum. Default is "balanced". bing_u_cookie: str | None - The _U cookie from Bing required to connect and use Bing Chat. If not provided, + The _U cookie from Bing required to connect and use Copilot. If not provided, the `BING_U_COOKIE` environment variable is loaded instead. Default is None. use_proxy: str | None - Flag to determine if an HTTP proxy will be used to start a conversation with Bing Chat. If set to True, + Flag to determine if an HTTP proxy will be used to start a conversation with Copilot. If set to True, the `HTTP_PROXY` and `HTTPS_PROXY` environment variables must be set to the address of the proxy to be used. If not provided, no proxy will be used. Default is False. """ @@ -244,7 +244,7 @@ def _build_upload_arguments(self, attachment: str) -> str: async def _upload_attachment(self, attachment: str) -> dict: """ - Upload an image to Bing Chat. + Upload an image to Copilot. Parameters ---------- @@ -254,8 +254,8 @@ async def _upload_attachment(self, attachment: str) -> dict: Returns ------- dict - The response from Bing Chat. "blobId" and "processedBlobId" are parameters that can be passed - to https://www.bing.com/images/blob?bcid=[ID] and can obtain the uploaded image from Bing Chat. + The response from Copilot. "blobId" and "processedBlobId" are parameters that can be passed + to https://www.bing.com/images/blob?bcid=[ID] and can obtain the uploaded image from Copilot. """ cookies = {"_U": self.bing_u_cookie} if self.bing_u_cookie else {} @@ -279,12 +279,12 @@ async def _upload_attachment(self, attachment: str) -> dict: response_dict = await response.json() if not response_dict["blobId"]: raise ImageUploadException( - f"Failed to upload image, Bing Chat rejected uploading it" + f"Failed to upload image, Copilot rejected uploading it" ) if len(response_dict["blobId"]) == 0: raise ImageUploadException( - f"Failed to upload image, received empty image info from Bing Chat" + f"Failed to upload image, received empty image info from Copilot" ) await session.close() @@ -310,20 +310,20 @@ async def _ask( or self.client_id is None or self.invocation_id is None ): - raise NoConnectionException("No connection to Bing Chat was found") + raise NoConnectionException("No connection to Copilot was found") bing_chathub_url = BING_CHATHUB_URL if self.encrypted_conversation_signature: bing_chathub_url += f"?sec_access_token={urllib.parse.quote(self.encrypted_conversation_signature)}" - # Create a websocket connection with Bing Chat for sending and receiving messages. + # Create a websocket connection with Copilot for sending and receiving messages. try: self.wss_client = await websockets.connect( bing_chathub_url, extra_headers=CHAT_HEADERS, max_size=None ) except TimeoutError: raise ConnectionTimeoutException( - "Failed to connect to Bing Chat, connection timed out" + "Failed to connect to Copilot, connection timed out" ) from None await self.wss_client.send(as_json({"protocol": "json", "version": 1})) await self.wss_client.recv() @@ -418,7 +418,7 @@ async def _ask( async def start_conversation(self) -> None: """ - Connect to Bing Chat and create a new conversation. + Connect to Copilot and create a new conversation. """ session = await self._get_session(force_close=True) @@ -454,12 +454,12 @@ async def ask( raw: bool = False, ) -> str | dict | tuple[str | dict, list | None]: """ - Send a prompt to Bing Chat using the current conversation and return the answer. + Send a prompt to Copilot using the current conversation and return the answer. Parameters ---------- prompt : str - The prompt that needs to be sent to Bing Chat. + The prompt that needs to be sent to Copilot. attachment : str The URL to an image to be included with the prompt. context: str @@ -474,7 +474,7 @@ async def ask( Returns ------- str | dict | tuple - The text response from Bing Chat. If citations is True, the function returns the cited text. + The text response from Copilot. If citations is True, the function returns the cited text. If raw is True, the function returns the entire response object in raw JSON format. If suggestions is True, the function returns a list with the suggested responses. """ @@ -505,15 +505,15 @@ async def ask_stream( raw: bool = False, ) -> AsyncGenerator[str | dict | tuple[str | dict, list | None], None]: """ - Send a prompt to Bing Chat using the current conversation and stream the answer. + Send a prompt to Copilot using the current conversation and stream the answer. - By default, Bing Chat returns all previous tokens along with new ones. When using this + By default, Copilot returns all previous tokens along with new ones. When using this method in text-only mode, only new tokens are returned instead. Parameters ---------- prompt : str - The prompt that needs to be sent to Bing Chat. + The prompt that needs to be sent to Copilot. attachment : str The URL to an image to be included with the prompt. context: str @@ -528,7 +528,7 @@ async def ask_stream( Returns ------- str | dict | tuple - The text response from Bing Chat. If citations is True, the function returns the cited text. + The text response from Copilot. If citations is True, the function returns the cited text. If raw is True, the function returns the entire response object in raw JSON format. If suggestions is True, the function returns a list with the suggested responses. Only the final yielded result contains the suggested responses. @@ -565,13 +565,13 @@ async def compose( raw: bool = False, ) -> str | dict | tuple[str | dict, list | None]: """ - Send a prompt to Bing Chat and compose text based on the given prompt, tone, + Send a prompt to Copilot and compose text based on the given prompt, tone, format, and length. Parameters ---------- prompt : str - The prompt that needs to be sent to Bing Chat. + The prompt that needs to be sent to Copilot. tone : str, optional The tone of the response. Must be one of the options listed in the `ComposeTone` enum. Default is "professional". @@ -589,7 +589,7 @@ async def compose( Returns ------- str or dict - The response from Bing Chat. If raw is True, the function returns the entire response + The response from Copilot. If raw is True, the function returns the entire response object in raw JSON format. """ # Get the enum values corresponding to the given tone, format, and length. @@ -627,16 +627,16 @@ async def compose_stream( raw: bool = False, ) -> AsyncGenerator[str | dict | tuple[str | dict, list | None], None]: """ - Send a prompt to Bing Chat, compose and stream text based on the given prompt, tone, + Send a prompt to Copilot, compose and stream text based on the given prompt, tone, format, and length. - By default, Bing Chat returns all previous tokens along with new ones. When using this + By default, Copilot returns all previous tokens along with new ones. When using this method in text-only mode, only new tokens are returned instead. Parameters ---------- prompt : str - The prompt that needs to be sent to Bing Chat. + The prompt that needs to be sent to Copilot. tone : str, optional The tone of the response. Must be one of the options listed in the `ComposeTone` enum. Default is "professional". @@ -654,7 +654,7 @@ async def compose_stream( Returns ------- str or dict - The response from Bing Chat. If raw is True, the function returns the entire response + The response from Copilot. If raw is True, the function returns the entire response object in raw JSON format. """ # Get the enum values corresponding to the given tone, format, and length. @@ -694,7 +694,7 @@ async def reset_conversation(self, style: str | None = None) -> None: Parameters ---------- style : str - The conversation style that Bing Chat will adopt. Supported options are: + The conversation style that Copilot will adopt. Supported options are: - `creative` for original and imaginative chat - `balanced` for informative and friendly chat - `precise` for concise and straightforward chat @@ -711,7 +711,7 @@ async def reset_conversation(self, style: str | None = None) -> None: async def close_conversation(self) -> None: """ - Close all connections to Bing Chat. Clear conversation information. + Close all connections to Copilot. Clear conversation information. """ if self.wss_client and not self.wss_client.closed: await self.wss_client.close()