Nanobot 从 Channel 消息处理看python协程的使用

「文智助手」全场景办公AI助理AI+OPC全流程实践方案(大赛作品) 阅读详情

背景

在 Nanobot 从 AgentLoop 启动看怎么驱动大模型运行中提到协程和线程的区别,
通过Nanobot(channels.start_all)这里了解一下协程一些基本操作.

协程是用户态的轻量级“微线程”,切换由用户程序控制,没有内核态切换,开销极小;线程是内核态的资源单元,切换由操作系统调度,开销较大.
线程切换需要涉及用户态到内核态的转换,上下文包括内核栈、硬件寄存器等,保存和恢复资源较多

channels.start_all

    async def start_all(self) -> None:
        """Start all channels and the outbound dispatcher."""
        if not self.channels:
            logger.warning("No channels enabled")
            return

        # Start outbound dispatcher
        self._dispatch_task = asyncio.create_task(self._dispatch_outbound())

        # Start channels
        tasks = []
        for name, channel in self.channels.items():
            logger.info("Starting {} channel...", name)
            tasks.append(asyncio.create_task(self._start_channel(name, channel)))

        # Wait for all to complete (they should run forever)
        await asyncio.gather(*tasks, return_exceptions=True)

总体上的channel的启动代码如上。
在至少有一个已注册频道时,先起 _dispatch_outbound 消费总线出站消息,再为每个频道 create_task(start),
最后用 gather(…, return_exceptions=True) 一直等到这些长任务结束(正常即进程生命周期);无任何启用频道则直接返回。
总体上来说:

1. 使用 async def 定义协程
2. 使用 asyncio.run 运行协程
  • asyncio.create_task(self._dispatch_outbound())
    它将协程(coroutine)封装为任务(Task)对象,并立即调度该任务在事件循环中并在后台执行,从而允许在等待其完成的同时执行其他代码
    dispatch_outbound是一个 async 死循环,在 start_all() 里被 asyncio.create_task 单独跑,从 MessageBus 的出站队列取 OutboundMessage,
    按 msg.channel 找到对应 BaseChannel,再真正发到 Telegram/Discord 等
    async def _dispatch_outbound(self) -> None:
          """Dispatch outbound messages to the appropriate channel."""
          logger.info("Outbound dispatcher started")
    
          while True:
              try:
                  msg = await asyncio.wait_for(
                      self.bus.consume_outbound(),
                      timeout=1.0
                  )
    
                  if msg.metadata.get("_progress"):
                      if msg.metadata.get("_tool_hint") and not self.config.channels.send_tool_hints:
                          continue
                      if not msg.metadata.get("_tool_hint") and not self.config.channels.send_progress:
                          continue
    
                  channel = self.channels.get(msg.channel)
                  if channel:
                      await self._send_with_retry(channel, msg)
                  else:
                      logger.warning("Unknown channel: {}", msg.channel)
    
              except asyncio.TimeoutError:
                  continue
              except asyncio.CancelledError:
                  break
    
    • asyncio.wait_for(self.bus.consume_outbound(), timeout=1.0)
      这个是 asyncio 库中用于给异步操作(协程或任务)设置超时限制的函数。如果 aw 在 timeout 秒内未完成,则会触发 asyncio.TimeoutError 异常,并取消该任务
      用来消费出站的消息,并发动到对应的Channel中,如feishu等
      这里的 _send_with_retry 最终会调用 channel.send,这里我们以feishu的处理逻辑为例:
         loop = asyncio.get_running_loop()
         ...
         if ext in self._IMAGE_EXTS:
            key = await loop.run_in_executor(None, self._upload_image_sync, file_path)
            if key:
                await loop.run_in_executor(
                    None, _do_send,
                    "image", json.dumps({"image_key": key}, ensure_ascii=False),
                )
      
      • asyncio.get_running_loop()
        在异步函数(async def)或回调函数内部,获取当前线程的事件循环对象,以便绑定定时器、socket 或执行其他循环级操作
        这是为了后续获取线程池的方便
      • loop.run_in_executor(None,…)
        通过协程将任务委托给线程池 (ThreadPoolExecutor) 执行,从而避免阻塞核心的异步事件循环,因为协程是在同一个线程中运行的
        这里的第一个参数为None,则使用事件循环默认的线程池,而且这里用了 await,所以进行同步等待
  • asyncio.create_task(self._start_channel(name, channel))
    这里启动对应的 Channel,以feishu为例:
      async def start(self) -> None:
          """Start the Feishu bot with WebSocket long connection."""
          self._loop = asyncio.get_running_loop()
          ...
          builder = lark.EventDispatcherHandler.builder(
              self.config.encrypt_key or "",
              self.config.verification_token or "",
          ).register_p2_im_message_receive_v1(
              self._on_message_sync
          )
          ...
          def run_ws():
              import time
              import lark_oapi.ws.client as _lark_ws_client
              ws_loop = asyncio.new_event_loop()
              asyncio.set_event_loop(ws_loop)
              # Patch the module-level loop used by lark's ws Client.start()
              _lark_ws_client.loop = ws_loop
              try:
                  while self._running:
                      try:
                          self._ws_client.start()
                      except Exception as e:
                          logger.warning("Feishu WebSocket error: {}", e)
                      if self._running:
                          time.sleep(5)
              finally:
                  ws_loop.close()
    
          self._ws_thread = threading.Thread(target=run_ws, daemon=True)
          self._ws_thread.start()
    
          logger.info("Feishu bot started with WebSocket long connection")
          logger.info("No public IP required - using WebSocket to receive events")
    
          # Keep running until stopped
          while self._running:
              await asyncio.sleep(1)
    
    
    • self._loop = asyncio.get_running_loop()
      这里也是获得当前线程的事件循环对象,和上面send的时候获取的是一个。
    • _loop.is_running 和 asyncio.run_coroutine_threadsafe(self._on_message(data), self._loop)
      这个主要出现在 _on_message_sync方法中,
      is_running() 用于检查当前线程中正在运行的事件循环是否处于运行状态(而非已停止或关闭)
      asyncio.run_coroutine_threadsafe(coro, loop) 用于在主线程或其他工作线程中安全地提交协程到异步事件循环(loop)中执行的函数
    • threading.Thread(target=run_ws, daemon=True)
      启动线程,这里的 run_ws方法是在另一个线程中跑,这里会单独启动协程,这是为了在独立守护线程里跑,而收消息同步回调再通过 self._loop 把异步处理 _on_message 投到主事件循环
      • ws_loop = asyncio.new_event_loop()
        用于显式创建并返回一个新的事件循环对象的函数。它不会自动将新循环设置为当前线程的默认循环,主要用于需要手动管理循环、在不同线程中创建独立循环,或避免默认循环策略限制的场景
      • asyncio.set_event_loop(ws_loop)
        用于将指定的事件循环实例(loop)设置为当前OS线程的默认事件循环
      • ws_loop.close()
        asyncio.new_event_loop().close 释放其底层资源(如 socket、文件描述符),防止资源泄露
  • asyncio.gather
    用于并发运行多个可等待对象(如协程或任务)并收集结果的实用函数。它按参数顺序返回所有结果列表,await 时暂停直到所有任务完成
    其中 return_exceptions = True 表示异常会被视为正常结果放入结果列表
船载 OpenHarmony AIS 航海工作台:告警与防碰撞预警系统 船载OpenHarmony AIS航海工作台的告警与防碰撞系统,集成十余类告警(超速、偏航、会遇、SOS等),通过网格空间索引实现高效邻近判定,保障实时性。告警管理器统一调度规则、去重、通知与日志,支持悬浮球、语音、跑马灯、弹窗多渠道触达,确保航行安全。SOS紧急通道独立运行,避免干扰。系统设计强调性能优化与多场景适配,为航海安全提供核心支撑。 阅读详情

相关推荐

强化学习-动态规划

动态规划(dynamic programming)是程序设计算法中非常重要的内容,能够高效解决一些经典问题,例如背包问题和最短路径规划。动态规划的基本思想是将待求解问题分解成若干个子问题,先求解子问题,然后从这些子问题的解得到目标问题的解。动态规划会保存已解决的子问题的答案,在求解目标问题的过程中,需要这些子问题答案时就可以直接利用,避免重复计算。本章介绍如何用动态规划的思想来求解在马尔可夫决策过程中的最优策略。

qq_45481856的博客 2113

Nanobot 从 gateway 启动命令来看个人助理Agent的实现

本文分析了nanobot gateway命令的实现细节。该命令用于启动AI助手网关进程,采用Typer、Rich等现代CLI工具构建交互界面。核心功能包括: 参数处理:支持自定义端口、工作区路径、日志级别和配置文件路径 核心组件初始化: 消息总线(MessageBus)管理进程内消息队列 根据配置实例化LLM Provider 会话管理器(SessionManager)实现对话持久化 定时任务服务: 通过CronService管理定时任务 任务触发时构建消息并调用AI处理 支持结果通知和响应评估 系统采用a

monkeyboy_tech的博客 565

ZYNQ RFSoC 的DAC如何做到从 0到Fs频段 信号输出

之前一直没太了解 RFSoC 的DAC如何输出在 Fs/2 到 Fs 频率范围内的信号,例如 ZCU216中的 ZU49DR,其RF-DAC最大采样率是 9.85GSPS,如果想输出的信号中心频率在5.8G,它是如何有效输出在第二奈奎斯特区域范围的信号的。

weixin_44630490的博客 1552

HKUDS开源NanoBot:简介、源码、原理、实战

Agent-Loop、架构、核心方法、工具调用处理、会话管理、MCP服务器连接、进度回调、子代理:、最佳实践、实战

lonelymanontheway的博客 704

GLDAS数据高效处理指南:基于Matlab的NC4转GeoTIFF实战解析

本文提供了一份基于Matlab的GLDAS数据处理实战指南,详细解析了如何将NetCDF4格式的GLDAS数据高效、准确地批量转换为GIS友好的GeoTIFF格式。文章核心内容包括数据理解、环境搭建、核心代码逐步拆解、效率提升技巧以及常见避坑方案,旨在帮助全球生态、水文与气候领域的研究者打通数据预处理的关键环节,提升科研工作效率。

weixin_29094775的博客 311

SAP FI 提示没有为会计年度0 定义版本2025 GP626

SAP 错误 GP626 是一个常见的系统消息,通常表示某个会计年度的版本(如版本 0)未被定义或未激活。:在执行某些事务(如创建采购订单、过账凭证或维护成本中心)时,系统会检查相关版本是否已定义。的“Settings for Each Fiscal Year”界面中,选择一个已激活的会计年度。的“Settings for Each Fiscal Year”界面中,找到未激活的会计年度。:在控制范围(Controlling Area)中,未为指定的会计年度定义版本 0。如果没有,添加或复制现有年度的设置。

GAVIN 2490

【Nanobot】README09_LEVEL4 添加新聊天渠道

【Nanobot】README09_LEVEL4 添加新聊天渠道

感谢所有乐于奉献的人,在此不一一具名 66

JavaFX - 动画

JavaFX 动画

思你日度难眠 1603

Nanobot(OpenClaw 轻量实现)的底层原理解析

本文以精简版 OpenClaw——Nanobot 为切入点,拆解其核心原理。 其本质是基于循环执行的“提示词构建 + 调用大模型 + 工具操作”的本地 Agent 架构。通过分析消息处理、上下文构建、循环决策(AgentLoop)与工具调用(Tools)等流程,揭示其运行机制。

vivo互联网技术 596

Android Input——输入系统介绍(一)

Input 系统对于提供流畅、灵敏和一致的用户交互体验至关重要,它需要在不同的设备、场景和应用中保证输入事件的正确性、及时性和安全性。Android 输入系统是一个复杂但高效的设计,旨在处理来自各种输入设备(如触摸屏、键盘等)的用户交互,并将这些交互转换为应用程序可以理解和响应的形式。EventHub:输入系统的最底层,直接与硬件通信,监听和读取输入设备的原始事件。:从 EventHub 获取原始输入事件,对其进行解析,转化为更高层次的事件,以便上层应用或服务能够理解。

小旭的专栏 1712

华为OD机试真题 新系统【小学英语老师批改作文】

华为OD机试 新系统真题【小学英语老师批改作文】,提供C语言、Java、C++、Python、Go、JavaScript源码实现,并提供完整思路讲解,以及在线OJ模拟做题。华为OD机试真题【小学英语老师批改作文】

qq_45776114的博客 923

视频隐私脱敏工程化:CSRT/KCF追踪算法在本地推理中的实现与边界

在短视频内容合规审查中,动态遮挡(Dynamic Masking)是高频且高耗时的环节。传统手动关键帧打码不仅效率低下,且在目标快速移动或遮挡时极易出现遮罩漂移。本文从计算机视觉工程角度,解析基于CSRT与KCF算法的目标追踪方案在视频隐私处理中的技术路径、性能权衡及落地实践。

Mysssone的博客 231

C#与大数据分析:如何通过上位机进行设备故障诊断与预测

设备故障诊断是通过对设备的运行状态数据进行分析,识别和确认故障的类型和位置。而设备故障预测则是通过对设备的历史数据和运行状态进行分析,预测设备何时可能出现故障,从而进行预防性维护。数据采集:通过各种传感器、PLC、嵌入式设备等采集设备运行数据,如温度、压力、振动、转速、功率等。数据预处理:对采集到的数据进行清洗、去噪、缺失值处理、标准化等操作,以确保数据质量。特征工程:从原始数据中提取出有助于故障诊断和预测的特征,例如统计特征、时域特征、频域特征等。数据分析与建模。

这里只有干货:从 Modbus 通信到 MES 对接,从 YOLO 训练到工控机部署,带你搞定工业软件开发全流程。 1061

6 款电商 AI 图片生成软件实测|国内 + 跨境卖家工具清单

电商 AI 作图工具已经从 "能不能用" 进入了 "好不好用" 的阶段。对于绝大多数卖家而言,现在的 AI 工具已经可以覆盖 60%-80% 的基础商品图需求,显著降低拍摄和设计成本。选择工具的核心逻辑不是 "哪款最强",而是 "哪款最适配你的品类、平台规模和团队能力"。垂直电商工具胜在工作流效率,通用生图工具强在创意上限,模板类工具赢在上手速度。建议根据自身业务阶段,搭配 1-2 款主力工具 + 1 款辅助工具,形成适合自己的视觉生产流程。

Mardi_Ladin的博客 405

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

我用 GPUWorks 在 M1 Pro 上搭了个发票识别原型

公司里经常要看电子发票。我想先做个小原型:把 PDF 发给一个自己部署的图文模型,让它提取发票类型、日期、交易双方和金额,再把结果交给同事核对。这个原型不用先接财务系统,先看看从部署到调用要走多少步,模型返回的内容能不能帮上忙。

鸽芷咕的博客 2万+

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

您您这可以把问小白的多个会话比如说。左侧的多个会话一次性导出吗?不是单条会话里面的多次会对话。AI导出鸭

第三层是格式编译层。这个决策背后的判断很清晰:一个批量导出工具的价值,不在于“试三次”,而在于你真正用它处理了几十份技术文档、访谈记录或课程讲义之后,它是否值得留在你的工作流里。问小白的会话列表通过分页接口加载,AI导出鸭 在页面运行时建立旁路监听,捕获每一次分页请求返回的完整对话清单,包括会话 ID、标题、时间戳和隐藏的元数据字段。让AI导出回归优雅——这句话说的是:导出不该是体力活,而应该是一次完整的、可预期的文件交付。注意:这里的“批量”指的是左侧列表里的多个独立会话,不是一条会话内的多轮对话。

laoyunsi的博客 250

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

【从零理解 Spring AI · 12】MCP 的两种角色:做客户端还是做服务端

上一篇讲了 MCP 的概念:标准协议、三大角色、M+N 替代 M×N。

nice_lcj520的博客 503

河道漂浮物目标检测数据集

目标检测,yolo,河道漂浮物目标检测数据集

DL_data_set的博客 205

AI Agent之核心框架

A: 显式 Thought 有三类价值:可解释性(便于人类审计)、可调试性(定位哪一步选错工具)、学习信号(可做监督微调或评估中间步骤质量)。ReAct 把推理与 可执行行动 绑定,每一步行动后都有 真实 Observation 反馈,从而用工具结果约束生成,降低闭卷幻觉。做完不等于结束——还要 评估做得好不好,把 教训 记下来,下次 带着教训重试,反思作为 记忆,影响后续尝试的策略。工作流程:Action → Evaluation → Reflection → Retry。A: 普通 CoT 只在。

剑雨巍巍的博客 201

AI 应用开发工程师技术实践:大模型接入、通用组件封装与性能优化

本文提出AI应用从PoC到生产的核心挑战:模型调用的持续可用、可控与可优化。通过构建统一LLM网关实现多供应商路由与故障转移,封装对话、工具调用与RAG组件以解耦业务逻辑,结合前缀缓存、批处理与流式背压治理等性能优化手段,形成“接通→接稳→接快”的工程路径,最终以工程化能力决定AI应用的生产可用性。

2301_79189962的博客 560

AI前沿日报 · 2026-11-04 | 祛魅时刻:Astra“纯读权重“神话的崩塌

①Astra"裸权重通吃"被spaCy创始人Honnibal精准祛魅——仅1/3实验真裸读,数学能力提升依赖Python+50次迭代;②Simon Willison用Qwen 3.8-27B端侧复现权重空间编程;③Nvidia开源Auto-Ontology自动知识图谱;④$800开源全域抓取机器人Stringman;⑤OpenAI悄然重开Codex训练开关引信任危机;⑥DeepMind发布Gemini 4 Argon机器人基础模型;⑦美国科技巨头隐性AI债务达3.2万亿美元,6个月增90%。

johnsong2009的博客 577

大模型 Embedding 与向量相似度详解

Embedding 解决的问题:计算机不懂文字,但懂数字│▼文本 → 向量(1024维浮点数数组)│▼相似度解决的问题:怎么判断两个向量(文本)有多接近│▼余弦相似度:看向量方向的夹角,越接近0°越相似│▼最终效果:语义搜索——理解意思,而非字面匹配一句话总结:Embedding 把文字变成数字,余弦相似度比较数字的方向,两者结合实现了"理解语义"的搜索。

T3165919332的博客 92

GPT-1 架构和计算细节

下面配合框图,对 GPT-1 的每个组件做公式展开 + 数值实例(配置:12 层 × 768,12 头,FFN 3072,词表 40478,共 117M 参数)。GPT-1 把翻译模型的编码器-解码器砍掉一半,只留解码器,然后以"预测下一个词"为目标在 BooksCorpus 上预训练。与 2017 原版的四个架构差异(框图中标 ★):h0=E[token]+Epos[position],E∈R40478×768, Epos∈R512×768h^0 = E[\text{token}] + E_{pos}[\

eloudy的专栏 283

终端 AI 审计与 “龙虾” 类智能体风险治理:从可见性到闭环溯源

生成式 AI 办公普及之后,数据泄露风险逐步下沉到终端。员工将合同、源代码、客户资料粘贴至公有大模型,以及龙虾(OpenClaw)这类本地开源 AI 智能体的滥用,成为企业安全新挑战。传统网络边界防护存在审计盲区,本文从风险链路拆解、核心能力模型、分级治理策略、落地踩坑点以及技术局限性多角度,分享终端侧 AI 安全治理的实践思路。

2401_86491085的博客 642

2.53 基于极稀疏指纹的室内定位注意力图元学习

该论文发表于IEEE Transactions on Mobile Computing(TMC)2026年6月,面向极稀疏指纹条件下的WiFi室内定位,针对指纹采集人力成本高、标记指纹稀缺时定位精度大幅下降的痛点,提出注意力图元学习模型AGML(Attentional Graph Meta‑Learning),结合图神经网络、元学习、两种指纹数据增强与分布对齐技术,在标记指纹极少的场景实现高精度室内定位,同时公开了多套真实+仿真定位数据集用于基准测试。场景:二维室内空间,障碍物造成信号遮挡,

weixin_42963026的博客 339

语音识别与语音合成的技术原理及应用

语音识别 #语音合成 #人工智能 #大模型。语音识别与语音合成的技术原理及应用。一、语音识别的核心原理。二、语音合成的核心原理。三、工程落地的主要难点。五、需要关注的现实问题。

weixin_62919816的博客 215
上一篇: Nanobot 从 AgentLoop 启动看怎么驱动大模型运行
下一篇: Prompt Engineering 和 Context Engineering 和 Harness Engineering 区别和联系
鸿乃江边鸟
博客等级 码龄6年 3746粉丝 235原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值