Files
2026-07-13 13:32:05 +08:00

106 lines
3.1 KiB
Python

"""
Streaming LangGraph Agent
Complexity: MEDIUM - Tests streaming with tool calls
"""
from typing import Literal
from langgraph.graph import StateGraph, END, START, MessagesState
from langgraph.prebuilt import ToolNode
from langchain_openai import ChatOpenAI
from langchain_core.tools import tool
from langchain_core.runnables import RunnableConfig
@tool
def get_stock_price(symbol: str) -> str:
"""Get the current stock price for a ticker symbol."""
prices = {
"AAPL": "$178.50 (+1.2%)",
"GOOGL": "$142.30 (-0.5%)",
"MSFT": "$378.90 (+0.8%)",
"TSLA": "$245.60 (+2.1%)",
"AMZN": "$185.20 (-0.3%)",
}
return prices.get(symbol.upper(), f"Stock price not available for {symbol}")
@tool
def get_company_info(symbol: str) -> str:
"""Get company information for a ticker symbol."""
info = {
"AAPL": "Apple Inc. - Technology company, Market Cap: $2.8T",
"GOOGL": "Alphabet Inc. - Technology company, Market Cap: $1.8T",
"MSFT": "Microsoft Corporation - Technology company, Market Cap: $2.9T",
"TSLA": "Tesla Inc. - Electric vehicles, Market Cap: $780B",
"AMZN": "Amazon.com Inc. - E-commerce/Cloud, Market Cap: $1.9T",
}
return info.get(symbol.upper(), f"Company info not available for {symbol}")
tools = [get_stock_price, get_company_info]
# Enable streaming
llm = ChatOpenAI(model="gpt-5.4-mini", temperature=0, seed=42, streaming=True)
llm_with_tools = llm.bind_tools(tools)
def agent_node(state: dict, config: RunnableConfig) -> dict:
"""Agent node - calls the LLM."""
messages = state["messages"]
response = llm_with_tools.invoke(messages, config=config)
return {"messages": [response]}
async def async_agent_node(state: dict, config: RunnableConfig) -> dict:
"""Async agent node - calls the LLM."""
messages = state["messages"]
response = await llm_with_tools.ainvoke(messages, config=config)
return {"messages": [response]}
def should_continue(state: dict) -> Literal["tools", "__end__"]:
"""Determine if we should continue to tools or end."""
messages = state["messages"]
last_message = messages[-1]
if hasattr(last_message, "tool_calls") and last_message.tool_calls:
return "tools"
return "__end__"
def build_sync_app():
"""Build sync streaming app."""
graph = StateGraph(MessagesState)
graph.add_node("agent", agent_node)
graph.add_node("tools", ToolNode(tools))
graph.add_edge(START, "agent")
graph.add_conditional_edges(
"agent", should_continue, {"tools": "tools", "__end__": END}
)
graph.add_edge("tools", "agent")
return graph.compile()
def build_async_app():
"""Build async streaming app."""
graph = StateGraph(MessagesState)
graph.add_node("agent", async_agent_node)
graph.add_node("tools", ToolNode(tools))
graph.add_edge(START, "agent")
graph.add_conditional_edges(
"agent", should_continue, {"tools": "tools", "__end__": END}
)
graph.add_edge("tools", "agent")
return graph.compile()
sync_app = build_sync_app()
async_app = build_async_app()