iT邦幫忙

2025 iThome 鐵人賽

DAY 16
0
生成式 AI

nutc_imac_Agent拼裝車系列 第 16

Day 16 Streamlit 與 LangGraph Agent 的結合

  • 分享至 

  • xImage
  •  

當我們在開發模型或使用模型的過程中,常常會遇到一個問題是我們的Demo成果要怎麼可以快速展示在他人面前?我們可能會先想到把結果輸出成表單,或是寫一個前端來當做互動的介面,但這往往需要額外的技能與時間。這時候 Streamlit 就像是一個神隊友,只要使用簡單的 Python 程式碼,就能在短短幾分鐘內把資料分析或機器學習成果轉換成網頁應用,讓同學或朋友只要打開瀏覽器就能操作。

昨天,我們挑戰改用 LangGraph 來搭建 Agent,把 MCP Server 以 stdio 的方式接上,讓 Agent 能在推論流程中呼叫 sayHello 工具。

今天,我們要再更進一步嘗試使用 Streamlit 來串接這個 Agent,讓整個互動過程可以即時的展示在網頁上。

1. MCP Server (回顧)

我們前幾天寫的 mcp_server.py 長這樣:

mcp = FastMCP("My MCP Server")

@mcp.tool
def sayHello(text: str) -> str:
    """回傳一段打招呼的訊息。"""
    return f"Hello, {text}!"

if __name__ == "__main__":
    mcp.run()

這個 Server 透過 mcp.run(),會使用 stdio 來跟外部溝通。

2. 在 LangGraph 端建立 Agent 串接 MCP Server (回顧)

我們昨天寫的 Agent.py 長這樣:

load_dotenv()

MODEL = os.getenv("OPENAI_API_MODEL", "gpt-4.1")

SYSTEM_HINT = (
    "你是一個只會打招呼的助手。"
    "當使用者請你打招呼時,請呼叫 MCP 提供的 sayHello(text: str) 工具來產生訊息;"
    "若使用者需求與打招呼無關,直接回覆「我只能打招呼。」;"
    "所有回覆一律使用繁體中文。"
)

def _extract_text_from_result(result) -> str:
    try:
        if isinstance(result, dict) and "messages" in result and result["messages"]:
            last = result["messages"][-1]
            content = getattr(last, "content", None) or ""
            if isinstance(content, list):
                # 內容有可能是多段結構,取出文字段
                texts = []
                for part in content:
                    if isinstance(part, dict) and "text" in part:
                        texts.append(part["text"])
                    elif isinstance(part, str):
                        texts.append(part)
                return "\n".join([t for t in texts if t])
            if isinstance(content, str):
                return content
        return str(result)
    except Exception:
        return str(result)

async def run_agent(user_query: str):
    params = StdioServerParameters(
        command="python",
        args=["mcp_server.py"],
        env=os.environ.copy(),
    )

    async with stdio_client(params) as (read, write):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await load_mcp_tools(session)

            llm = ChatOpenAI(model=MODEL)
            agent = create_react_agent(llm, tools)

            messages = [
                {"role": "system", "content": SYSTEM_HINT},
                {"role": "user", "content": user_query},
            ]

            result = await agent.ainvoke({"messages": messages})
            return _extract_text_from_result(result)

if __name__ == "__main__":
    out = asyncio.run(run_agent("幫我跟小明打招呼"))
    print(out)

3. 安裝streamlit

python -m venv venv
source ./venv/bin/activate
pip install streamlit

4. 寫一個簡單的 streamlit 進行測試

st.set_page_config(page_title="MCP 測試")

st.title("MCP 測試")

if "history" not in st.session_state:
    st.session_state.history = []

for role, msg in st.session_state.history:
    with st.chat_message(role):
        st.write(msg)

if prompt := st.chat_input("輸入訊息(例如:幫我跟小明打招呼)"):
    st.session_state.history.append(("user", prompt))
    with st.chat_message("user"):
        st.write(prompt)

    with st.chat_message("assistant"):
        with st.spinner("思考中..."):
            try:
                reply = asyncio.run(run_agent(prompt))
            except Exception as e:
                reply = f"執行出錯:{e}"
        st.write(reply)

    st.session_state.history.append(("assistant", reply))

使用以下指令運行:

streamlit run app.py --server.address localhost --server.port 8501 

結果如下圖:
https://ithelp.ithome.com.tw/upload/images/20250930/201503697Etd2CZiSl.png

從昨天透過 LangGraph 串接 MCP Server 工具,到今天再把 Agent 包進 Streamlit,我們完成從後端推論到前端展示的循環。透過這樣的組合,讓我們可以在有限的時間裡完成一個可互動的應用,不需要額外的前端開發,也不需處理複雜的部署,就能把成果即時展示給同學或團隊成員。


上一篇
Day 15 使用 LangGraph 串接 FastMCP Server
下一篇
Day17 LLM 與 SLM 的優勢、挑戰與應用場景
系列文
nutc_imac_Agent拼裝車19
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言