【实战营彩蛋】MindSearch 快速部署(InternStudio 版)

一、关卡任务

基础任务

比如,对于多步骤的复杂问题,模型能够分析用户需求,先搜索嫦娥 6 号的技术难点、再针对每一个技术难点搜索对应的解决方案,再从任务目标、技术手段、科学成果、国际合作 4 个方面对比阿波罗 11 号登月计划,最后总结我国探月成功的贡献。

MindSearch 依靠其独特的路径建模方式在 agent 层面上进行并发,在 3 分钟内就阅读了 300+ 相关网页,给出了最终的答案。而且,与其他 AI 搜索引擎不同的是,MindSearch 完全对外展示了问题解决过程中的 AI 的思考过程和搜索中间结果,用户可以根据自己的需要查看每一次的搜索过程和模型阅读的网页,增加了对整个内容的可解释性和可信度。

在面对更大规模的信息搜集整理任务时,需面对三重挑战:

(1)搜索引擎难以一次性精确返回复杂请求所需的全量网络信息
(2)待整合的信息散布在多个网页中,信息非常嘈杂
(3)大量的网络内容很容易超过 LLM 可处理的上下文长度

为了解决这些难题,研发团队提出了名为 MindSearch (思·索)的多智能体框架。顾名思义,MindSearch 模拟人的思维过程,先对问题进行充分的“思”考,再进行完整的信息搜“索”,同时将整个系统设计成“思”和“索”两个智能体进行分工协作,交互完成任务。

如上图所示,由规划器专注“思”考,分析问题、拆解任务,并将任务分配给检索器。而检索器负责层次化检“索”网络信息,并回答每个子问题。于此同时,MindSearch 的多智能体设计也将处理大量信息的负载分配给了不同的智能体,使得整个框架能够处理更长的上下文(超过 300 个网页)。

二、实验过程

2.1 使用免费的搜索接口

2.1.1 激活环境

小助手提前帮大家安装好了环境,只需要一步一步按照下面的步骤便可以启动 MindSearch。

conda activate /share/pre_envs/mindsearch

2.1.2 启动后端

打开新终端运行以下命令启动推理后端,使用入门岛中学到的方式使用 vscode 或者 ssh 将端口映射到本地 8002 端口。

conda activate /share/pre_envs/mindsearch
cd /share/demo/MindSearchDuck

python -m mindsearch.app --lang cn --model_format internstudio_server

2.1.3 启动前端

打开新终端运行以下命令启动前端,使用入门岛中学到的方式使用 vscode 或者 ssh 将端口映射到本地 7860 端口。

ssh -CNg -L 7860:127.0.0.1:7860 root@ssh.intern-ai.org.cn -p 35177
conda activate /share/pre_envs/mindsearch
cd /share/demo/MindSearchDuck

python run.py

本地浏览器打开 http://localhost:7860 地址,开始 MindSearch 之旅。

2.2 使用 Bing 的接口

Bing API Key 获取网址(尽量选高一点的定价):Web Search API | Microsoft Bing

学生可以使用学术认证,获得免费的使用资格:

如果没办法注册成功,还可以使用谷歌搜索API或者DuckDuckGo。

DuckDuckGo这个是默认的选项。

2.3 遇到问题

RuntimeError: Operation on the closed queue is forbidden

解决方案:

在mindsearch/app.py

找到

async def generate():
        try:
            queue = janus.Queue()

            # 使用 run_in_executor 将同步生成器包装成异步生成器
            def sync_generator_wrapper():
                try:
                    for response in agent.stream_chat(inputs):
                        queue.sync_q.put(response)
                except Exception as e:
                    logging.exception(
                        f'Exception in sync_generator_wrapper: {e}')
                finally:
                    # 确保在发生异常时队列中的所有元素都被消费
                    queue.sync_q.put(None)

            async def async_generator_wrapper():
                loop = asyncio.get_event_loop()
                loop.run_in_executor(None, sync_generator_wrapper)
                while True:
                    response = await queue.async_q.get()
                    if response is None:  # 确保消费完所有元素
                        break
                    yield response
                    if not isinstance(
                            response,
                            tuple) and response.state == AgentStatusCode.END:
                        break

            async for response in async_generator_wrapper():
                if isinstance(response, tuple):
                    agent_return, node_name = response
                else:
                    agent_return = response
                    node_name = None
                origin_adj = deepcopy(agent_return.adjacency_list)
                adjacency_list = convert_adjacency_to_tree(
                    agent_return.adjacency_list, 'root')
                assert adjacency_list[
                    'name'] == 'root' and 'children' in adjacency_list
                agent_return.adjacency_list = adjacency_list['children']
                agent_return = asdict(agent_return)
                agent_return['adj'] = origin_adj
                response_json = json.dumps(dict(response=agent_return,
                                                current_node=node_name),
                                           ensure_ascii=False)
                yield {'data': response_json}
                # yield f'data: {response_json}\n\n'
        except Exception as exc:
            msg = 'An error occurred while generating the response.'
            logging.exception(msg)
            response_json = json.dumps(
                dict(error=dict(msg=msg, details=str(exc))),
                ensure_ascii=False)
            yield {'data': response_json}
            # yield f'data: {response_json}\n\n'
        finally:
            queue.close()
            await queue.wait_closed()

替换为

async def generate():
        try:
            queue = janus.Queue()
            stop_event = asyncio.Event()

            # 使用 run_in_executor 将同步生成器包装成异步生成器
            # Wrapping a sync generator as an async generator using run_in_executor
            def sync_generator_wrapper():
                try:
                    for response in agent.stream_chat(inputs):
@@ -71,21 +72,22 @@ def sync_generator_wrapper():
                    logging.exception(
                        f'Exception in sync_generator_wrapper: {e}')
                finally:
                    # 确保在发生异常时队列中的所有元素都被消费
                    # Notify async_generator_wrapper that the data generation is complete.
                    queue.sync_q.put(None)

            async def async_generator_wrapper():
                loop = asyncio.get_event_loop()
                loop.run_in_executor(None, sync_generator_wrapper)
                while True:
                    response = await queue.async_q.get()
                    if response is None:  # 确保消费完所有元素
                    if response is None:  # Ensure that all elements are consumed
                        break
                    yield response
                    if not isinstance(
                            response,
                            tuple) and response.state == AgentStatusCode.END:
                        break
                stop_event.set()  # Inform sync_generator_wrapper to stop

            async for response in async_generator_wrapper():
                if isinstance(response, tuple):
@@ -115,6 +117,8 @@ async def async_generator_wrapper():
            yield {'data': response_json}
            # yield f'data: {response_json}\n\n'
        finally:
            await stop_event.wait(
            )  # Waiting for async_generator_wrapper to stop
            queue.close()
            await queue.wait_closed()

如果因为远程机环境不能修改,可以重新去MindSearch仓库下载运行。

2.4 结果

SpringBoot项目启动彩蛋是指在项目启动时,通过在控制台输出特定的Logo或者文字画面来增加启动的趣味性。 要实现SpringBoot项目启动彩蛋,可以通过修改`banner.txt`文件来替换默认的Spring Logo。这个文件可以包含自定义的Logo或者文字画面。 如果你想生成自己的Logo或文字画面,可以使用在线工具来生成,比如http://patorjk.com/software/taag、http://www.network-science.de/ascii/、http://www.degraeve.com/img2txt.php。这些工具可以根据你输入的内容生成相应的Logo或文字画面,你可以将生成的内容复制到`banner.txt`文件中,然后替换默认的Spring Logo。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* [SpringBoot项目启动彩蛋与启动完成提示修改](https://blog.csdn.net/shouchenchuan5253/article/details/107647377)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *3* [git启动文件彩蛋](https://download.csdn.net/download/weixin_41847607/10683713)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值