[{"content":"","date":"2026-08-05","externalUrl":null,"permalink":"/categories/","section":"Categories","summary":"","title":"Categories","type":"categories"},{"content":"","date":"2026-08-05","externalUrl":null,"permalink":"/tags/demo/","section":"Tags","summary":"","title":"Demo","type":"tags"},{"content":"","date":"2026-08-05","externalUrl":null,"permalink":"/categories/langgraph/","section":"Categories","summary":"","title":"LangGraph","type":"categories"},{"content":"","date":"2026-08-05","externalUrl":null,"permalink":"/posts/","section":"Posts","summary":"","title":"Posts","type":"posts"},{"content":"import json import os from typing import Annotated, Sequence, TypedDict from dotenv import load_dotenv from langchain_core.messages import BaseMessage, ToolMessage, SystemMessage from langchain_core.runnables import RunnableConfig from langgraph.constants import END from langgraph.graph import StateGraph from langgraph.graph.message import add_messages from langchain_openai import ChatOpenAI from langchain_core.tools import tool load_dotenv() # 图状态 class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages] llm = ChatOpenAI( model=os.getenv(\u0026#34;MODEL_NAME\u0026#34;), base_url=os.getenv(\u0026#34;BASE_URL\u0026#34;), api_key=os.getenv(\u0026#34;API_KEY\u0026#34;), timeout=30) @tool def get_weather(location: str) -\u0026gt; str: \u0026#34;\u0026#34;\u0026#34;Call to get the weather from a specific location.\u0026#34;\u0026#34;\u0026#34; if any([city in location.lower() for city in [\u0026#39;sf\u0026#39;, \u0026#39;san francisco\u0026#39;]]): return \u0026#34;It\u0026#39;s sunny in San Francisco, but you better look out if you\u0026#39;re a a Gemini 😈.\u0026#34; else: return f\u0026#34;I am not sure what the weather is in {location}.\u0026#34; tools = [get_weather] model = llm.bind_tools(tools) tools_by_name = {tool.name: tool for tool in tools} #Define the tool node def tool_node(state: AgentState): outputs = [] for tool_call in state[\u0026#34;messages\u0026#34;][-1].tool_calls: tool_result = tools_by_name[tool_call[\u0026#34;name\u0026#34;]].invoke(tool_call[\u0026#34;args\u0026#34;]) outputs.append( ToolMessage( content=json.dumps(tool_result), name=tool_call[\u0026#34;name\u0026#34;], tool_call_id=tool_call[\u0026#34;id\u0026#34;], ) ) return {\u0026#34;messages\u0026#34;: outputs} # Define the node that calls the model def call_model(state: AgentState, config: RunnableConfig): system_prompt = SystemMessage( \u0026#34;You are a helpful AI assistant, please respond to the users query to the best of your ability.\u0026#34;, ) response = model.invoke([system_prompt] + state[\u0026#34;messages\u0026#34;], config) return {\u0026#34;messages\u0026#34;: [response]} # Define the conditional edge that determines whether to continue or not def should_continue(state: AgentState): messages = state[\u0026#34;messages\u0026#34;] last_message = messages[-1] if not last_message.tool_calls: return \u0026#34;end\u0026#34; else: return \u0026#34;continue\u0026#34; # Define a new graph workflow = StateGraph(AgentState) # Define the two nodes we will cycle between workflow.add_node(\u0026#34;agent\u0026#34;, call_model) workflow.add_node(\u0026#34;tools\u0026#34;, tool_node) # Set the entrypoint as \u0026#39;agent\u0026#39; workflow.set_entry_point(\u0026#34;agent\u0026#34;) # Add a conditional edge workflow.add_conditional_edges( \u0026#34;agent\u0026#34;, should_continue, { \u0026#34;continue\u0026#34;: \u0026#34;tools\u0026#34;, \u0026#34;end\u0026#34;: END, }, ) # Add a normal edge from \u0026#39;tools\u0026#39; to \u0026#39;agent\u0026#39; workflow.add_edge(\u0026#34;tools\u0026#34;, \u0026#34;agent\u0026#34;) graph = workflow.compile() print(graph.get_graph().draw_mermaid()) def print_stream(stream): for s in stream: message = s[\u0026#34;messages\u0026#34;][-1] if isinstance(message, tuple): print(message) else: message.pretty_print() while True: user_megs = input(\u0026#34;\\nuser: \u0026#34;).strip() if user_megs == \u0026#34;quit\u0026#34;: break inputs = {\u0026#34;messages\u0026#34;: [(\u0026#34;user\u0026#34;, user_megs)]} print_stream(graph.stream(inputs, stream_mode=\u0026#34;values\u0026#34;)) LangGraph 流程图\n","date":"2026-08-05","externalUrl":null,"permalink":"/posts/react-demo/","section":"Posts","summary":"import json import os from typing import Annotated, Sequence, TypedDict from dotenv import load_dotenv from langchain_core.messages import BaseMessage, ToolMessage, SystemMessage from langchain_core.runnables import RunnableConfig from langgraph.constants import END from langgraph.graph import StateGraph from langgraph.graph.message import add_messages from langchain_openai import ChatOpenAI from langchain_core.tools import tool load_dotenv() # 图状态 class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], add_messages] llm = ChatOpenAI( model=os.getenv(\"MODEL_NAME\"), base_url=os.getenv(\"BASE_URL\"), api_key=os.getenv(\"API_KEY\"), timeout=30) @tool def get_weather(location: str) -\u003e str: \"\"\"Call to get the weather from a specific location.\"\"\" if any([city in location.lower() for city in ['sf', 'san francisco']]): return \"It's sunny in San Francisco, but you better look out if you're a a Gemini 😈.\" else: return f\"I am not sure what the weather is in {location}.\" tools = [get_weather] model = llm.bind_tools(tools) tools_by_name = {tool.name: tool for tool in tools} #Define the tool node def tool_node(state: AgentState): outputs = [] for tool_call in state[\"messages\"][-1].tool_calls: tool_result = tools_by_name[tool_call[\"name\"]].invoke(tool_call[\"args\"]) outputs.append( ToolMessage( content=json.dumps(tool_result), name=tool_call[\"name\"], tool_call_id=tool_call[\"id\"], ) ) return {\"messages\": outputs} # Define the node that calls the model def call_model(state: AgentState, config: RunnableConfig): system_prompt = SystemMessage( \"You are a helpful AI assistant, please respond to the users query to the best of your ability.\", ) response = model.invoke([system_prompt] + state[\"messages\"], config) return {\"messages\": [response]} # Define the conditional edge that determines whether to continue or not def should_continue(state: AgentState): messages = state[\"messages\"] last_message = messages[-1] if not last_message.tool_calls: return \"end\" else: return \"continue\" # Define a new graph workflow = StateGraph(AgentState) # Define the two nodes we will cycle between workflow.add_node(\"agent\", call_model) workflow.add_node(\"tools\", tool_node) # Set the entrypoint as 'agent' workflow.set_entry_point(\"agent\") # Add a conditional edge workflow.add_conditional_edges( \"agent\", should_continue, { \"continue\": \"tools\", \"end\": END, }, ) # Add a normal edge from 'tools' to 'agent' workflow.add_edge(\"tools\", \"agent\") graph = workflow.compile() print(graph.get_graph().draw_mermaid()) def print_stream(stream): for s in stream: message = s[\"messages\"][-1] if isinstance(message, tuple): print(message) else: message.pretty_print() while True: user_megs = input(\"\\nuser: \").strip() if user_megs == \"quit\": break inputs = {\"messages\": [(\"user\", user_megs)]} print_stream(graph.stream(inputs, stream_mode=\"values\")) LangGraph 流程图\n","title":"React demo","type":"posts"},{"content":"","date":"2026-08-05","externalUrl":null,"permalink":"/tags/","section":"Tags","summary":"","title":"Tags","type":"tags"},{"content":"欢迎来到我的博客！这里记录了我的技术探索和生活感悟。\n","date":"2026-08-05","externalUrl":null,"permalink":"/","section":"欢迎来到我的博客","summary":"欢迎来到我的博客！这里记录了我的技术探索和生活感悟。\n","title":"欢迎来到我的博客","type":"page"},{"content":"","date":"2026-08-02","externalUrl":null,"permalink":"/tags/blog/","section":"Tags","summary":"","title":"Blog","type":"tags"},{"content":"","date":"2026-08-02","externalUrl":null,"permalink":"/tags/hello/","section":"Tags","summary":"","title":"Hello","type":"tags"},{"content":" 你好，世界！ # 这是我的第一篇博客文章，基于 Hugo 和 Blowfish 主题搭建。\n关于这个博客 # 这个博客使用以下技术栈：\nHugo - 静态网站生成器 Blowfish - 美观的 Hugo 主题 GitHub Pages - 网站托管 GitHub Actions - 自动化部署 下一步计划 # 撰写更多技术文章 优化博客配置 添加更多功能 期待在这个博客上记录更多精彩内容！\n","date":"2026-08-02","externalUrl":null,"permalink":"/posts/hello-world/","section":"Posts","summary":"你好，世界！ # 这是我的第一篇博客文章，基于 Hugo 和 Blowfish 主题搭建。\n","title":"Hello World","type":"posts"},{"content":"","date":"2026-08-02","externalUrl":null,"permalink":"/categories/%E7%94%9F%E6%B4%BB/","section":"Categories","summary":"","title":"生活","type":"categories"},{"content":"","externalUrl":null,"permalink":"/authors/","section":"Authors","summary":"","title":"Authors","type":"authors"},{"content":"","externalUrl":null,"permalink":"/series/","section":"Series","summary":"","title":"Series","type":"series"}]