从零推导多 Agent 协作网络 (Flow Agent)

拨开迷雾看本质:从零推导多 Agent 协作网络 (Flow Agent)

1. 为什么我们需要多个 Agent 协作?

在简单的场景中,一个拥有各种工具的单体 Agent(如我们在 react.md 中推导的那样)就足够了。

但当业务变得复杂时,单体 Agent 很容易出现一些系统性问题:

  1. Prompt 爆炸:如果你让一个 Agent 既懂写代码、又懂审查、还要会发邮件,它的 System Prompt 会长到让大模型"失焦"。
  2. 工具灾难:如果给它塞 50 个工具,模型根本选不过来,甚至会把查天气的工具和删数据库的工具搞混。

朴素的想法:

既然一个 Agent 搞不定,我们就把任务拆分给多个 专职 的 Agent。

假设我们手写一个极简的"多 Agent 协作"代码:

go 复制代码
// 朴素的多 Agent 协作
func RunMultiAgent(input string) {
    // 1. 经理分析需求
    managerPlan := managerAgent.Run(input)
    
    // 2. 如果需要写代码,就调 Coder
    if strings.Contains(managerPlan, "code") {
        codeResult := coderAgent.Run(managerPlan)
        // 3. 代码写完,调 Reviewer
        reviewResult := reviewerAgent.Run(codeResult)
        fmt.Println("最终结果:", reviewResult)
    }
}

看起来很清晰?但这只是在写 硬编码的脚本 ,一旦业务链路变长、需要 Agent 之间互相讨论(比如 Reviewer 觉得不行,打回给 Coder 重新写),这种用 if/else 手工调度的代码就会彻底失控。


2. 第一步演进:解决硬编码调度(Transfer 机制)

问题场景 :

我们希望 Agent 能够 自主决定 下一个任务交给谁,而不是在外部代码里用 if/else 写死。比如 Manager 发现问题很复杂,它自己决定"把任务转交(Transfer)给 Coder"。

批判性思考 :

要让 Agent 自主转交,我们需要赋予它一种"交接棒"的能力。

最自然的想法是:把"转移给另一个 Agent"做成一个 Tool 塞给当前 Agent。

引入 Transfer 机制后的本质代码:

go 复制代码
// 框架层:定义一种特殊的工作流引擎
type FlowEngine struct {
    agents map[string]Agent
}

func (e *FlowEngine) Run(startAgentName string, history []Message) {
    currName := startAgentName
    
    for currName != "" {
        agent := e.agents[currName]
        
        // 执行当前 Agent
        resp := agent.Run(history)
        history = append(history, resp)
        
        // 检查这个 Agent 是否调用了特殊的 Transfer 工具
        if resp.HasToolCall("TransferTo") {
            // 解析它想转给谁
            nextAgent := resp.ToolCalls[0].Args["target_agent"]
            currName = nextAgent // 接力棒传下去了!
        } else {
            // 如果没调 Transfer,说明任务结束了
            currName = ""
        }
    }
}

在这个模型下,Coder 和 Reviewer 可以互相 Transfer,形成一个死循环辩论,而你不需要在外部写任何一行 while 循环。

补充:Transfer 的数据契约

上面的伪码默认 Transfer 只是在"换一个 Agent 继续读同一段 history"。这能跑通,但也会自然引出一个工程问题:交接时到底传什么?

  1. 如果只传 history,结构化状态(例如计划、约束、工具调用的结果对象)会被迫编码进文本,形成隐式协议。
  2. 如果额外传 state,就需要一个明确的 Schema(强类型或至少可校验),否则状态会在多个 Agent 之间逐步漂移。

更稳妥的理解方式,是把 Transfer 的 "数据契约" 拆成两层:一层是 显式控制面 ,另一层是 隐式数据面 。

  1. 显式控制面:Transfer 的职责是表达 "把控制权交给谁" 。它可以额外携带少量观测信息(例如 reason / tag),用于复盘与可观测,但不应承载业务数据,否则交接会退化为 "在 Agent 之间传包",并在链路变长后迅速演化出不可维护的隐式协议。
  2. 隐式数据面:上下文与状态应放在一个共享的会话容器里,并由框架贯穿整个协作链路。在 Eino 的实现中,Transfer 的显式载荷非常薄(目标 Agent 名),下一个 Agent 之所以仍能接着跑,是因为它继续共享同一个 runCtx(RootInput + Session.Events + Session.Values)。因此,许多看起来像 "state" 的信息,最终更像是 "会话 KV" 或 "事件序列" 的投影,而不是 Transfer 参数本身。

若要把这套模式做得更工程化,改进方向通常也落在共享容器上,而不是往 Transfer 参数里塞更多字段:

  1. 为 Session.Values 引入最小 Schema:至少做到可校验(版本号 + 必需字段),并明确 key 命名空间,避免不同 Agent 互相踩踏或让状态在链路中漂移。
  2. 把大对象从 history 搬走:history 更适合承载决策与结论;工具大结果、结构化中间态更适合放在 Session.Values 中,只在 history 里引用一个摘要或 ID。
  3. 将交接做成可观测事件:即使 Transfer 只传目标名,也应记录交接原因与关键上下文摘要,方便在事后回答 "为什么会跳到这个 Agent" 。

3. 第二步演进:解决"记忆错乱"与"鸡同鸭讲"(History Rewrite)

问题场景 :

在上面的交接棒模式中,大家共享同一个 history []Message。

想象一下:

  1. Coder 写了一段代码,并在 history 里记录了 assistant: 好的,代码写完了。
  2. 接力棒传给了 Reviewer。
  3. Reviewer 看到历史记录里写着 assistant: 好的,代码写完了。
    灾难发生了! Reviewer 会以为这句话是 自己 刚才说的!它会陷入精神分裂,无法区分哪句话是 Coder 说的,哪句话是自己说的。

批判性思考 :

大模型本身是没有"自我意识"的,它只认 Role(user/assistant/tool)。在多 Agent 网络中,不同 Agent 轮流扮演 assistant 会导致极其严重的身份混淆。

我们必须在交接棒时,翻译(Rewrite)历史。

引入 History Rewriter 后的本质解法:

go 复制代码
// 每次交接给新 Agent 前,把之前的记录"翻译"成用户口吻
func RewriteHistory(history []Message, nextAgentName string) []Message {
    var newHistory []Message
    
    for _, msg := range history {
        if msg.Role == "assistant" && msg.Author != nextAgentName {
            // 关键:把别的 Agent 说的的话,伪装成 User 对当前 Agent 说的背景信息
            rewritten := fmt.Sprintf("For context: [%s] said: %s", msg.Author, msg.Content)
            newHistory = append(newHistory, Message{Role: "user", Content: rewritten})
        } else {
            newHistory = append(newHistory, msg)
        }
    }
    return newHistory
}

通过这种转换,当 Reviewer 接手时,它看到的是 user: For context: [Coder] said: 好的,代码写完了。这样它的"自我认知"就不会错乱。

补充:History Rewrite 的工程代价

History Rewrite 是一个非常有效的 "兜底工程技巧",但它也会带来一些确定的代价:

  1. 上下文膨胀:每条消息都增加前缀与转述信息,链路越长越容易触发摘要/裁剪,从而改变后续 Agent 的判断依据。
  2. 语用漂移 :把别的 Agent 的发言改写成 user 背景,会把对等协作语境悄悄变成"用户指令 + 背景材料",影响模型的服从与质疑倾向。
  3. 注入面扩大 :如果子 Agent 输出包含诱导性文本,改写为 user 后风险更高;更稳的长期方向通常是结构化消息(保留 Author、RunPath、State)而不是纯字符串拼接。

4. 第三步演进:解决网络层级与事件风暴(Flow Agent Wrapper)

问题场景 :

随着 Agent 越来越多,扁平的"交接棒"不够用了。我们需要 层级结构(Supervisor 模式) 。

比如:MainAgent 包含子 Agent [Coder, Reviewer]。

这时候会出现两个典型痛点:

  1. 事件风暴:前端想要看到实时的打字机效果。但由于有多个嵌套的 Agent 轮流运行,到底该监听谁的输出?如果 Coder 和 Reviewer 在疯狂对骂,前端怎么把这些流式的事件(Event)有序地拼凑起来?
  2. 中断与恢复地狱 :如果 Coder 在中间调用工具挂起了。系统恢复时,你怎么知道是去唤醒 MainAgent 还是 Coder?

批判性思考 :

我们不能把多 Agent 当成简单的"平级函数互相调用"。我们需要一个 统一的包装器(Wrapper) ,把所有 Agent 包装成一样的接口。这个包装器负责:

  1. 拦截和聚合事件:把各个子 Agent 零散的事件打上时间戳和标签,汇聚到一根总的管子里。
  2. 拦截和翻译交接棒(Transfer):截获底层的 Transfer 事件,根据层级结构找到目标 Agent。
  3. 处理横切关注点(Cross-cutting Concerns) :在真实业务中,我们不仅要调 Agent,还要在每个 Agent 执行前后做打点追踪(Tracing)、权限校验、统一的异常捕获 。如果把这些代码塞进每个 Agent 内部,代码会极度臃肿。包装器正好可以在调用 realAgent.Run 前后,插入这些"横切逻辑"。

引入 Flow Wrapper (装饰器模式) 的本质代码:

我们需要一个 统一的包装器(Wrapper) ,把所有 Agent 包装成一样的接口。这个包装器负责:

  1. 统一输入输出:把零散的历史记录聚合成统一的输入,把乱飞的事件打上标签聚合成统一的输出流。
  2. 拦截和翻译交接棒(Transfer):截获底层的 Transfer 事件,根据层级结构递归调度下一个 Agent。
  3. 精准路由恢复(Resume):当收到恢复信号时,根据信号里的"目的地名字",决定是自己恢复,还是把信号透传给某个子 Agent。

在这个模型里,有一个经常被忽略但很关键的隐含前提:事件流的顺序需要足够稳定。否则前端渲染、日志对齐与恢复定位都会变得很困难。最简单的方式是保持 "单线程、深度优先" 的运行模型;一旦引入并发子 Agent,就需要额外的排序键(例如时间戳 + 运行路径 + 事件序号)来重建可重放顺序。

go 复制代码
// 框架层:代理包装器 (装饰器模式)
// 它包装了一个真实的 Agent,并为它处理历史翻译、事件转发、调度和恢复
type FlowAgent struct {
    realAgent Agent
    subAgents map[string]*FlowAgent
    name      string
}

// ---------------------------------------------------------
// 核心逻辑 1:如何组织输入和输出 (Run)
// ---------------------------------------------------------
func (f *FlowAgent) Run(globalHistory []Message, outChan chan Event) {
    // 【输入组织】:大模型容易精神分裂,所以在真正调底层 Agent 前,先把全局历史翻译成 "For context: [XXX] said: ..."
    rewrittenHistory := RewriteHistory(globalHistory, f.name)
    
    // 创建一个拦截器 channel,用来"偷听"真实 Agent 的动静
    innerChan := make(chan Event)
    go f.realAgent.Run(rewrittenHistory, innerChan)
    
    // 【输出组织】:循环处理底层冒出来的每一个事件
    for event := range innerChan {
        // 1. 打上当前 Agent 的水印,防止多层嵌套时前端分不清是谁说的
        event.AgentName = f.name 
        
        // 2. 拦截 Transfer 事件 (解决交接棒问题)
        if event.IsTransfer() {
            targetName := event.TransferTarget
            targetAgent := f.subAgents[targetName]
            
            // 递归调度!把接力棒传给下一个 Agent,并把事件无缝拼接到当前的总输出流中
            // 注意:因为 targetAgent 也是个 FlowAgent,所以它也会经历历史翻译、水印等过程
            targetAgent.Run(event.CurrentHistory, outChan)
            return // 当前 Agent 的任务被交接出去了,自己的 Run 结束
        }
        
        // 3. 普通事件,直接透传给外层的输出管子
        outChan <- event 
    }
}

// ---------------------------------------------------------
// 核心逻辑 2:如何解决中断与恢复地狱 (Resume)
// ---------------------------------------------------------
// resumeInfo 里包含了用户当初恢复时指定的"目标组件名字"
func (f *FlowAgent) Resume(resumeInfo ResumeInfo, outChan chan Event) {
    // 1. 如果中断发生在我这层(比如我自己调的某个 Tool 挂起了),那我自己恢复
    if resumeInfo.TargetAgentName == f.name {
        f.realAgent.Resume(resumeInfo, outChan)
        return
    }
    
    // 2. 如果中断不发生在我这层,说明中断发生在我的某个子孙节点里
    // 这时候我就像个路由器一样,查一下路由表(subAgents),把恢复信号原封不动地踢给对应的子节点
    targetAgent := f.subAgents[resumeInfo.TargetAgentName]
    if targetAgent != nil {
        targetAgent.Resume(resumeInfo, outChan)
        return
    }
    
    panic("找不到要恢复的 Agent!")
}

这个路由逻辑隐含了一个约束: TargetAgentName 必须稳定且唯一。层级网络里仅靠短名很容易冲突,更稳的做法通常是使用路径化的标识(例如 root.reviewer)或运行时分配的 ID,并在 checkpoint 里保存该标识以保证跨版本可恢复。

通过这个 FlowAgent 装饰器:

  • 输入/输出不再混乱 :外部的调用方只需要往最外层的 FlowAgent 传一次输入,监听一根 outChan。内部不管互相怎么 Transfer、怎么嵌套,最终所有的水滴都会被打上 AgentName 的标签,从这根唯一的管子里流出来。
  • 恢复不再迷路 :当外部调用 rootAgent.Resume 时,恢复信号会像网络数据包一样,沿着装饰器链一层层往下传,直到精准命中当初挂起的那个真实 Agent。

5. 补充思考:Flow 与 ReAct 的关系

在理解了 Flow 的包装器本质后,我们必须回答一个关键问题:被包装在里面的那个 realAgent 到底是什么?Flow 和 ReAct 是什么关系?

答案是:Flow 是编排层(网络),ReAct 是执行层(节点)。

在绝大多数情况下,Flow 包装的 realAgent 就是一个 ReAct Agent(也就是 Eino 里的 ChatModelAgent)。

ReAct 如何支撑了 Flow?

如果在 flow.md 里我们推导的 Transfer(交接棒)机制显得过于"理想化",那是因为我们没有把它和 ReAct 结合起来看。

  1. "思考然后交接"的闭环 :

    Flow 只是规定了"一旦出现 Transfer 事件,我就帮你转发"。但谁来产生这个 Transfer 事件?

    是底层的 ReAct Agent!ReAct Agent 的核心能力是 Reasoning + Acting。当它(模型)经过 Reasoning 发现自己搞不定,或者发现任务应该归属下一环节时,它就会选择调用一个特殊的 Tool(比如 TransferToAgent)。这个 Tool 的执行结果(Acting),就是吐出一个 Transfer Action,从而触发了外层 Flow 的调度。
    没有 ReAct 的智能决策,Flow 就是一个无法触发的死网络。

  2. 状态挂起的降维打击(宏观路由 vs 微观现场) :

    在 Flow 中,我们遇到了"中断与恢复地狱"。虽然 Flow 的 Resume 方法像路由器一样解决了"把信号踢给谁"的问题(Agent 层面的 Resume ),但最终那个子节点是怎么真正挂起和恢复的呢?

    这完全依赖于底层的 ReAct 框架!正如我们在 react.md 中推导的,ReAct 底层的图引擎(Graph)和状态机(State)才是真正保存 Checkpoint 和执行断点续传的功臣(工具层面的 Resume)。

    • ReAct 负责"微观现场":它记住"我正在调第 3 个工具,工具叫 AskUser,参数是什么"。
    • Flow 负责"宏观路由" :它记住"当前是 Coder 在干活,所以我要把唤醒信号发给 Coder,而不是 Reviewer"。
      Flow 站在了 ReAct 的肩膀上,把微观节点的挂起能力,扩展成了整个宏观网络的挂起能力。

6. 映射到现实:Eino 的 adk/flow.go 到底做了什么?

当我们审视真实的 adk/flow.go 时,你会发现它的核心逻辑就是我们上面推导的 第三步(Flow Wrapper) 。

Eino 的 flowAgent 是一个非常典型的 装饰器(Decorator) 模式。

  1. 解决"鸡同鸭讲" :L171-L200 rewriteMessage 函数,正是把其他 Agent 的 assistant 发言,改写成了 For context: [xxx] said: 的 user 发言,显著缓解了大模型的身份错乱问题。
  2. 解决"调度交接" :L468-L488 的 if destName != "" 逻辑。当底层的 Agent 吐出一个 Transfer 动作时,flowAgent 把它截获了,然后从自己的 subAgents 列表里找出目标 Agent,递归调用 subAIter := agentToRun.Run(...)。
  3. 解决"事件风暴与归属" :L429-L440 的 exactRunPathMatch 逻辑。因为多层嵌套,事件会在 channel 里乱飞。flowAgent 通常需要通过 RunPath 匹配,来决定哪些事件属于"我自己这层的运行",应该记录到 Session 里,哪些事件只是子节点的噪音,应该忽略。

6.1 深入 Transfer 工具的"原生注入"机制

在前面的推导中,我们把"转移给另一个 Agent"简单地说成是"塞给当前 Agent 的一个 Tool"。在 Eino 的真实实现中,这个注入过程隐藏着极深的架构考量。

当你调用 adk.SetSubAgents(ctx, parentAgent, []Agent{childAgent}) 构建 Flow 网络时,ChatModelAgent 会在准备执行上下文时( <adk/chatmodel.go#L636-L657> prepareExecContext)原生地注入 Transfer 能力:

go 复制代码
// 1. 获取所有可以 Transfer 的目标(子节点 + 父节点)
transferToAgents := a.subAgents
if a.parentAgent != nil && !a.disallowTransferToParent {
    transferToAgents = append(transferToAgents, a.parentAgent)
}

// 2. 如果存在可交接的目标,原生地注入 Instruction 和 Tool
if len(transferToAgents) > 0 {
    // 动态生成 Transfer 的专属提示词,大模型看到的极简版本大致如下:
    // "可用的其他 Agent:
    //  - Coder:负责写代码
    //  - Reviewer:负责审查
    // 决策规则:如果你自己搞不定,请调用 'transfer_to_agent' 函数,把活交出去。"
    transferInstruction := genTransferToAgentInstruction(ctx, transferToAgents)
    instruction = concatInstructions(instruction, transferInstruction)

    // 强行把 transfer_to_agent 工具塞进列表
    toolsNodeConf.Tools = append(toolsNodeConf.Tools, &transferToAgent{})
    
    // 【核心黑科技】:标记这个工具为"立即返回"类型,用于打断 ReAct 的内部死循环
    returnDirectly[TransferToAgentToolName] = true
}

为什么是硬编码原生注入,而不是用 Middleware 包装?

这揭示了 Transfer 的本质:它不是一个普通的"业务工具(Tool)",而是改变控制流的"底层汇编指令(JMP)"。

  • Transfer 必须修改底层 ReAct 引擎的控制流:一旦大模型调用了它,Agent 必须立刻结束当前生命周期(returnDirectly),把控制权交还给外层的 Flow 引擎去唤醒下一个节点。
  • Transfer 必须感知网络的父子拓扑:它需要动态知道自己当前挂载了哪些子节点、谁是父节点,而 Middleware 是一种无状态的请求拦截器,不适合维护图拓扑。

7. 批判性总结:Flow 究竟是"标准"还是"选项"?

在阅读完上述分析后,极易产生一个误解:既然 Flow 能解决这么多问题,是不是所有的多 Agent 协作底层都在用 flowAgent?

答案是:绝对不是。

为了搞清 adk/flow.go 和各种 Prebuilt Agent(预置模式)的关系,我们必须做一次彻底的隔离辨析。

7.1 核心辨析:flowAgent 只是一种特定的网络协议,不是底层标准!

在 Eino 的世界里,真正的大一统底层标准是 adk.Agent 接口 。只要你实现了 Run 和 Resume,你就是一个合法的 Agent。

而 flowAgent(通过 SetSubAgents 和 AgentWithOptions 创建),仅仅是为了实现 Transfer(异步变轨交接) 这种特定的协作模式,而特化出来的一种"网络协议包装器"。

这就好比:Agent 接口是 TCP/IP 协议,而 flowAgent 是 HTTP 协议。你可以用 HTTP 聊天,但你完全可以绕过 HTTP,自己用 TCP 写一套专用的 RPC(比如 Deep Agent 和 PlanExecute)。

7.2 映射到 Prebuilt 模式:谁在用,谁没用?

  1. Supervisor 模式:重度依赖 Flow

    • 源码证明 :在 adk/prebuilt/supervisor/supervisor.go 中,核心逻辑正是调用了 adk.SetSubAgents,并用 DeterministicTransferTo 包装了子节点。
    • 原因 :Supervisor 的灵魂就是"星型网络的 Transfer 变轨"(主管派活,小兵干完后强制 Transfer 回主管)。这种需求完美契合 flowAgent 解决的痛点(交接、历史改写),因此它是 Flow 体系的直接受益者。
  2. Workflow 模式:强行复用 Flow 马甲

    • 源码证明 :在 adk/workflow.go 中,框架对所有子节点调用了 toFlowAgent,但强制加上了 WithDisallowTransferToParent()。
    • 原因 :Workflow 其实不需要自由的 Transfer(它的顺序是写死的),但它需要复用 flowAgent 强大的"事件拦截与路由"能力(用来监听 BreakLoop 和 Exit)。所以它属于"阉割版复用"。
  3. Deep Agent 模式:彻底抛弃 Flow

    • 源码证明 :在 adk/prebuilt/deep/task_tool.go 中,DeepAgent 将子代理包裹时,使用的是 adk.NewAgentTool,完全没有调用 SetSubAgents 或使用 flowAgent。
    • 原因 :正如我们在 deep.md 中推导的,Deep Agent 走的是 "函数调用栈(Tool Call)" 路线。主 Agent 是通过同步阻塞等待 task 工具返回,而不是通过 Transfer 异步交接。既然没有交接,就不需要 flowAgent 来改写历史、不需要它来接管路由。
  4. PlanExecute 模式:彻底抛弃 Flow

    • 源码证明 :在 adk/prebuilt/planexecute/plan_execute.go 中,它直接使用了最底层的 compose.NewChain 拼接 Graph,完全没有 flowAgent 的影子。
    • 原因:PlanExecute 是一台"强管控的白盒状态机",节点只能乖乖执行图框架按数组顺序塞过来的步骤,根本没有动态路由的自由,自然不需要 Flow。

7.3 最终结论

adk/flow.go 的本质,是 利用"装饰器"抹平了多 Agent 协作中,基于 Transfer 异步交接带来的网络拓扑与历史错乱差异 。

在开发者眼里,无论底层是多深的网络(主管管组长,组长管小兵),最外层看起来只是一个普通的、实现了 Run 和 Resume 的 Agent。所有的"交接棒(Transfer)"、"历史记忆翻译"和"事件流合并",都被 flowAgent 这个包装器吃掉了。

它的代价是什么?

和 react.go 一样,隐含机制与约定较多。

当你的 Agent 网络出现问题(比如 A 传给 B,B 又传给 C,中间某个参数丢失了),你去查日志,会发现:

  1. 你的原始 Message 被 historyRewriter 悄悄改写了。
  2. 你的事件流被一层层的 flowAgent 包裹、过滤和复制。
  3. 如果你想实现一种并非基于 Transfer 工具的交接逻辑(比如基于外部事件触发),flowAgent 的这套体系会很难直接支持,因为它把交接逻辑深度绑定在了对 lastAction.TransferToAgent 的拦截上。

Eino 的 Flow 体系,为了提供"开箱即用的多 Agent 聊天网络",在内部做了极重的封装。它更适合构建类似 AutoGen 的聊天式 Agent 协作,但如果你的业务需要的是类似 Airflow 的 状态机工作流编排 ,用这套体系反而会感到束手束脚。


8. 进一步思考:这套模式的边界与更稳的演进

  1. 字符串改写是兜底,不是终局:当系统从 Demo 走向复杂链路,建议逐步迁移到结构化消息(保留 Author、RunPath、State、工具结果),把 "身份" 和 "状态" 从文本里抽出来。
  2. 显式 State 契约会迟早出现 :一旦链路上出现 Planner、Executor、Reviewer 等分工,纯 history 很快就不够用;越早把 State Schema 明确,越少靠约定字符串解析续命。
  3. 并发引入前先定义可重放顺序:如果要让子 Agent 并行,先定义事件排序键与重放策略,否则流式 UI、日志复现与 resume 对齐都会变成难题。
  4. 外部事件驱动需要解耦 Transfer:当交接来自外部系统(队列、Webhook、定时器)而不是模型的 tool call,交接机制需要从 "拦截 lastAction" 演进为更通用的调度接口。
相关推荐
零基础1233 分钟前
LLM Agent 驱动的物模型构建:从设备手册到边缘接入的自动化实践
运维·人工智能·经验分享·python·自动化
这张生成的图像能检测吗7 分钟前
(论文速读)LINN:液体神经网络与脉冲神经元融合的可解释旋转机械故障诊断
人工智能·深度学习·神经网络·故障诊断
东方佑12 分钟前
v24 (Hybrid2Fast) 架构与实验报告
人工智能·深度学习·语言模型·自然语言处理·架构
阿部多瑞 ABU14 分钟前
重复的辩证法:从哲学僵尸到历史唯物主义——论意识、重复与人类解放
人工智能·ai写作
枫叶丹419 分钟前
从一次推理请求出发:模型、显存、网络与服务系统如何共同决定性能
网络·人工智能·chatgpt·开源·agent·codex
YangYang9YangYan23 分钟前
2027 秋招|应用统计学专业投递快消市场部,岗位 JD 拆解与统计能力落地
人工智能·数据分析
lie..24 分钟前
30天从零开始学AI应用开发(Day 17):ChromaDB 上手:给本地文档建一个“外挂大脑”
数据库·人工智能·oracle
deepdata_cn27 分钟前
Seedance 2.5如何敲开工厂车间的门
人工智能
一水鉴天27 分钟前
差-余-残三词体系:术语定稿与设计方案 20261004(豆包)
人工智能
杭州领祺科技37 分钟前
27 号令横向隔离落地清单:储能边缘计算网关 ≠ 电力专用网闸,算电协同中心安全分区/纵向加密/SPDnet 怎么配
人工智能·安全·网络安全·边缘计算·储能·电力·电力监控