From 4fac263a126caac45f60ef5c6784a662144232e3 Mon Sep 17 00:00:00 2001 From: lonpatovaadelina Date: Tue, 2 Jun 2026 16:16:53 +0000 Subject: [PATCH] =?UTF-8?q?=D0=9F=D0=BE=D0=B2=D1=82=D0=BE=D1=80=D0=BD?= =?UTF-8?q?=D1=8B=D0=B9=20=D1=8D=D0=BA=D0=B7=D0=B0=D0=BC=D0=B5=D0=BD:=20?= =?UTF-8?q?=D0=93=D1=80=D0=B0=D1=84=20=D1=81=20=D1=80=D0=B5=D1=84=D0=BB?= =?UTF-8?q?=D0=B5=D0=BA=D1=81=D0=B8=D0=B5=D0=B9=20=D0=B8=20=D0=B4=D0=BE?= =?UTF-8?q?=D1=80=D0=B0=D0=B1=D0=BE=D1=82=D0=BA=D0=BE=D0=B9:=20solution.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solution.py | 129 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 129 insertions(+) create mode 100644 solution.py diff --git a/solution.py b/solution.py new file mode 100644 index 0000000..6154801 --- /dev/null +++ b/solution.py @@ -0,0 +1,129 @@ +<|channel|>final code<|message|>import os +from typing import TypedDict, Literal + +from langgraph.graph import StateGraph, END +from langchain_openai import ChatOpenAI + + +# ---------- 1. Состояние ---------- +class ReflectState(TypedDict): + question: str + draft: str + critique: str + verdict: Literal["ok", "needs_revision"] + round: int + max_rounds: int + + +# ---------- 2. Узлы ---------- +def draft_answer(state: ReflectState) -> dict: + """Первичный ответ на вопрос.""" + llm = ChatOpenAI(model="gpt-4o-mini") + prompt = f"Напиши краткий ответ (5–10 предложений) на следующий вопрос:\n\n{state['question']}" + response = llm.invoke(prompt) + state["draft"] = response.content.strip() + return {"draft": state["draft"]} + + +def reflect(state: ReflectState) -> dict: + """LLM‑критик оценивает ответ.""" + llm = ChatOpenAI(model="gpt-4o-mini") + prompt = ( + f"Оцени следующий ответ на вопрос \"{state['question']}\":\n\n" + f"{state['draft']}\n\n" + "Дай verdict: ok или needs_revision. " + "Если needs_revision, перечисли 2–3 конкретных замечания." + ) + response = llm.invoke(prompt) + text = response.content.strip() + # Разделяем verdict и critique + if "needs_revision" in text: + state["verdict"] = "needs_revision" + parts = text.split("needs_revision", 1)[-1].strip() + state["critique"] = parts + else: + state["verdict"] = "ok" + state["critique"] = "" + return {"verdict": state["verdict"], "critique": state["critique"]} + + +def rewrite(state: ReflectState) -> dict: + """Учитываем critique и переписываем ответ.""" + llm = ChatOpenAI(model="gpt-4o-mini") + prompt = ( + f"Перепиши ответ, учитывая следующие замечания:\n\n" + f"{state['critique']}\n\n" + f"Оригинальный ответ:\n{state['draft']}" + ) + response = llm.invoke(prompt) + state["draft"] = response.content.strip() + state["round"] += 1 + return {"draft": state["draft"], "round": state["round"]} + + +# ---------- 3. Граф ---------- +builder = StateGraph(ReflectState) + +builder.add_node("draft_answer", draft_answer) +builder.add_node("reflect", reflect) +builder.add_node("rewrite", rewrite) + +builder.set_entry_point("draft_answer") +builder.add_edge("draft_answer", "reflect") +builder.add_conditional_edges( + "reflect", + lambda x: x["verdict"], + { + "ok": END, + "needs_revision": "rewrite", + }, +) +builder.add_edge("rewrite", "reflect") + +graph = builder.compile() + + +# ---------- 4. CLI ---------- +def main(): + import argparse + + parser = argparse.ArgumentParser(description="LangGraph рефлексия") + parser.add_argument( + "--question", + type=str, + required=True, + help="Вопрос, на который нужно ответить.", + ) + args = parser.parse_args() + + # Инициализируем состояние + state: ReflectState = { + "question": args.question, + "draft": "", + "critique": "", + "verdict": "", + "round": 0, + "max_rounds": 2, + } + + # Запускаем граф + result = graph.invoke(state) + + # Выводим финальный ответ и логи + print("\n=== Финальный ответ ===") + print(result["draft"]) + print("\n=== Лог рефлексии ===") + print(f"Round: {result['round']}") + print(f"Verdict: {result['verdict']}") + if result["critique"]: + print("Critique:") + print(result["critique"]) + + +if __name__ == "__main__": + # Проверяем наличие ключа OpenAI + if "OPENAI_API_KEY" not in os.environ: + raise RuntimeError( + "Пожалуйста, установите переменную окружения OPENAI_API_KEY." + ) + main() \ No newline at end of file