使用PocketFlow构建Web Search Agent

news2025/5/18 22:47:33

前言

本文介绍的是PocketFlow的cookbook中的pocketflow-agent部分。

回顾一下PocketFlow的核心架构:

image-20250509114110295

每一个节点的架构:

image-20250509114123433

具体介绍可以看上一篇文章:

“Pocket Flow,一个仅用 100 行代码实现的 LLM 框架”

实现效果

这个Web Search Agent是干嘛的呢?

这个Agent会判断你输入的问题是否需要搜索网络,如果需要会搜索网络之后回答。

效果如下图所示:

image-20250513135723662

现在就让我们看看是怎么实现的吧!!

Web Search Agent实现

先看看这个Web Search Agent的整体架构。

Web Search Agent包含三个节点:

Web Search Agent
判断节点
网络搜索节点
回答节点

image-20250513143402522

这三个节点的关系如下图所示:

search
answer
context
判断节点
网络搜索节点
回答节点

image-20250513140049115

现在来看整体流程。

首先创建节点并连接:

def create_agent_flow():
    """
    Create and connect the nodes to form a complete agent flow.
    
    The flow works like this:
    1. DecideAction node decides whether to search or answer
    2. If search, go to SearchWeb node
    3. If answer, go to AnswerQuestion node
    4. After SearchWeb completes, go back to DecideAction
    
    Returns:
        Flow: A complete research agent flow
    """
    # Create instances of each node
    decide = DecideAction()
    search = SearchWeb()
    answer = AnswerQuestion()
    
    # Connect the nodes
    # If DecideAction returns "search", go to SearchWeb
    decide - "search" >> search
    
    # If DecideAction returns "answer", go to AnswerQuestion
    decide - "answer" >> answer
    
    # After SearchWeb completes and returns "decide", go back to DecideAction
    search - "decide" >> decide
    
    # Create and return the flow, starting with the DecideAction node
    return Flow(start=decide) 

决定节点的prep:

image-20250513140356232

获取上下文(当前还没有上下文)与问题。

决定节点的exec:

image-20250513140549001

获取prep的问题与上下文,判断是搜索还是回答。

看看这里的提示词:

 prompt = f"""
### CONTEXT
You are a research assistant that can search the web.
Question: {question}
Previous Research: {context}

### ACTION SPACE
[1] search
  Description: Look up more information on the web
  Parameters:
    - query (str): What to search for

[2] answer
  Description: Answer the question with current knowledge
  Parameters:
    - answer (str): Final answer to the question

## NEXT ACTION
Decide the next action based on the context and available actions.
Return your response in this format:

```yaml
thinking: |
    <your step-by-step reasoning process>
action: search OR answer
reason: <why you chose this action>
answer: <if action is answer>
search_query: <specific search query if action is search>
```
IMPORTANT: Make sure to:
1. Use proper indentation (4 spaces) for all multi-line fields
2. Use the | character for multi-line text fields
3. Keep single-line fields without the | character
"""

注意这里作者使用的是yaml返回而不是json,这是因为大模型返回json出错的概率更高一点,我也遇到过好多次json返回错误。

返回大模型的决定:

image-20250513141120743

决定节点的post:

image-20250513141209079

会返回search,转到Search节点。

Search节点的prep:

image-20250513141327104

从共享存储中获取要搜索的内容。

Search节点的exec:

image-20250513141511716

开始执行网络搜索,这里作者使用的是duckduckgo,直接使用很方便,当然也可以使用brave,免费订阅一个月2000次的额度。

image-20250513141729933

将结果合并之后返回。

Search节点的post:

image-20250513141806169

将网络搜索的结果放到共享存储的context中。

image-20250513142038766

返回决定节点。

根据获取的上下文做判断:

image-20250513142149296

模型决定回答:

image-20250513142242161

回答节点的prep:

image-20250513142315344

从共享存储中获取问题与上下文。

回答节点的exec:

image-20250513142509635

获取问题与上下文,现在的上下文变成之前的答案:

image-20250513142436528

回答的提示词:

 prompt = f"""
### CONTEXT
Based on the following information, answer the question.
Question: {question}
Research: {context}

## YOUR ANSWER:
Provide a comprehensive answer using the research results.
"""

回答节点的post:

image-20250513142625799

最终回答从共享存储中取出:

print(shared.get("answer", "No answer found"))

image-20250513142811238

以上就将这个流程走通了。

整体的流程图大概如下所示:

flowchart TD
l[开始] --> a
a[决定节点的prep:获取上下文(当前还没有上下文)与问题。] --> 
b[决定节点的exec:获取prep的问题与上下文,判断是搜索还是回答。] -->
c[决定节点的post:返回search或answer] -->|search| d[网络搜索节点的prep:从共享存储中获取要搜索的内容。] 
c -->|answer|e[回答节点的prep:从共享存储中获取问题与上下文。]
d -->f[网络搜索节点的exec:获取网络搜索结果]
f -->g[网络搜索节点的post:将网络搜索的结果放到共享存储的context中。]
g -->a
e -->i[回答节点的exec:根据获取的上下文回答问题]
i -->j[回答节点的post:从共享存储中取出最终回答]
j--> k[结束]

image-20250513150525245

以上就是这个Web Search Agent的工作流。

由于我个人比较喜欢C#,我也用C#复刻了一个,下期介绍如何使用C#复刻一个。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2378834.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

记录:echarts实现tooltip的某个数据常显和恢复

<template><div class"com-wapper"><div class"func-btns"><el-button type"primary" plain click"showPoint(2023)">固定显示2023年数据</el-button><el-button type"success" plain cli…

八股文--JVM(1)

⭐️⭐️JVM内存模型 程序计数器&#xff1a;可以看作是当前线程所执行的字节码的行号指示器&#xff0c;用于存储当前线程正在执行的 Java 方法的 JVM 指令地址。如果线程执行的是 Native 方法&#xff0c;计数器值为 null。是唯一一个在 Java 虚拟机规范中没有规定任何 OutOf…

从RPA项目说说RPC和MQ的使用。

去年我负责一个 RPA&#xff08;机器人流程自动化&#xff09;项目&#xff0c;帮某电商公司搭建订单处理系统。项目里有个场景特别有意思&#xff1a;当用户下单后&#xff0c;系统需要同时触发库存扣减、物流调度、积分发放三个模块。一开始我们想都没想&#xff0c;直接用 R…

UUG杭州站 | 团结引擎1.5.0 OpenHarmony新Feature介绍

PPT下载地址&#xff1a;https://u3d.sharepoint.cn/:b:/s/UnityChinaResources/EaZmiWfAAdFFmuyd6c-7_3ABhvZoaM69g4Uo2RrSzT3tZQ?e2h7RaL 在2025年4月12日的Unity User Group杭州站中&#xff0c;Unity中国OpenHarmony技术负责人刘伟贤带来演讲《团结引擎1.5.0 OpenHarmony新…

Vue3——父子组件通信

在Vue开发中&#xff0c;组件通信是核心概念之一。良好的组件通信机制能让我们的应用更加清晰、可维护。 父传子defineProps defineProps是一个编译时宏&#xff0c;仅在内部可用&#xff0c;不需要显式导入。声明的 props 会自动暴露给模板。 还返回一个对象&#xff0c;其中…

游戏引擎学习第276天:调整身体动画

运行游戏&#xff0c;演示我们遇到的拉伸问题&#xff0c;看起来不太好&#xff0c;并考虑切换到更顶视角的视角 我们开始讨论游戏开发中的一些美学决策&#xff0c;特别是在处理动画方面。虽然我们是游戏程序员&#xff0c;通常不负责设计或艺术部分&#xff0c;但因为这是一…

从开发者角度看数据库架构进化史:JDBC - 中间件 - TiDB

作者&#xff1a; Lucien-卢西恩 原文来源&#xff1a; https://tidb.net/blog/e7034d1b Java 应用开发技术发展历程 在业务开发早期&#xff0c;用 Java 借助 JDBC 进行数据库操作&#xff0c;虽能实现基本交互&#xff0c;但需手动管理连接、编写大量 SQL 及处理结果集&a…

Mipsel固件Fuzzing小记

Mipsel固件Fuzzing小记 0x01 准备 1.1 安装必要工具链 首先需要安装 MIPS 交叉编译工具链和相关依赖&#xff1a; sudo apt-get install -y gcc-mipsel-linux-gnu g-mipsel-linux-gnu binwalk qemu-user-static afl这些工具分别用于&#xff1a;交叉编译、固件解包、二进制…

本土DevOps革命:Gitee如何撬动中国企业的数字化转型新动能

在数字化浪潮席卷全球的背景下&#xff0c;中国企业正面临前所未有的转型压力与机遇。随着《数据安全法》和《个人信息保护法》的全面实施&#xff0c;以及信创产业政策的深入推进&#xff0c;研发工具链的自主可控已成为关乎企业核心竞争力的战略命题。在这一关键赛道上&#…

强化学习入门:马尔科夫奖励过程二

文章目录 前言1、动作2、策略总结 前言 最近想开一个关于强化学习专栏&#xff0c;因为DeepSeek-R1很火&#xff0c;但本人对于LLM连门都没入。因此&#xff0c;只是记录一些类似的读书笔记&#xff0c;内容不深&#xff0c;大多数只是一些概念的东西&#xff0c;数学公式也不会…

JVM 双亲委派机制

一、从 JDK 到 JVM&#xff1a;Java 运行环境的基石 在 Java 开发领域&#xff0c;JDK&#xff08;Java Development Kit&#xff09;是开发者的核心工具包。它不仅包含了编译 Java 代码的工具&#xff08;如 javac&#xff09;&#xff0c;还内置了 JRE&#xff08;Java Run…

uniapp -- uCharts 仪表盘刻度显示 0.9999999 这样的值问题处理。

文章目录 🍉问题🍉解决方案🍉问题 在仪表盘上,23.8变成了 23.799999999999997 🍉解决方案 formatter格式化问题 1:在 config-ucharts.js 或 config-echarts.js 配置对应的 formatter 方法 formatter: {yAxisDemo1: function (

BGP团体属性

团体属性&#xff1a; 1、用于限制BGP路由的传递范围 2、类似于IGP协议中的tag值&#xff0c;用于对BGP路由实现标记。 团体属性的分类&#xff1a; 1、公共团体属性&#xff1a; Internet&#xff1a;默认所有路由都有该属性&#xff0c;具有该属性BGP路由发送给所有的BGP邻居…

Redis——三大策略

过期删除策略 Redis可以对key设置过期时间&#xff0c;因此需要有相应的机制将已过期的键值对删除 设置了过期时间的key会存放在过期字典中&#xff0c;可以用presist命令取消key过期时间 过期字典存储在redisDb结构中&#xff1a; typedef struct redisDb {dict *dict; …

Windows 操作系统使用 Tcping 命令检查目标主机端口是否开放

检查目标主机端口是否开放的方法已经很多了&#xff0c;网络上也有第三方网页版的检查工具&#xff0c;这篇文章给大家介绍一个实用小工具 Tcping 。 一、下载安装 Tcping 命令 Tcping 非 Windows 自带命令&#xff0c;我们需要下载 Tcping 可执行文件&#xff0c;然后将该文…

开源RTOS(实时操作系统):nuttx 编译

开源RTOS&#xff08;实时操作系统&#xff09;&#xff1a;nuttx 编译 手册&#xff1a;Installing — NuttX latest documentation 源码&#xff1a;GitHub - apache/nuttx: Apache NuttX is a mature, real-time embedded operating system (RTOS) Installing The fir…

python打包exe报错:处理文件时错误:Excel xlsx file; not supported

背景&#xff1a;最近用python写一个excel解析工具&#xff0c;然后打包成exe可执行文件的时候&#xff0c;遇到这样的问题 1.在我自己编译器运行是可以正常将上传后的excel进行解析&#xff0c;但是在打包成exe后&#xff0c;就无法正常解析excel 问题排查&#xff1a; 1.切换…

VUE3 -综合实践(Mock+Axios+ElementPlus)

目录 前言 目标 1.工程创建 2.Mock 2.1 配置Mock 扩 展 2.2 定义模拟数据 2.3 创建Mock服务器 3.导入ElementPlus 4.表格页面搭建 5.动态路由跳转 6.详情页面的制作 前言 基于前文 VUE3详细入门&#xff0c;我们对VUE3的基本使用有了初步的了解&#xff0c;下…

NDS3211HV单路H.264/HEVC/HD视频编码器

1产品概述 NDS3211HV单路高清编码器是一款功能强大的音/视频编码设备&#xff0c;支持2组立体声&#xff0c;同时还支持CC(CVBS)字幕。支持多种音频编码方式。该设备配备了多种音/视频输入接口&#xff1a;HD-SDI数字视频输入、HDMI高清输入&#xff08;支持CC&#xff09;、A…

LeetCode热题100--206.反转链表--简单

1. 题目 给你单链表的头节点 head &#xff0c;请你反转链表&#xff0c;并返回反转后的链表。 示例 1&#xff1a; 输入&#xff1a;head [1,2,3,4,5] 输出&#xff1a;[5,4,3,2,1] 示例 2&#xff1a; 输入&#xff1a;head [1,2] 输出&#xff1a;[2,1] 示例 3&…