feat: solution for 6a1864fd8a94f887e50d4706
This commit is contained in:
@@ -0,0 +1,112 @@
|
||||
from typing import TypedDict, List, Optional
|
||||
from langchain_openai import ChatOpenAI
|
||||
from pydantic import SecretStr
|
||||
from langgraph.graph import StateGraph, START, END
|
||||
from langgraph.checkpoint.memory import InMemorySaver
|
||||
|
||||
# ---------- LLM ----------
|
||||
llm = ChatOpenAI(
|
||||
model="openai/gpt-oss-20b",
|
||||
base_url='https://platform.brojs.ru/jrnl-bh/api/inference/v1',
|
||||
api_key=SecretStr("jrnl_30283ab953615cbb6846ff9940a1eedce0b76d7b2f59a2394f29e74643e6a90d"),
|
||||
temperature=0.2,
|
||||
)
|
||||
|
||||
# ---------- State ----------
|
||||
class PlanningState(TypedDict):
|
||||
task: str
|
||||
plan: List[str] | None
|
||||
current_step: int
|
||||
results: List[str]
|
||||
|
||||
# ---------- Nodes ----------
|
||||
def planning(state: PlanningState) -> PlanningState:
|
||||
prompt = (
|
||||
f"Разбей задачу '{state['task']}' на 3–6 конкретных шагов. "
|
||||
"Ответ в виде JSON массива строк, например:\n"
|
||||
'["Шаг 1", "Шаг 2", ...]'
|
||||
)
|
||||
response = llm.invoke(prompt).content
|
||||
try:
|
||||
import json
|
||||
plan = json.loads(response)
|
||||
if not isinstance(plan, list):
|
||||
raise ValueError
|
||||
except Exception:
|
||||
# fallback: simple split by newlines or numbers
|
||||
plan = [line.strip() for line in response.splitlines() if line.strip()]
|
||||
return {
|
||||
**state,
|
||||
"plan": plan,
|
||||
"current_step": 0,
|
||||
"results": [],
|
||||
}
|
||||
|
||||
def execution(state: PlanningState) -> PlanningState:
|
||||
step_idx = state["current_step"]
|
||||
if state["plan"] is None or step_idx >= len(state["plan"]):
|
||||
return state
|
||||
step_text = state["plan"][step_idx]
|
||||
# Execute the step (here we just echo it; replace with real logic)
|
||||
result = f"[Шаг {step_idx + 1}] Выполнено: {step_text}"
|
||||
new_results = state["results"] + [result]
|
||||
return {
|
||||
**state,
|
||||
"current_step": step_idx + 1,
|
||||
"results": new_results,
|
||||
}
|
||||
|
||||
def should_continue(state: PlanningState) -> str:
|
||||
if state["plan"] is None or state["current_step"] >= len(state["plan"]):
|
||||
return "finish"
|
||||
return "execute"
|
||||
|
||||
# ---------- Graph ----------
|
||||
graph = StateGraph(PlanningState)
|
||||
graph.add_node("planning", planning)
|
||||
graph.add_node("execution", execution)
|
||||
|
||||
# Connect planning to the first execution step
|
||||
graph.add_edge("planning", "execution")
|
||||
|
||||
# Conditional loop: after each execution, decide whether to continue or finish
|
||||
graph.add_conditional_edges(
|
||||
"execution",
|
||||
should_continue,
|
||||
{
|
||||
"execute": "execution",
|
||||
"finish": END,
|
||||
},
|
||||
)
|
||||
|
||||
graph.set_entry_point("planning")
|
||||
workflow = graph.compile(checkpointer=InMemorySaver())
|
||||
|
||||
# ---------- Demo ----------
|
||||
if __name__ == "__main__":
|
||||
task_text = input("Задача: ").strip()
|
||||
if not task_text:
|
||||
print("Нет задачи.")
|
||||
exit(0)
|
||||
|
||||
initial_state: PlanningState = {
|
||||
"task": task_text,
|
||||
"plan": None,
|
||||
"current_step": 0,
|
||||
"results": [],
|
||||
}
|
||||
|
||||
result = workflow.invoke(initial_state)
|
||||
plan = result["plan"]
|
||||
results = result["results"]
|
||||
|
||||
print("\nПлан:")
|
||||
for i, step in enumerate(plan, start=1):
|
||||
print(f"{i}. {step}")
|
||||
|
||||
print("\nРезультаты выполнения:")
|
||||
for r in results:
|
||||
print(r)
|
||||
|
||||
final_summary = "\n".join(results)
|
||||
print("\nИтог:\n", final_summary)
|
||||
Reference in New Issue
Block a user