update main.py

This commit is contained in:
2026-05-28 17:03:54 +00:00
parent 088d01bc0a
commit f3b40db050
+12 -31
View File
@@ -15,7 +15,7 @@ Requirements:
from __future__ import annotations from __future__ import annotations
import os import os
from typing import TypedDict, List, Optional from typing import List
from langgraph.graph import StateGraph, START, END from langgraph.graph import StateGraph, START, END
from langchain_core.messages import HumanMessage, SystemMessage from langchain_core.messages import HumanMessage, SystemMessage
@@ -23,17 +23,11 @@ from langchain_openai import ChatOpenAI
from rich.console import Console from rich.console import Console
from rich.table import Table from rich.table import Table
# --------------------------------------------------------------------------- # Import shared state definition
# 1. State definition from models import PlanningState
# ---------------------------------------------------------------------------
class PlanningState(TypedDict):
task: str
plan: List[str] | None
current_step: int
results: List[str]
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 2. LLM configuration BroJS endpoint # 1. LLM configuration BroJS endpoint
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
llm = ChatOpenAI( llm = ChatOpenAI(
model="openai/gpt-oss-20b:free", model="openai/gpt-oss-20b:free",
@@ -43,7 +37,7 @@ llm = ChatOpenAI(
) )
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 3. Planning node split task into steps # 2. Planning node split task into steps
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def planning(state: PlanningState) -> PlanningState: def planning(state: PlanningState) -> PlanningState:
"""Ask the LLM to produce a numbered list of steps. """Ask the LLM to produce a numbered list of steps.
@@ -64,7 +58,6 @@ def planning(state: PlanningState) -> PlanningState:
data = json.loads(text) data = json.loads(text)
plan: List[str] = data.get("plan", []) plan: List[str] = data.get("plan", [])
except Exception: except Exception:
# Fallback split on newlines and strip numbering
plan = [] plan = []
for line in text.splitlines(): for line in text.splitlines():
line = line.strip() line = line.strip()
@@ -82,19 +75,13 @@ def planning(state: PlanningState) -> PlanningState:
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 4. Execution node perform one step (here we just echo the step) # 3. Execution node perform one step (here we just echo the step)
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def execution(state: PlanningState) -> PlanningState: def execution(state: PlanningState) -> PlanningState:
"""Execute a single step.
In a real assignment you would replace this with calls to tools or other logic.
For demonstration, we simply record the step text as the result.
"""
idx = state["current_step"] idx = state["current_step"]
if idx >= len(state["plan"]): if idx >= len(state.get("plan", [])):
return state return state
step_text = state["plan"][idx] step_text = state["plan"][idx]
# Simulate execution in practice you might call a tool here.
result = f"Executed: {step_text}" result = f"Executed: {step_text}"
new_results = state["results"].copy() new_results = state["results"].copy()
new_results.append(result) new_results.append(result)
@@ -105,7 +92,7 @@ def execution(state: PlanningState) -> PlanningState:
} }
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 5. Decision node should we continue? # 4. Decision node should we continue?
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def should_continue(state: PlanningState) -> str: def should_continue(state: PlanningState) -> str:
if state["current_step"] >= len(state.get("plan", [])): if state["current_step"] >= len(state.get("plan", [])):
@@ -113,7 +100,7 @@ def should_continue(state: PlanningState) -> str:
return "execute" return "execute"
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 6. Build the graph # 5. Build the graph
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
graph = StateGraph(PlanningState) graph = StateGraph(PlanningState)
graph.add_node("planning", planning) graph.add_node("planning", planning)
@@ -131,21 +118,16 @@ graph.add_conditional_edges(
agent = graph.compile() agent = graph.compile()
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 7. Helper to run the agent and prettyprint results # 6. Helper to run the agent and prettyprint results
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
def run_agent(task: str) -> None: def run_agent(task: str) -> None:
console = Console() console = Console()
state: PlanningState = {"task": task, "plan": None, "current_step": 0, "results": []} state: PlanningState = {"task": task, "plan": None, "current_step": 0, "results": []}
config = {"configurable": {"thread_id": f"{task[:8]}"}} config = {"configurable": {"thread_id": f"{task[:8]}"}}
# Run the agent we capture intermediate states via a callback.
results: List[PlanningState] = []
for event in agent.stream(state, config): for event in agent.stream(state, config):
if isinstance(event, dict) and "messages" in event: pass # we only need final state
continue # ignore final message
results.append(event)
# Print plan
console.print("\n[bold underline]Task:[/]", task) console.print("\n[bold underline]Task:[/]", task)
if state.get("plan"): if state.get("plan"):
table = Table(title="Plan", show_header=False, box=None) table = Table(title="Plan", show_header=False, box=None)
@@ -153,7 +135,6 @@ def run_agent(task: str) -> None:
table.add_row(f"{i}. {step}") table.add_row(f"{i}. {step}")
console.print(table) console.print(table)
# Print execution results
console.print("\n[bold underline]Execution Results:[/]") console.print("\n[bold underline]Execution Results:[/]")
for r in state.get("results", []): for r in state.get("results", []):
console.print(r) console.print(r)
@@ -161,7 +142,7 @@ def run_agent(task: str) -> None:
console.print("\n[green]Finished.[/]\n") console.print("\n[green]Finished.[/]\n")
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
# 8. Demo examples # 7. Demo examples
# --------------------------------------------------------------------------- # ---------------------------------------------------------------------------
if __name__ == "__main__": if __name__ == "__main__":
examples = [ examples = [