lss233 / chatgpt-mirai-qq-bot

🚀 一键部署!真正的 AI 聊天机器人!支持ChatGPT、文心一言、讯飞星火、Bing、Bard、ChatGLM、POE,多账号,人设调教,虚拟女仆、图片渲染、语音发送 | 支持 QQ、Telegram、Discord、微信 等平台
GNU Affero General Public License v3.0
12.53k stars 1.52k forks source link

[BUG] newbing返回的结果中包含web_search_results #1139

Open rookie2onion opened 11 months ago

rookie2onion commented 11 months ago

提交 issue 前,请先确认:

表现
newbing返回的结果中包含web_search_results的部分

运行环境:

复现步骤
正常使用newbing,询问一个会令其搜索的问题,就会在结果中出现web_search_results

一部分日志
[Bing AI 响应] {"web_search_results":[{"title":"苏联(存 在于1922-1991年的联邦制社会主义国家)_百度百科","snippets":["百度百科-验证","苏维埃社会主义共和国联盟(俄语:Союз Советских Социалистических Республик),简称“苏联”,是存在于1922—1991年的联邦制社会主义国家,由苏联共产党执政。其由15个权利平等的加盟共和国按照自愿联合的原则组成,领土涵盖东欧的大部分。"],"url":"https://baike.baidu.com/item/%e8%8b%8f%e8%81%94/199168"},{"title":"苏联 - 维基百科,自由的百科全书","snippets":["苏联 - 维基百科,自由的百科全书 \n 苏联 此條目需要补充更多 来源 。 (2020年1月15日) 请协助補充多方面 可靠来源 以 改善这篇条目 , 无法查证 的内容可能會因為 异议提出 而被移除。 致使用者:请搜索一下条目的标题(来源搜索: \"苏联\" — 网页 、 新闻 、 书籍 、 学术 、 图像 ),以检查网络上是否存在该主题的更多可靠来源( 判定指引 )。

Nothingness-Void commented 11 months ago

我也一样,应该是微软方改的

glaw1984 commented 11 months ago

出现故障!如果这个问题持续出现,请和我说“重置会话” 来开启一段新的会话,或者发送 “回滚会话” 来回溯到上一条对话,你上一条说的我就当作没看见。 'adaptiveCards'

glaw1984 commented 11 months ago

出现故障!如果这个问题持续出现,请和我说“重置会话” 来开启一段新的会话,或者发送 “回滚会话” 来回溯到上一条对话,你上一条说的我就当作没看见。 'messages'

glaw1984 commented 11 months ago

bing基本没有法用了

Huoyuuu commented 10 months ago

遇到同样的问题。 这边的解决办法是在/adpater/ms/bing.py中增加字符串替换语句parsed_content = re.sub(r'\{"web_search_results":.*\}', '', parsed_content),手动去除web_search_results的内容。

我在async def ask(self, prompt: str) -> Generator[str, None, None]函数内部添加了两行这样的语句,修改后的函数如下:

    async def ask(self, prompt: str) -> Generator[str, None, None]:
        self.count = self.count + 1
        parsed_content = ''
        image_urls = []
        try:
            async for final, response in self.bot.ask_stream(prompt=prompt,
                                                             conversation_style=self.conversation_style,
                                                             wss_link=config.bing.wss_link,
                                                             locale="zh-cn"):
                if not response:
                    continue

                if final:
                    # 最后一条消息
                    max_messages = config.bing.max_messages
                    with suppress(KeyError):
                        max_messages = response["item"]["throttling"]["maxNumUserMessagesInConversation"]

                    with suppress(KeyError):
                        raw_text = response["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"]
                        image_urls = re.findall(image_pattern, raw_text)

                    remaining_conversations = f'\n剩余回复数:{self.count} / {max_messages} ' \
                        if config.bing.show_remaining_count else ''

                    if len(response["item"].get('messages', [])) > 1 and config.bing.show_suggestions:
                        suggestions = response["item"]["messages"][-1].get("suggestedResponses", [])
                        if len(suggestions) > 0:
                            parsed_content = parsed_content + '\n猜你想问:  \n'
                            for suggestion in suggestions:
                                parsed_content = f"{parsed_content}* {suggestion.get('text')}  \n"

                    parsed_content = parsed_content + remaining_conversations
                    parsed_content = re.sub(r'\{"web_search_results":.*\}', '', parsed_content)

                    if parsed_content == remaining_conversations:  # No content
                        yield "Bing 已结束本次会话。 继续发送消息将重新开启一个新会话。 "
                        await self.on_reset()
                        return
                else:
                    # 生成中的消息
                    parsed_content = re.sub(r"Searching the web for:(.*)\n", "", response)
                    parsed_content = re.sub(r"```json(.*)```", "", parsed_content,flags=re. DOTALL)
                    parsed_content = re.sub(r"Generating answers for you...", "", parsed_content)
                    parsed_content = re.sub(r'\{"web_search_results":.*\}', '', parsed_content)
                    if config.bing.show_references:
                        parsed_content = re.sub(r"\[(\d+)\]: ", r"\1: ", parsed_content)
                    else:
                        parsed_content = re.sub(r"(\[\d+\]\: .+)+", "", parsed_content)
                    parts = re.split(image_pattern, parsed_content)
                    # 图片单独保存
                    parsed_content = parts[0]

                    if len(parts) > 2:
                        parsed_content = parsed_content + parts[-1]

                yield parsed_content
            logger.debug(f"[Bing AI 响应] {parsed_content}")
            image_tasks = [
                asyncio.create_task(self.__download_image(url))
                for url in image_urls
            ]
            for image in await asyncio.gather(*image_tasks):
                yield image
        except (asyncio.exceptions.TimeoutError, asyncio.exceptions.CancelledError) as e:
            raise e
        except NotAllowedToAccess:
            yield "出现错误:机器人的 Bing Cookie 可能已过期,或者机器人当前使用的 IP 无法使用 Bing AI。 "
            return
        except Exception as e:
            if str(e) == 'Redirect failed':
                yield '画图失败:Redirect failed'
                return
            raise e
Huoyuuu commented 10 months ago

实测跑了一下,除web_search_results外,还会出现location_results等的结果。解决办法是改用更激进的正则表达式。 将上文替换语句修改为parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

修改后的函数如下

    async def ask(self, prompt: str) -> Generator[str, None, None]:
        self.count = self.count + 1
        parsed_content = ''
        image_urls = []
        try:
            async for final, response in self.bot.ask_stream(prompt=prompt,
                                                             conversation_style=self.conversation_style,
                                                             wss_link=config.bing.wss_link,
                                                             locale="zh-cn"):
                if not response:
                    continue

                if final:
                    # 最后一条消息
                    max_messages = config.bing.max_messages
                    with suppress(KeyError):
                        max_messages = response["item"]["throttling"]["maxNumUserMessagesInConversation"]

                    with suppress(KeyError):
                        raw_text = response["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"]
                        image_urls = re.findall(image_pattern, raw_text)

                    remaining_conversations = f'\n剩余回复数:{self.count} / {max_messages} ' \
                        if config.bing.show_remaining_count else ''

                    if len(response["item"].get('messages', [])) > 1 and config.bing.show_suggestions:
                        suggestions = response["item"]["messages"][-1].get("suggestedResponses", [])
                        if len(suggestions) > 0:
                            parsed_content = parsed_content + '\n猜你想问:  \n'
                            for suggestion in suggestions:
                                parsed_content = f"{parsed_content}* {suggestion.get('text')}  \n"

                    parsed_content = parsed_content + remaining_conversations
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

                    if parsed_content == remaining_conversations:  # No content
                        yield "Bing 已结束本次会话。 继续发送消息将重新开启一个新会话。 "
                        await self.on_reset()
                        return
                else:
                    # 生成中的消息
                    parsed_content = re.sub(r"Searching the web for:(.*)\n", "", response)
                    parsed_content = re.sub(r"```json(.*)```", "", parsed_content,flags=re. DOTALL)
                    parsed_content = re.sub(r"Generating answers for you...", "", parsed_content)
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
                    if config.bing.show_references:
                        parsed_content = re.sub(r"\[(\d+)\]: ", r"\1: ", parsed_content)
                    else:
                        parsed_content = re.sub(r"(\[\d+\]\: .+)+", "", parsed_content)
                    parts = re.split(image_pattern, parsed_content)
                    # 图片单独保存
                    parsed_content = parts[0]

                    if len(parts) > 2:
                        parsed_content = parsed_content + parts[-1]

                yield parsed_content
            logger.debug(f"[Bing AI 响应] {parsed_content}")
            image_tasks = [
                asyncio.create_task(self.__download_image(url))
                for url in image_urls
            ]
            for image in await asyncio.gather(*image_tasks):
                yield image
        except (asyncio.exceptions.TimeoutError, asyncio.exceptions.CancelledError) as e:
            raise e
        except NotAllowedToAccess:
            yield "出现错误:机器人的 Bing Cookie 可能已过期,或者机器人当前使用的 IP 无法使用 Bing AI。 "
            return
        except Exception as e:
            if str(e) == 'Redirect failed':
                yield '画图失败:Redirect failed'
                return
            raise e
Nothingness-Void commented 10 months ago

实测跑了一下,除web_search_results外,还会出现location_results等的结果。解决办法是改用更激进的正则表达式。 将上文替换语句修改为parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

修改后的函数如下

    async def ask(self, prompt: str) -> Generator[str, None, None]:
        self.count = self.count + 1
        parsed_content = ''
        image_urls = []
        try:
            async for final, response in self.bot.ask_stream(prompt=prompt,
                                                             conversation_style=self.conversation_style,
                                                             wss_link=config.bing.wss_link,
                                                             locale="zh-cn"):
                if not response:
                    continue

                if final:
                    # 最后一条消息
                    max_messages = config.bing.max_messages
                    with suppress(KeyError):
                        max_messages = response["item"]["throttling"]["maxNumUserMessagesInConversation"]

                    with suppress(KeyError):
                        raw_text = response["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"]
                        image_urls = re.findall(image_pattern, raw_text)

                    remaining_conversations = f'\n剩余回复数:{self.count} / {max_messages} ' \
                        if config.bing.show_remaining_count else ''

                    if len(response["item"].get('messages', [])) > 1 and config.bing.show_suggestions:
                        suggestions = response["item"]["messages"][-1].get("suggestedResponses", [])
                        if len(suggestions) > 0:
                            parsed_content = parsed_content + '\n猜你想问:  \n'
                            for suggestion in suggestions:
                                parsed_content = f"{parsed_content}* {suggestion.get('text')}  \n"

                    parsed_content = parsed_content + remaining_conversations
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

                    if parsed_content == remaining_conversations:  # No content
                        yield "Bing 已结束本次会话。 继续发送消息将重新开启一个新会话。 "
                        await self.on_reset()
                        return
                else:
                    # 生成中的消息
                    parsed_content = re.sub(r"Searching the web for:(.*)\n", "", response)
                    parsed_content = re.sub(r"```json(.*)```", "", parsed_content,flags=re. DOTALL)
                    parsed_content = re.sub(r"Generating answers for you...", "", parsed_content)
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
                    if config.bing.show_references:
                        parsed_content = re.sub(r"\[(\d+)\]: ", r"\1: ", parsed_content)
                    else:
                        parsed_content = re.sub(r"(\[\d+\]\: .+)+", "", parsed_content)
                    parts = re.split(image_pattern, parsed_content)
                    # 图片单独保存
                    parsed_content = parts[0]

                    if len(parts) > 2:
                        parsed_content = parsed_content + parts[-1]

                yield parsed_content
            logger.debug(f"[Bing AI 响应] {parsed_content}")
            image_tasks = [
                asyncio.create_task(self.__download_image(url))
                for url in image_urls
            ]
            for image in await asyncio.gather(*image_tasks):
                yield image
        except (asyncio.exceptions.TimeoutError, asyncio.exceptions.CancelledError) as e:
            raise e
        except NotAllowedToAccess:
            yield "出现错误:机器人的 Bing Cookie 可能已过期,或者机器人当前使用的 IP 无法使用 Bing AI。 "
            return
        except Exception as e:
            if str(e) == 'Redirect failed':
                yield '画图失败:Redirect failed'
                return
            raise e

感谢 是把如下代码复制进去直接就可用了吗

Huoyuuu commented 10 months ago

实测跑了一下,除web_search_results外,还会出现location_results等的结果。解决办法是改用更激进的正则表达式。 将上文替换语句修改为parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content) 修改后的函数如下

    async def ask(self, prompt: str) -> Generator[str, None, None]:
        self.count = self.count + 1
        parsed_content = ''
        image_urls = []
        try:
            async for final, response in self.bot.ask_stream(prompt=prompt,
                                                             conversation_style=self.conversation_style,
                                                             wss_link=config.bing.wss_link,
                                                             locale="zh-cn"):
                if not response:
                    continue

                if final:
                    # 最后一条消息
                    max_messages = config.bing.max_messages
                    with suppress(KeyError):
                        max_messages = response["item"]["throttling"]["maxNumUserMessagesInConversation"]

                    with suppress(KeyError):
                        raw_text = response["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"]
                        image_urls = re.findall(image_pattern, raw_text)

                    remaining_conversations = f'\n剩余回复数:{self.count} / {max_messages} ' \
                        if config.bing.show_remaining_count else ''

                    if len(response["item"].get('messages', [])) > 1 and config.bing.show_suggestions:
                        suggestions = response["item"]["messages"][-1].get("suggestedResponses", [])
                        if len(suggestions) > 0:
                            parsed_content = parsed_content + '\n猜你想问:  \n'
                            for suggestion in suggestions:
                                parsed_content = f"{parsed_content}* {suggestion.get('text')}  \n"

                    parsed_content = parsed_content + remaining_conversations
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

                    if parsed_content == remaining_conversations:  # No content
                        yield "Bing 已结束本次会话。 继续发送消息将重新开启一个新会话。 "
                        await self.on_reset()
                        return
                else:
                    # 生成中的消息
                    parsed_content = re.sub(r"Searching the web for:(.*)\n", "", response)
                    parsed_content = re.sub(r"```json(.*)```", "", parsed_content,flags=re. DOTALL)
                    parsed_content = re.sub(r"Generating answers for you...", "", parsed_content)
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
                    if config.bing.show_references:
                        parsed_content = re.sub(r"\[(\d+)\]: ", r"\1: ", parsed_content)
                    else:
                        parsed_content = re.sub(r"(\[\d+\]\: .+)+", "", parsed_content)
                    parts = re.split(image_pattern, parsed_content)
                    # 图片单独保存
                    parsed_content = parts[0]

                    if len(parts) > 2:
                        parsed_content = parsed_content + parts[-1]

                yield parsed_content
            logger.debug(f"[Bing AI 响应] {parsed_content}")
            image_tasks = [
                asyncio.create_task(self.__download_image(url))
                for url in image_urls
            ]
            for image in await asyncio.gather(*image_tasks):
                yield image
        except (asyncio.exceptions.TimeoutError, asyncio.exceptions.CancelledError) as e:
            raise e
        except NotAllowedToAccess:
            yield "出现错误:机器人的 Bing Cookie 可能已过期,或者机器人当前使用的 IP 无法使用 Bing AI。 "
            return
        except Exception as e:
            if str(e) == 'Redirect failed':
                yield '画图失败:Redirect failed'
                return
            raise e

感谢 是把如下代码复制进去直接就可用了吗

是的,替换掉adapter/ms/bing.py文件中的ask函数。另外这里实质上是加了两个字符串替换语句,直接加进去也是OK的。

Anzu0831 commented 10 months ago

实测跑了一下,除web_search_results外,还会出现location_results等的结果。解决办法是改用更激进的正则表达式。 将上文替换语句修改为parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content) 修改后的函数如下

    async def ask(self, prompt: str) -> Generator[str, None, None]:
        self.count = self.count + 1
        parsed_content = ''
        image_urls = []
        try:
            async for final, response in self.bot.ask_stream(prompt=prompt,
                                                             conversation_style=self.conversation_style,
                                                             wss_link=config.bing.wss_link,
                                                             locale="zh-cn"):
                if not response:
                    continue

                if final:
                    # 最后一条消息
                    max_messages = config.bing.max_messages
                    with suppress(KeyError):
                        max_messages = response["item"]["throttling"]["maxNumUserMessagesInConversation"]

                    with suppress(KeyError):
                        raw_text = response["item"]["messages"][1]["adaptiveCards"][0]["body"][0]["text"]
                        image_urls = re.findall(image_pattern, raw_text)

                    remaining_conversations = f'\n剩余回复数:{self.count} / {max_messages} ' \
                        if config.bing.show_remaining_count else ''

                    if len(response["item"].get('messages', [])) > 1 and config.bing.show_suggestions:
                        suggestions = response["item"]["messages"][-1].get("suggestedResponses", [])
                        if len(suggestions) > 0:
                            parsed_content = parsed_content + '\n猜你想问:  \n'
                            for suggestion in suggestions:
                                parsed_content = f"{parsed_content}* {suggestion.get('text')}  \n"

                    parsed_content = parsed_content + remaining_conversations
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)

                    if parsed_content == remaining_conversations:  # No content
                        yield "Bing 已结束本次会话。 继续发送消息将重新开启一个新会话。 "
                        await self.on_reset()
                        return
                else:
                    # 生成中的消息
                    parsed_content = re.sub(r"Searching the web for:(.*)\n", "", response)
                    parsed_content = re.sub(r"```json(.*)```", "", parsed_content,flags=re. DOTALL)
                    parsed_content = re.sub(r"Generating answers for you...", "", parsed_content)
                    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
                    if config.bing.show_references:
                        parsed_content = re.sub(r"\[(\d+)\]: ", r"\1: ", parsed_content)
                    else:
                        parsed_content = re.sub(r"(\[\d+\]\: .+)+", "", parsed_content)
                    parts = re.split(image_pattern, parsed_content)
                    # 图片单独保存
                    parsed_content = parts[0]

                    if len(parts) > 2:
                        parsed_content = parsed_content + parts[-1]

                yield parsed_content
            logger.debug(f"[Bing AI 响应] {parsed_content}")
            image_tasks = [
                asyncio.create_task(self.__download_image(url))
                for url in image_urls
            ]
            for image in await asyncio.gather(*image_tasks):
                yield image
        except (asyncio.exceptions.TimeoutError, asyncio.exceptions.CancelledError) as e:
            raise e
        except NotAllowedToAccess:
            yield "出现错误:机器人的 Bing Cookie 可能已过期,或者机器人当前使用的 IP 无法使用 Bing AI。 "
            return
        except Exception as e:
            if str(e) == 'Redirect failed':
                yield '画图失败:Redirect failed'
                return
            raise e

感谢 是把如下代码复制进去直接就可用了吗

是的,替换掉adapter/ms/bing.py文件中的ask函数。另外这里实质上是加了两个字符串替换语句,直接加进去也是OK的。

感谢大佬 ,大佬威武! (可惜我在ubuntu环境下没找到这个路径 😥。)

Huoyuuu commented 10 months ago

@Anzu0831 Ubuntu应该是docker配置的,我写一下修改方法,更具体的内容可以参考相关教程等等。

  1. 把容器中的adapter文件夹备份到本地的adapter文件夹。
    sudo docker cp chatgpt-qq_chatgpt_1:/app/adapter ./adapter
  2. 在本地的adapter/ms/bing.py文件中修改代码,在ask函数中加入两行正则表达式。
    parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
  3. 在docker-compose的配置文件docker-compose.yaml中指定volumes映射,让容器启动时采用本地adapter中文件的设置。
    version: '3'
    services:
    chatgpt-qq_chatgpt_1:
    image: lss233/chatgpt-mirai-qq-bot:v2.5.3
    volumes:
      - ./config.cfg:/app/config.cfg
      - ./data:/app/data
      - ./presets:/app/presets
      - ./adapter:/app/adapter  # 将主机上的./adapter目录挂载到容器的/app/adapter目录
      # 其他容器配置...
  4. 更新容器,载入修改后的配置文件和adapter文件。
    sudo docker-compose up -d chatgpt
lss233 commented 10 months ago

可以用v3版本

Anzu0831 commented 10 months ago

@Anzu0831 Ubuntu应该是docker配置的,我写一下修改方法,更具体的内容可以参考相关教程等等。

  1. 把容器中的adapter文件夹备份到本地的adapter文件夹。
sudo docker cp chatgpt-qq_chatgpt_1:/app/adapter ./adapter
  1. 在本地的adapter/ms/bing.py文件中修改代码,在ask函数中加入两行正则表达式。
parsed_content = re.sub(r'\{".*":.*\}', '', parsed_content)
  1. 在docker-compose的配置文件docker-compose.yaml中指定volumes映射,让容器启动时采用本地adapter中文件的设置。
version: '3'
services:
  chatgpt-qq_chatgpt_1:
    image: lss233/chatgpt-mirai-qq-bot:v2.5.3
    volumes:
      - ./config.cfg:/app/config.cfg
      - ./data:/app/data
      - ./presets:/app/presets
      - ./adapter:/app/adapter  # 将主机上的./adapter目录挂载到容器的/app/adapter目录
      # 其他容器配置...
  1. 更新容器,载入修改后的配置文件和adapter文件。
sudo docker-compose up -d chatgpt

大佬威武 [打CALL][打CALL][打CALL]

thomashooo commented 9 months ago

能解决

Anzu0831 commented 9 months ago

可以用v3版本

在V3版本中 似乎并未提到如何在linux环境下进行更新 ,我试着像之前一样 执行 docker-compose pull && docker-compose up -d 更新最新镜像,并未从v2.5.3更新至v3.0.0 🤔