一步步教你用 Streamlit + Pydantic AI 搭建深度研究智能體應(yīng)用
如果你曾經(jīng)好奇如何通過結(jié)合智能的后端 Agent 和流暢的交互式前端來釋放人工智能的真正力量,那你來對地方了!今天,我們將把你的知識提升到一個新高度,通過將強大的 Pydantic AI 研究 Agent 作為后端,與動態(tài)的 Streamlit 界面作為前端進行整合。
AI 的世界發(fā)展得快如閃電。現(xiàn)代 Web 應(yīng)用早已不再是靜態(tài)網(wǎng)站。得益于 AI Agent 的魔力,它們變得智能、響應(yīng)迅速且交互性強。將 AI Agent 后端與用戶友好的前端結(jié)合,你就能打造出充滿活力的應(yīng)用:用實時網(wǎng)絡(luò)數(shù)據(jù)回答問題,自動化研究,讓用戶能實時與結(jié)果互動,而無需復(fù)雜的 Web 開發(fā)麻煩。
這次整合有什么令人興奮的地方?你將學(xué)會如何:
? 使用 Pydantic AI 和 Tavily 在后端協(xié)調(diào)強大的語言模型和實時搜索
? 通過 Streamlit 這個基于 Python 的美觀前端,展現(xiàn)所有這些能力
在本教程結(jié)束時,你將能夠:
? 理解從后端 Agent 邏輯到前端可視化的清晰路徑
? 將你的 AI Agent 和儀表板代碼復(fù)用并整合成一個統(tǒng)一的解決方案
? 獲得信心去實驗其他 AI 驅(qū)動的 Web 應(yīng)用
前提條件
雖然推薦閱讀這兩篇博客,但如果你時間有限,可以跳過 Python 儀表板那篇。不過我強烈建議閱讀 Pydantic AI 研究 Agent 那篇,因為我們會復(fù)用那里的很多代碼。不過別擔(dān)心,我在這兒也包含了關(guān)鍵概念的解釋,所以如果你想直接開始,也能跟得上,必要時可以回頭參考之前的文章。
回顧:已有的構(gòu)建模塊
在深入探討后端與前端無縫整合的樂趣之前 ??,讓我們回顧一下你在前兩篇教程中涵蓋的關(guān)鍵學(xué)習(xí)里程碑。如果你已經(jīng)迫不及待想動手,可以直接跳到下一節(jié)。
1. 用 Pydantic AI 和 Tavily 打造現(xiàn)代研究 Agent
在我們的第一次旅程中,我們解鎖了 AI 驅(qū)動的研究 Agent 世界。利用 Pydantic AI 進行類型檢查的結(jié)構(gòu)化數(shù)據(jù)管道,以及 Tavily 獲取實時網(wǎng)絡(luò)信息,你學(xué)會了:
? 環(huán)境設(shè)置:安裝必要的 Python 包,如 pydantic_ai 和 tavily_python,并管理 API 密鑰的配置文件。
? 設(shè)計穩(wěn)健的數(shù)據(jù)模型:利用 Pydantic 的 BaseModel 類定義搜索結(jié)果和 Agent 輸出的預(yù)期結(jié)構(gòu),確保數(shù)據(jù)始終干凈、可靠、可預(yù)測。
? 用 Tavily 搜索賦能:你將 Agent 連接到實時網(wǎng)絡(luò)數(shù)據(jù),掌握了異步查詢的藝術(shù),通過 Tavily 的 API 收集、過濾并返回相關(guān)內(nèi)容。
? 像 Agent 一樣思考:通過 Pydantic AI 的 Agent 類(以及可選的高級推理,使用像 Llama 3 或 GPT-4 這樣強大的 LLM),你編寫了能生成帶上下文、驗證和清晰結(jié)構(gòu)輸出的 Agent,這對任何研究流程都至關(guān)重要。
掌握這些概念將你的 Python 腳本技能提升到了 AI Agent 時代。重點在于后端智能、韌性和確保你的 AI 能在實時、雜亂的網(wǎng)絡(luò)數(shù)據(jù)上推理。
2. 用 Streamlit 構(gòu)建交互式儀表板
在我們的第二篇基礎(chǔ)博客中,焦點從計算智能轉(zhuǎn)向了引人入勝的展示。你學(xué)會了將靜態(tài)代碼轉(zhuǎn)變?yōu)槌錆M活力的 Web 應(yīng)用,使用的是 Streamlit:
? 輕松創(chuàng)建 Web 應(yīng)用:Streamlit 簡化了將 Python 腳本轉(zhuǎn)為響應(yīng)式網(wǎng)頁的過程,只需幾行代碼,無需 Flask、Django 或前端經(jīng)驗。
? 數(shù)據(jù)處理與 EDA:你練習(xí)了使用 pandas 和 numpy 等庫導(dǎo)入和處理數(shù)據(jù),進行探索性數(shù)據(jù)分析(EDA)以挖掘洞見。
? 動態(tài)可視化:Streamlit 的內(nèi)置圖表功能讓你能展示趨勢和比較,配合交互式控件和美觀的圖表。
? 直觀的用戶控制:下拉菜單、滑塊和側(cè)邊欄讓用戶能引導(dǎo)分析,為你的儀表板帶來真正的交互性。
整合一切
文件夾結(jié)構(gòu)
創(chuàng)建一個項目文件夾,包含以下文件:
Project-Folder/
├── ?? agent.py # 核心 AI Agent 實現(xiàn)
├── ?? app.py # Streamlit Web 界面
├── ?? requirements.txt # Python 依賴
├── ?? README.md # 項目文檔
└── ?? .env # 環(huán)境變量(不跟蹤)理解研究 Agent 后端代碼
現(xiàn)在你已經(jīng)了解了什么是研究 Agent,以及為什么 Pydantic AI 和 Tavily 是動態(tài)組合,讓我們詳細講解驅(qū)動這個智能研究助手的后端代碼。準備好一杯咖啡 ?,我們開始吧。
1. 導(dǎo)入語句:搭建舞臺
每個研究項目都從引入正確的庫開始。使用你之前創(chuàng)建的 agent.py 腳本。在腳本頂部,你需要導(dǎo)入 Python 庫和模塊,為代碼賦予必要能力:
from tavily import TavilyClient
import os
from dotenv import load_dotenv
from pydantic import BaseModel, Field
from typing import List
from pydantic_ai import Agent, Tool
from pydantic_ai.models.openai import OpenAIModel
from pydantic_ai.providers.openai import OpenAIProvider
import asyncio? from tavily import TavilyClient 引入客戶端以訪問 Tavily 的實時網(wǎng)絡(luò)搜索工具。
? os 和 load_dotenv 通過環(huán)境變量安全管理敏感的 API 密鑰,這是處理 API 的最佳實踐。
? pydantic.BaseModel/Field/List 強制執(zhí)行嚴格的數(shù)據(jù)驗證和清晰的 Agent 輸入輸出模式(就像一份合同:你的代碼始終知道期待什么數(shù)據(jù))。
? pydantic_ai 模塊讓你定義和運行 AI 驅(qū)動的 Agent,最終接入大型語言模型(LLM)和像網(wǎng)絡(luò)搜索這樣的外部工具。
? asyncio 啟用異步(非阻塞)代碼。網(wǎng)絡(luò)搜索在后臺進行,讓你的應(yīng)用保持快速和響應(yīng)性。
提示:始終使用環(huán)境變量(比如 .env靠近文件)來存儲密鑰,絕不硬編碼。
2. Tavily 客戶端初始化
load_dotenv()
client = TavilyClient(os.getenv("TAVILY_API_KEY"))? load_dotenv() 從 .env 文件加載變量,使你的 API 密鑰(如 TAVILY_API_KEY)可供腳本使用。
? TavilyClient() 用你的密鑰初始化,允許腳本向 Tavily 的網(wǎng)絡(luò)搜索 API 發(fā)出安全、認證的請求。
3. Pydantic 數(shù)據(jù)模型:結(jié)構(gòu)化輸出
class SearchResult(BaseModel):
title: str
url: str
snippet: str
class SearchResults(BaseModel):
results: List[SearchResult]
main_content: str = Field(descriptinotallow="The main content of the blog")目的:這些 BaseModel 類精確描述了 Agent 的輸出結(jié)構(gòu):搜索結(jié)果列表(SearchResult)和可選的主要內(nèi)容摘要(main_content)。好處:后端與前端之間的數(shù)據(jù)傳遞始終可預(yù)測、類型檢查、安全。最佳實踐:清晰定義的模型減少錯誤,提高可讀性,便于調(diào)試。
4. 編寫搜索邏輯:異步網(wǎng)絡(luò)搜索
async deftavily_search(query: str) -> dict:
search_response = client.search(query=query, search_depth="advanced", max_results=5)
return {
"results": [
{
"title": res["title"],
"url": res["url"],
"snippet": res["content"]
}
for res in search_response["results"]
]
}
asyncdefsearch_tool(query: str):
returnawait tavily_search(query)? 異步模式:async 關(guān)鍵字允許函數(shù)暫停而不阻塞整個程序,這對等待慢速網(wǎng)絡(luò) API 尤為重要。
? 為何兩個函數(shù)?tavily_search 執(zhí)行實際查詢和格式化,search_tool 是一個包裝器,方便直接插入 Agent 的工具接口。
? 定制化:最大結(jié)果數(shù)、搜索深度和結(jié)果格式都可輕松調(diào)整。
5. 模型與 Agent 設(shè)置:核心大腦
model = OpenAIModel('gpt-4.1', provider=OpenAIProvider(api_key=os.getenv('OPENAI_API_KEY')))
web_agent = Agent(
system_prompt="You are a research assistant. Answer questions using live web data and provide the main content explaining the topic in detail in markdown format with proper sections and sub-sections",
tools=[Tool(search_tool, takes_ctx=False)],
output_type=SearchResults,
model=model
)? OpenAI 模型:定義 LLM(如 GPT-4),使用從環(huán)境變量安全獲取的 API 密鑰。
? 系統(tǒng)提示:指導(dǎo) AI 的行為(例如,“作為研究助手,使用實時網(wǎng)絡(luò)數(shù)據(jù),以 markdown 格式提供詳細的主題解釋,包含適當?shù)恼鹿?jié)和子章節(jié)”)。可以嘗試調(diào)整系統(tǒng)提示,觀察響應(yīng)的質(zhì)量和細節(jié)變化,真的很有趣!
? 工具:將網(wǎng)絡(luò)搜索功能提供給 Agent,供其在需要實時數(shù)據(jù)時調(diào)用。
? 輸出類型:確保 Agent 僅返回符合 SearchResults 模式的響應(yīng)(超安全、干凈)。
? 注意:Pydantic AI 的輸出類型讓你避免了 LLM 通常無結(jié)構(gòu)的混亂輸出,真是救星!這就是為什么我個人更喜歡這個框架,而不是更流行的 LangChain 或 LangGraph。
6. Agent 運行器:整合一切
async def run_agent(query):
response = await web_agent.run(query)
return response.data.results, response.data.main_content目的:這個函數(shù)是你的 Web 前端調(diào)用的部分。它接收用戶的問題,讓 Agent 施展魔法,并直接為 UI 返回搜索詳情和主要內(nèi)容摘要。異步:保持應(yīng)用的響應(yīng)性,多個用戶或請求不會拖慢速度。
最終思考與最佳實踐
? 關(guān)注點分離:代碼的每個部分(搜索、模式、Agent、運行器)都有明確的任務(wù),便于更新或調(diào)試。
? 安全性:使用環(huán)境變量,而不是硬編碼密鑰。
? 可讀性:使用 Pydantic 模型確保清晰,強制類型檢查。
? 異步優(yōu)先:現(xiàn)代 Python,尤其是 Web 開發(fā),應(yīng)使用 asyncio 以獲得更好性能。
這個模塊化、經(jīng)過測試的后端是接下來要構(gòu)建的 Streamlit 前端的完美搭檔。
構(gòu)建 Streamlit 前端:展示 AI 搜索結(jié)果
恭喜!?? 如果你跟到這里,你已經(jīng)擁有了一個強大的研究 Agent 后端,隨時提供深刻的搜索結(jié)果和摘要。下一個任務(wù):用 Streamlit 讓這些洞見變得易于訪問且美觀。
Streamlit 是一個友好的 Python 庫,能將你的腳本變成交互式 Web 應(yīng)用。無需連夜成為前端開發(fā)者!在本節(jié)中,我們將構(gòu)建一個簡單但精致的 Streamlit 界面,用于查詢你的研究 Agent,并展示搜索結(jié)果和主要內(nèi)容摘要。讓我們用一個流暢的 UI 為你的項目賦能,完美分享給朋友、團隊或全世界。
1. 設(shè)置 Streamlit 應(yīng)用
首先,確保 Streamlit 已安裝:
pip install streamlit創(chuàng)建一個名為 app.py 的新文件。在頂部導(dǎo)入核心庫:
import streamlit as st
import asyncio
from agent import run_agent # 導(dǎo)入你的異步 run_agent 函數(shù)專業(yè)提示:如果在 Jupyter 中運行,可能需要使用 nest_asyncio:
import nest_asyncio
nest_asyncio.apply()2. 設(shè)計用戶輸入部分
用標題和友好的提示歡迎用戶:
st.set_page_config(page_title="AI Research Assistant", page_icnotallow="??")
st.title("?? AI 研究儀表板")
st.write("在下方輸入你的研究問題。你的個人研究 Agent 將搜索網(wǎng)絡(luò)并為你總結(jié)結(jié)果——隨時待命!")
query = st.text_input("今天想研究什么?", "強化學(xué)習(xí)是如何工作的?")3. 處理搜索請求(異步來救場!)
這里是魔法時刻:當用戶提交查詢時,調(diào)用你的 Agent 并展示結(jié)果。由于 run_agent 是異步的,優(yōu)雅地包裝它的調(diào)用:
if st.button("運行研究"):
with st.spinner('正在咨詢你的研究 Agent,請稍候...'):
results, main_content = asyncio.run(run_agent(query))提示:Streamlit 的 st.spinner 非常適合讓用戶知道應(yīng)用正在忙碌,避免尷尬的沉默等待。
4. 優(yōu)雅地展示結(jié)果
將輸出組織成清晰分隔的部分,增加清晰度和風(fēng)格:
if "main_content" in locals():
st.subheader("?? 摘要")
st.markdown(main_content, unsafe_allow_html=True)
st.subheader("?? 頂級搜索結(jié)果")
for idx, result in enumerate(results, 1):
with st.container():
st.markdown(f"**{idx}. [{result.title}]({result.url})**")
st.markdown(result.snippet)
st.markdown("---")一些 UI/UX 小技巧:
? 使用 st.container() 或 st.expander() 進行視覺分組。
? 標題和圖標(如 ?? 或 ??)打破單調(diào),引導(dǎo)視線。
? Markdown 允許你注入豐富的格式、鏈接甚至 LaTeX 方程,所以別害羞,美化那些摘要吧!
5. 高級優(yōu)化:響應(yīng)式與精致
想提升外觀和體驗?試試這些:
? 使用 st.sidebar 添加設(shè)置(比如選擇結(jié)果數(shù)量,切換摘要或完整答案)。
? 通過 st.markdown 和 unsafe_allow_html=True 添加自定義 CSS,打造主題背景和卡片。
? 使用 st.error 或 st.warning 優(yōu)雅地顯示錯誤信息。
? 記住:可訪問性和鼓勵很重要。添加工具提示、占位符文本和歡快的成功消息!
6. 測試你的應(yīng)用!??
保存文件,然后在終端中導(dǎo)航到項目目錄,運行以下命令啟動 Streamlit:
streamlit run app.py你的友好 AI 研究儀表板現(xiàn)在在 localhost:8501 上線了!
你做到了!
構(gòu)建這個 UI 真是一個成就。你不僅實現(xiàn)了高質(zhì)量、驗證過的按需研究,還讓它變得任何人都能輕松使用。如果你想冒險,探索 Streamlit 的文檔,了解更多圖表、標簽和其他交互功能!
繼續(xù)實驗,別猶豫展現(xiàn)你的風(fēng)格和 UX 調(diào)整。你正在成為全棧 AI 驅(qū)動數(shù)據(jù)應(yīng)用的專家。快樂構(gòu)建!
連接后端與前端的基礎(chǔ):實現(xiàn)無縫協(xié)作
你已經(jīng)用 Pydantic AI 和 Tavily 構(gòu)建了一個強大的后端研究 Agent,并設(shè)置了一個吸引人的 Streamlit UI。下一步——也是最棘手的——是讓這兩部分順暢溝通,讓用戶能在你的便捷儀表板中提出問題并立即看到高質(zhì)量、驗證過的 AI 答案。
本節(jié)將帶你完成 Streamlit UI 與異步研究 Agent 后端的連接,處理同步 UI 框架中的異步操作,解決新手常遇到的常見問題,并提供一個簡潔、可復(fù)制粘貼的示例。同時,你會找到故障排除提示和清單,將困惑轉(zhuǎn)化為信心。??
1. 為什么連接異步后端到 Streamlit 很棘手?
你的 run_agent(query) 函數(shù)是異步的,但 Streamlit 期望普通的(同步)函數(shù)用于 UI 回調(diào)。這種不匹配可能導(dǎo)致錯誤,比如 RuntimeError: This event loop is already running,或者按下按鈕后什么也沒發(fā)生。在 Streamlit 環(huán)境中處理異步通常是第一個重要的“頓悟”時刻。
問題:
? 異步函數(shù)適合非阻塞代碼,但 Streamlit 的主循環(huán)是同步的。
? 頂級 Streamlit 代碼中不允許使用原生的 await。
快速解決方案:
? 如果你不在異步循環(huán)中,使用 Python 的 asyncio.run()。
? 如果在 Jupyter 中遇到循環(huán)錯誤,使用 nest_asyncio 修補循環(huán)。
2. 最小示例:整合前端與后端
以下是 app.py Streamlit 腳本所需的基本模式:
import streamlit as st
import asyncio
from your_backend_module import run_agent # 你的異步研究 Agent 運行器
try:
import nest_asyncio
nest_asyncio.apply()
except ImportError:
pass# 非筆記本環(huán)境不需要
st.title("?? AI 研究儀表板")
st.write("在下方輸入你的研究問題。Agent 將獲取新鮮的網(wǎng)絡(luò)數(shù)據(jù)和深刻的摘要!")
query = st.text_input("今天想研究什么?", "強化學(xué)習(xí)是如何工作的?")
if st.button("運行研究"):
with st.spinner('正在咨詢你的研究 Agent,請稍候...'):
try:
results, main_content = asyncio.run(run_agent(query))
st.subheader("?? 摘要")
st.markdown(main_content, unsafe_allow_html=True)
st.subheader("?? 頂級搜索結(jié)果")
for idx, result inenumerate(results, 1):
st.markdown(f"**{idx}. [{result.title}]({result.url})**")
st.markdown(result.snippet)
st.markdown("---")
except Exception as e:
st.error(f"發(fā)生錯誤:{e}")關(guān)鍵步驟:
? 使用 asyncio.run 橋接異步和同步世界。
? 優(yōu)雅地處理錯誤,確保 UI 不會無聲崩潰。
? 為筆記本/colab 環(huán)境應(yīng)用可選的 nest_asyncio。
3. 故障排除與優(yōu)化的清單 ???
以下是調(diào)試和優(yōu)化的快速清單:
? 正確導(dǎo)入和調(diào)用你的異步 Agent。
? 在筆記本中使用 nest_asyncio 修補循環(huán)。
? 用 try/except 包裝 Agent 調(diào)用以處理錯誤。
? 顯示 UI 加載動畫以提高響應(yīng)性。
? 將摘要和搜索結(jié)果渲染成清晰的部分。
? 修改后端代碼后重啟 Streamlit!
? 如果出現(xiàn)認證錯誤,檢查 .env 和憑據(jù)。
? 如果有問題,打印/記錄調(diào)試信息。
? 閱讀錯誤堆棧跟蹤,它們通常會告訴你哪一步失敗了。
4. 常見問題與解決方案
問題:按下按鈕后什么也沒發(fā)生!
檢查:確認你保存了后端更改,重啟了 Streamlit,并檢查按鈕代碼是否有拼寫錯誤。
問題:出現(xiàn) RuntimeError: This event loop is already running。
修復(fù):在 Jupyter 環(huán)境中調(diào)用 nest_asyncio.apply(),命令行環(huán)境不需要。
問題:結(jié)果看起來很奇怪/為空!
修復(fù):先將原始結(jié)果打印或顯示到 Streamlit,可能是模式更新或查詢錯誤導(dǎo)致對象為空。
問題:API 認證/權(quán)限錯誤。
修復(fù):仔細檢查 .env 并重新加載憑據(jù)。在 Streamlit 開發(fā)控制臺中打印配置以驗證密鑰。
5. 更進一步:打造強大的實時 UI
熟悉同步調(diào)用后,嘗試拓展:
? 添加加載動畫或骨架屏以增加精致感。
? 如果你的 Agent 支持流式傳輸,嘗試實時顯示部分輸出。
? 考慮使用 Streamlit 的 session_state 添加對話歷史。
? 注意:我們將在未來的帖子中涵蓋以上內(nèi)容。
太棒了!通過有條不紊地將后端研究邏輯連接到 Streamlit 儀表板,你已經(jīng)完成了一個真正的端到端 AI 驅(qū)動數(shù)據(jù)產(chǎn)品管道。繼續(xù)調(diào)整、擴展,慶祝吧,你正在成為全棧數(shù)據(jù)科學(xué)家!

























