From 97f80f6f6f2d1569e0c04e55f35f9a2652beb987 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=90=D0=B4=D0=B5=D0=BB=D0=B8=D0=BD=D0=B0=20=D0=A1=D0=B0?= =?UTF-8?q?=D1=82=D1=82=D0=B0=D1=80=D0=BE=D0=B2=D0=B0?= Date: Sun, 31 May 2026 10:43:42 +0000 Subject: [PATCH] add main --- main.py | 80 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..80f2811 --- /dev/null +++ b/main.py @@ -0,0 +1,80 @@ +""" +LangGraph planning agent example. + +Run with: + python main.py "Compare Python and JavaScript" +""" +import json, sys +from typing import TypedDict, List +from langgraph.graph import StateGraph, END +from langgraph.prebuilt import create_chat_agent +from langchain_openai import ChatOpenAI + +# 1. Define state +class PlanningState(TypedDict): + task: str + plan: List[str] | None + current_step: int + results: List[str] + +# 2. LLM for planning and execution +llm = ChatOpenAI(temperature=0) + +# 3. Planning node – split task into steps +async def planning(state: PlanningState) -> PlanningState: + prompt = ( + "You are a helpful assistant that splits a user task into a numbered list of 3-6 concrete steps. + Return only the JSON array of strings, e.g. ["Step 1", "Step 2"] without any explanation.") + response = await llm.agenerate([{"role": "user", "content": f"{prompt}\nTask: {state['task']}"}]) + text = response.generations[0][0].text.strip() + try: + plan = json.loads(text) + if not isinstance(plan, list): raise ValueError + except Exception as e: + # fallback simple split by lines + plan = [line.strip() for line in text.splitlines() if line.strip()] + return {**state, "plan": plan, "current_step": 0, "results": []} + +# 4. Execution node – run one step +async def execution(state: PlanningState) -> PlanningState: + step = state['plan'][state['current_step']] + prompt = f"Execute the following step and return only the result string: {step}" + response = await llm.agenerate([{"role": "user", "content": prompt}]) + result = response.generations[0][0].text.strip() + new_results = state['results'] + [result] + return {**state, "current_step": state['current_step'] + 1, "results": new_results} + +# 5. Condition node – decide to continue or finish +def should_continue(state: PlanningState) -> str: + if state['current_step'] >= len(state['plan']): + return END + return "execute" + +# 6. Build graph +workflow = StateGraph(PlanningState) +workflow.add_node("planning", planning) +workflow.add_node("execution", execution) +workflow.set_entry_point("planning") +workflow.add_conditional_edges("planning", lambda _: "execute") +workflow.add_edge("execution", "should_continue") +workflow.add_conditional_edges("should_continue", should_continue) +graph = workflow.compile() + +# 7. Run demo +if __name__ == "__main__": + if len(sys.argv) < 2: + print("Usage: python main.py ''") + sys.exit(1) + task = sys.argv[1] + result = graph.invoke({"task": task}) + plan = result['plan'] + results = result['results'] + print(f"\nTask: {task}\n") + print("Plan:\n") + for i, step in enumerate(plan, 1): + print(f"{i}. {step}") + print("\nResults:\n") + for i, res in enumerate(results, 1): + print(f"[Step {i}] {res}\n") + final = "\nFinal answer: " + "\n".join(results) + print(final)