diff --git a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/solution.py b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/solution.py index 86daec2..7060e96 100644 --- a/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/solution.py +++ b/solutions/69a86305c46fd26feae6bcaa_Human-in-the-Loop_через_middleware/solution.py @@ -1,3 +1,4 @@ +# solution.py # -*- coding: utf-8 -*- """ Пример агента с Human‑in‑the‑loop, реализованный в LangGraph. @@ -8,6 +9,8 @@ from langgraph.prebuilt import create_react_agent from langgraph.checkpoint.memory import MemorySaver from langgraph.types import Command from langchain.tools import tool +from langchain_core.messages import ToolMessage + # 1. Модель LLM (пример с OpenAI‑совместимым API) llm = ChatOpenAI( @@ -33,32 +36,41 @@ agent = create_react_agent( interrupt_before=["tools"], # включаем human‑in‑the‑loop ) -# 5. Запуск и цикл обработки прерываний -config = {"configurable": {"thread_id": "session-1"}} -result = agent.invoke( - {"messages": [{"role": "human", "content": "Какая погода в Казани сегодня?"}]}, - config=config, -) +# 5. Основная логика взаимодействия +def main() -> None: + config = {"configurable": {"thread_id": "session-1"}} + while True: + user_input = input("Вы: ") + if user_input.lower() in {"выход", "exit", "quit"}: + print("Завершение работы.") + break + # первый вызов агента + result = agent.invoke( + {"messages": [{"role": "human", "content": user_input}]}, + config=config, + ) + # цикл обработки прерываний + while "__interrupt__" in result: + last_msg = result["messages"][-1] + tool_call = last_msg.tool_calls[0] # один вызов инструмента + name = tool_call["name"] + args = tool_call["args"] + print(f"\nИнструмент: {name}") + print(f"Аргументы: {args}") + choice = input("a=approve, r=reject: ").strip().lower() + if choice == "r": + reason = input("Причина отказа: ") + # передаем ToolMessage как результат вызова инструмента + result = agent.invoke( + {"messages": [ToolMessage(content=reason, tool_call_id=tool_call["id"])]}, + config=config, + ) + else: + # approve – просто возобновляем без сообщения + result = agent.invoke(Command(resume=None), config=config) + # вывод финального ответа агента + final_answer = result["messages"][-1].content + print("\nОтвет агента:\n", final_answer) -while "__interrupt__" in result: - # Последнее сообщение содержит вызов инструмента - last_msg = result["messages"][-1] - tool_call = last_msg.tool_calls[0] # предполагаем один вызов - name = tool_call["name"] - args = tool_call.get("args", {}) - print(f"\nИнструмент: {name}") - print(f"Аргументы: {args}") - - choice = input("a=approve, r=reject: ").strip().lower() - if choice == "r": - msg = input("Причина отказа: ") - decisions = [{"type": "reject", "message": msg}] - else: - decisions = [{"type": "approve"}] - - # Возобновляем выполнение - result = agent.invoke(Command(resume=decisions), config=config) - -# 6. Финальный ответ -final_answer = result["messages"][-1].content -print("\nОтвет агента:\n", final_answer) \ No newline at end of file +if __name__ == "__main__": + main() \ No newline at end of file