当前位置: 首页 > ds >正文

使用PocketFlow构建Web Search Agent

前言

本文介绍的是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 answer2. If search, go to SearchWeb node3. If answer, go to AnswerQuestion node4. After SearchWeb completes, go back to DecideActionReturns:Flow: A complete research agent flow"""# Create instances of each nodedecide = DecideAction()search = SearchWeb()answer = AnswerQuestion()# Connect the nodes# If DecideAction returns "search", go to SearchWebdecide - "search" >> search# If DecideAction returns "answer", go to AnswerQuestiondecide - "answer" >> answer# After SearchWeb completes and returns "decide", go back to DecideActionsearch - "decide" >> decide# Create and return the flow, starting with the DecideAction nodereturn 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] searchDescription: Look up more information on the webParameters:- query (str): What to search for[2] answerDescription: Answer the question with current knowledgeParameters:- 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.xdnf.cn/news/6136.html

相关文章:

  • java为什么要实现自动装箱和拆箱
  • Promise.all静态方法
  • 乙酰基六肽-39/Silusyne 新型减肥活性肽,减少脂肪堆积
  • 火山引擎发展初始
  • 高效跨平台文件传输与管理的工具
  • SimScape物理建模实例2--带控制的单质量弹簧阻尼系统
  • PPT制作-平滑切换
  • logback 日志归档,解决主日志和归档日志分别定义不同的周期
  • Manus 开放注册:AI 智能体领域的新起点
  • 岩土拉压试验机
  • ​​华为云服务器:智能算力网格​
  • 计数循环java
  • 24年面试问题总结记录
  • 光学(1)
  • CVE-2025-31258 macOS远程视图服务沙箱逃逸漏洞PoC已公开
  • 【老飞飞源码】新版高清飞飞源码+数据库+客户端+服务器端完整文件打包
  • C++语法基础(下)
  • 【经验总结】【乘法替换方法】
  • coco数据集mAP评估
  • function call介绍和实现(以DeepSeek为例)
  • 2025高质量数据集实践指南
  • 无人机避障——(运动规划部分)深蓝学院动力学kinodynamic A* 3D算法理论解读(附C++代码)
  • 聊聊JetCache的CachePenetrationProtect
  • Baklib知识中台驱动企业智慧服务升级
  • WebGIS 开发中的数据安全与隐私保护:急需掌握的要点
  • MongoDB 的主要优势和劣势是什么?适用于哪些场景?
  • 安卓刷机模式详解:Fastboot、Fastbootd、9008与MTK深刷
  • 19.three官方示例+编辑器+AI快速学习webgl_buffergeometry_points
  • 缺乏需求变更的影响评估,如何降低项目风险
  • AI 赋能数智孪生:更快、更智能、更易用