news 2026/9/17 22:37:10

基于 Pydantic AI 与 Brave Search API 构建高级网络搜索 Agent:从 CLI 到 Live Agent Studio 的完整实践

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
基于 Pydantic AI 与 Brave Search API 构建高级网络搜索 Agent:从 CLI 到 Live Agent Studio 的完整实践

基于 Pydantic AI 与 Brave Search API 构建高级网络搜索 Agent:从 CLI 到 Live Agent Studio 的完整实践

【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents

本篇技术指南围绕 oTTomator Live Agent Studio 开源仓库中的pydantic-ai-advanced-researcher项目展开,完整讲解如何利用 Pydantic AI 框架与 Brave Search API 构建一个"先搜索、后总结"的高级网络研究 Agent。读完本文,你将掌握该 Agent 的三种运行形态(命令行 CLI、Streamlit Web 界面、Live Agent Studio API 集成)的搭建与配置方法,理解其依赖注入、工具调用、流式输出与消息历史管理的底层实现,并可直接复用到自己的 Pydantic AI 项目中。

项目概览与核心设计思路

该 Agent 的核心价值在于它并非简单地把用户问题直接丢给 LLM,而是通过 Brave Search API 先抓取与查询相关的网页结果,将其整理成精炼的文本摘要后,再交给 LLM 作为事实依据生成最终回答。用原文档的话说,它"利用 Brave API 总结从搜索查询中找到的一批文章,生成一段简洁而全面的信息,供 LLM 回答用户问题"。

仓库中该目录下共提供三个可运行版本:

版本入口文件适用场景
命令行版本web_search_agent.py本地调试、服务端批处理,同时支持 GPT 与 Ollama 本地模型
Streamlit Web 界面streamlit_ui.py提供带文字流式输出与聊天历史的浏览器交互界面
Live Agent Studio 集成版studio-integration-version/作为参考实现,展示 API 端点、数据库、鉴权与消息历史管理的完整集成

其中studio-integration-version目录包含将 Agent 接入 Live Agent Studio 的精确代码,如果你打算把自己的 Agent 集成进该平台,可直接将其作为参考实现。

环境准备与安装

前置条件

  • Python 3.11+
  • OpenAI API Key(使用 GPT 模型时需要)
  • Ollama(可选,用于本地 LLM 推理)
  • Brave Search API Key

安装步骤

首先获取仓库并进入项目目录:

git clone https://github.com/coleam00/ottomator-agents.git cd ottomator-agents/pydantic-ai-advanced-researcher

说明:本文讨论的pydantic-ai-advanced-researcher目录位于当前仓库根目录下,实际路径为pydantic-ai-advanced-researcher/

建议在 Python 虚拟环境中安装依赖:

pip install -r requirements.txt

该命令会安装 Pydantic AI、Streamlit 及其全部依赖。根据仓库中的 requirements.txt,关键依赖版本包括:pydantic-ai==0.0.10(含pydantic-ai-slim)、streamlit==1.40.2openai==1.57.0httpx==0.28.0python-dotenv==1.0.1logfire==2.6.2devtools==0.12.2,以及 pandas、numpy、altair 等 Streamlit 依赖链。若仅运行命令行版本,这些依赖足以满足;Studio 集成版还需 fastapi、uvicorn、supabase 等(见下文)。

环境变量配置

.env.example重命名为.env,然后填入密钥与模型偏好:

OPENAI_API_KEY=your_openai_api_key # 仅在使用 GPT 模型时需要 BRAVE_API_KEY=your_brave_api_key LLM_MODEL=your_chosen_model # 例如 gpt-4、qwen2.5:32b

其中LLM_MODEL是全局模型开关:gpt开头(不区分大小写)则走 OpenAI 官方模型;否则走 Ollama 本地模型。这一判定逻辑直接体现在 web_search_agent.py 中:

llm = os.getenv('LLM_MODEL', 'gpt-4o') client = AsyncOpenAI( base_url = 'http://localhost:11434/v1', api_key='ollama' ) model = OpenAIModel(llm) if llm.lower().startswith("gpt") else OpenAIModel(llm, openai_client=client)

值得注意的实现细节是:Ollama 场景并非使用独立的 Pydantic AI Ollama provider,而是借助 Ollama 自带的 OpenAI 兼容端点(http://localhost:11434/v1),通过OpenAIModel统一接入。这种设计让两种模型共用同一套 Agent 代码,切换成本极低。LLM_MODEL未设置时默认回退到gpt-4o;在 Live Agent Studio 平台上,该 Agent 使用的正是gpt-4o-mini

Agent 核心实现:依赖注入与 Web 搜索工具

Agent 与依赖类型定义

Agent 本体通过 Pydantic AI 的Agent类构建,见 web_search_agent.py:

@dataclass class Deps: client: AsyncClient brave_api_key: str | None web_search_agent = Agent( model, system_prompt=f'You are an expert at researching the web to answer user questions. The current date is: {datetime.now().strftime("%Y-%m-%d")}', deps_type=Deps, retries=2 )

这里的Deps是 Pydantic AI 的依赖注入类型:把httpx.AsyncClient(负责实际发 HTTP 请求)和 Brave API Key 打包注入工具函数。system_prompt使用 f-string 动态注入当前日期,帮助 LLM 理解时间上下文,避免回答过期信息。retries=2表示 Agent 在工具调用出错时最多自动重试 2 次。

search_web 工具:请求、格式化与兜底

search_web是注册到 Agent 上的唯一工具,见 web_search_agent.py:

@web_search_agent.tool async def search_web( ctx: RunContext[Deps], web_query: str ) -> str: """Search the web given a query defined to answer the user's question.""" if ctx.deps.brave_api_key is None: return "This is a test web search result. Please provide a Brave API key to get real search results." headers = { 'X-Subscription-Token': ctx.deps.brave_api_key, 'Accept': 'application/json', } with logfire.span('calling Brave search API', query=web_query) as span: r = await ctx.deps.client.get( 'https://api.search.brave.com/res/v1/web/search', params={ 'q': web_query, 'count': 5, 'text_decorations': True, 'search_lang': 'en' }, headers=headers ) r.raise_for_status() data = r.json() span.set_attribute('response', data)

其关键参数与行为如下:

  • 鉴权:通过请求头X-Subscription-Token携带 Brave API Key;
  • 请求参数count=5请求最多 5 条网页结果;text_decorations=True让 Brave 在文本中附加富文本修饰;search_lang=en限定英文搜索;
  • 可观测性:调用被logfire.span包裹,配合logfire.configure(send_to_logfire='if-token-present')——没有配置 Logfire token 时静默跳过,不会阻塞运行(仓库根目录的 requirements.txt 中logfire==2.6.2即服务于该能力);
  • 无 Key 兜底BRAVE_API_KEY缺失时返回一条提示性测试结果,而不是抛异常,保证 Agent 流程不断裂;
  • 结果精简:只取前 3 条(web_results[:3]),且要求同时具备titledescription才纳入,最终格式化为Title: ... / Summary: ... / Source: ...的纯文本块返回给 LLM。这体现了"先检索、再总结"的核心设计——LLM 拿到的不是原始 JSON,而是高度浓缩的搜索摘要。

命令行入口

web_search_agent.py 的main()展示了最小可运行范式:

async def main(): async with AsyncClient() as client: brave_api_key = os.getenv('BRAVE_API_KEY', None) deps = Deps(client=client, brave_api_key=brave_api_key) result = await web_search_agent.run( 'Give me some articles talking about the new release of React 19.', deps=deps ) debug(result) print('Response:', result.data)

以"React 19 发布相关文章"为示例查询,使用debug(result)输出完整结果对象(含工具调用、token 消耗等诊断信息),再用print打印最终回答。日常使用只需:

python web_search_agent.py

脚本会根据LLM_MODEL自动判定走 GPT 还是 Ollama,无需额外传参。

Streamlit Web 界面:流式输出与聊天历史

为什么 Streamlit 版默认只走 GPT

streamlit_ui.py 为 Agent 提供了带文字流式输出(text streaming)和聊天历史的浏览器界面。源码注释明确指出:当前 Pydantic AI 对 Ollama 的流式支持尚不完善,因此该示例默认固定使用gpt-4o(第 28 行model = OpenAIModel('gpt-4o')),Ollama 调用部分被注释掉。如果你希望 Streamlit 版也使用 Ollama,需要参照web_search_agent.py改成非流式的同步调用方式。

流式响应的实现

async def prompt_ai(messages): async with AsyncClient() as client: brave_api_key = os.getenv('BRAVE_API_KEY', None) deps = Deps(client=client, brave_api_key=brave_api_key) async with web_search_agent.run_stream( messages[-1].content, deps=deps, message_history=messages[:-1] ) as result: async for message in result.stream_text(delta=True): yield message

关键点:run_streammessage_history传入历史消息(最新提问除外),保证多轮对话的上下文连续性;stream_text(delta=True)按增量块产出文本,供前端逐字渲染。

界面组装

if prompt := st.chat_input("What would you like research today?"): st.chat_message("user").markdown(prompt) st.session_state.messages.append(UserPrompt(content=prompt)) ... async for chunk in prompt_ai(st.session_state.messages): response_content += chunk message_placeholder.markdown(response_content) st.session_state.messages.append(ModelTextResponse(content=response_content))

流程为:st.chat_input接收用户提问 → 追加UserPromptst.session_state→ 调用prompt_ai生成器流式更新占位符 → 完成后把ModelTextResponse写回历史。历史记录中roleusermodel-text-response的消息会在重渲染时按"人/AI"气泡展示。启动方式:

streamlit run streamlit_ui.py

启动前确保.env中已设置 OpenAI API Key(本版本默认不依赖 Ollama)。从源码结构看,仓库中还保留了一个演进中的 web_search_agent_streamlit.py,其工具逻辑与命令行版一致,可作为不同演进路线的对照参考。

Live Agent Studio 集成:FastAPI 端点 + Supabase 持久化

studio-integration-version/是面向生产平台的标准参考实现,包含三层能力:API 端点、数据库集成、鉴权与消息历史管理。

依赖增强与 Agent 依赖类型

该版本的依赖清单(studio-integration-version/requirements.txt,UTF-16 编码)在基础依赖之上增加了fastapi==0.115.6uvicorn==0.34.0supabase==2.11.0pydantic-ai==0.0.19等。其 web_search_agent.py 将依赖类型扩展为:

@dataclass class WebResearcherDeps: client: AsyncClient supabase: Client session_id: str brave_api_key: str | None

相比 CLI 版多出supabase客户端与session_id,并且在工具内部把"正在检索:{query}"的进度消息实时写入 Supabase 的messages表,让前端可以展示 Agent 的思考过程(见该文件第 70-77 行)。

FastAPI 端点与鉴权

web_search_endpoint.py 定义了完整的服务端:

  • 请求/响应模型AgentRequest包含queryuser_idrequest_idsession_idAgentResponse仅返回success布尔值;
  • 鉴权:使用 FastAPI 的HTTPBearer从请求头解析 Bearer Token,与API_BEARER_TOKEN环境变量比对;变量未设置时返回 500,Token 不匹配返回 401;
  • CORSallow_origins=["*"]全放开,便于前端跨域调用;
  • 消息历史fetch_conversation_historysession_id从 Supabase 拉取最近 10 条消息(order("created_at", desc=True).limit(10)后反转为时间正序),并转换为 Pydantic AI 的ModelRequest/ModelResponse结构传入message_history
  • 持久化store_message{"type": ..., "content": ..., "data": ...}结构写入messages表,用户的 query 与 Agent 的回答都会落库,回答附带request_id便于追踪;
  • 容错:Agent 执行抛异常时,仍会向会话写入一条道歉消息并返回success=False,保证平台侧能感知失败。

端点注册为POST /api/pydantic-search-agent。启动命令(默认端口 8001):

uvicorn web_search_endpoint:app --host 0.0.0.0 --port 8001

容器化部署

studio-integration-version/Dockerfile 基于ottomator/base-python:latest基础镜像,通过构建参数ARG PORT=8001暴露端口,安装依赖后执行uvicorn web_search_endpoint:app --host 0.0.0.0 --port ${PORT}启动。构建时需要设置的环境变量至少包括:SUPABASE_URLSUPABASE_SERVICE_KEYAPI_BEARER_TOKENBRAVE_API_KEYLLM_MODELOPENAI_API_KEY(使用 GPT 模型时)。

配置说明汇总

LLM 模型选择

通过LLM_MODEL环境变量在两类模型间切换,取值即模型名:

# OpenAI GPT(可以是任意 OpenAI 模型) LLM_MODEL=gpt-4o # Ollama 本地模型(需先下载对应模型) LLM_MODEL=qwen2.5:32b

模型判定规则为llm.lower().startswith("gpt")(见 web_search_agent.py):以gpt开头使用 OpenAI 官方服务,否则走 Ollama 的 OpenAI 兼容端点。相应地,GPT 场景需要配置OPENAI_API_KEY;Ollama 场景则要求本机 Ollama 服务已启动且模型已下载。

环境变量速查

变量必填说明
BRAVE_API_KEYBrave Search API 订阅密钥,通过请求头X-Subscription-Token传递
OPENAI_API_KEYGPT 模型时OpenAI 官方模型密钥
LLM_MODEL模型名,默认gpt-4o;以gpt开头判定为 OpenAI 模型
SUPABASE_URLStudio 集成版Supabase 项目地址
SUPABASE_SERVICE_KEYStudio 集成版Supabase 服务端密钥(service role key)
API_BEARER_TOKENStudio 集成版接口调用方需携带的 Bearer Token

常见问题排查

  1. Ollama 连接问题:先确认 Ollama 服务在运行(ollama serve),再确认模型已下载(ollama pull your_model_name)。同时注意代码中 Ollama 端点固定为http://localhost:11434/v1,需保证 Agent 进程与 Ollama 同机或可达;
  2. API Key 问题:检查.env中密钥是否填写正确,并确认 Brave API Key 额度充足——无 Key 时工具只会返回提示性测试结果而非真实搜索数据;
  3. 模型加载问题:Ollama 场景下,请确保机器内存(RAM)足以承载所选模型,内存不足时建议换用更小的模型,例如将qwen2.5:32b降级为更小的量化版本。

小结

本文从安装配置、核心实现、三种运行形态到生产集成,系统还原了pydantic-ai-advanced-researcher的完整技术细节。其核心范式——Deps依赖注入承载外部客户端与密钥、用@agent.tool注册搜索工具、把搜索结果精简为摘要文本再交给 LLM 推理——是 Pydantic AI 框架中构建"检索增强型"Agent 的典型样板。无论是本地快速体验(CLI + Ollama),还是交互式演示(Streamlit),乃至平台级部署(FastAPI + Supabase),都可以直接以本仓库代码为起点进行二次开发。相关源码入口:命令行版 web_search_agent.py、界面版 streamlit_ui.py、集成版 web_search_endpoint.py。

【免费下载链接】ottomator-agentsAll the open source AI Agents hosted on the oTTomator Live Agent Studio platform!项目地址: https://gitcode.com/GitHub_Trending/ot/ottomator-agents

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/17 22:34:43

基于STM32的PMSM电机FOC矢量控制实战:Simulink仿真与秋招简历项目

1. 别慌,先把“最快补齐简历项目”的路线算清楚说实话,秋招这个时间点,看到“只会STM32”这句话,我太能理解那种紧迫感了。很多同学在校期间学的是单片机基础——GPIO点灯、按键中断、串口打印、定时器PWM、I2C读个传感器&#xf…

作者头像 李华
网站建设 2026/9/17 22:31:27

基于神经网络与MPC的600MW锅炉智能燃烧优化控制系统开发

简介:面向600MW机组燃煤电厂热控与运行优化人员,这份doc文档系统阐述了锅炉智能燃烧优化控制系统的完整开发与应用方案。内容围绕不改造锅炉设备、仅依托DCS数据与先进算法的技术路线,重点讲解总体设计、通讯接口、控制逻辑、运行界面&#x…

作者头像 李华
网站建设 2026/9/17 22:30:54

区域电网规划课程设计全流程:从负荷校验到调压计算

简介:面向电气工程及电力系统专业学生、电网规划初学者的参考文档,以课程设计报告形式完整呈现区域电网规划设计全流程。资源仅含1个PDF文件,压缩包约473KB,内容紧凑、便于按章节查阅。目前已有61人浏览学习,适合作为课…

作者头像 李华