import os import uuid import asyncio from langchain_openai import ChatOpenAI from langchain.tools import tool from langchain_core.messages import HumanMessage from deepagents import create_deep_agent from deepagents.backends import FilesystemBackend, LocalShellBackend, CompositeBackend from langgraph.checkpoint.memory import MemorySaver from rich.console import Console # Конфигурация LLM через OpenRouter llm = ChatOpenAI( model="openai/gpt-oss-20b:free", base_url="https://openrouter.ai/api/v1", api_key=os.getenv("OPENAI_API_KEY"), temperature=0.0, ) # Backend для выполнения инструментов (необязательно, но удобно) backend = CompositeBackend([ LocalShellBackend(workspace_dir="./workspace"), FilesystemBackend(), ]) # Пример простого инструмента @tool def get_price(params: dict) -> str: """ Получить цену товара в указанном городе и дате. """ city = params.get("city", "неизвестный город") date = params.get("date", "неизвестная дата") return f"Цена в {city} на {date} составляет 100$" # Создание агента с памятью и паузой перед инструментом memory = MemorySaver() agent = create_deep_agent( model=llm, tools=[get_price], backend=backend, system_prompt="You are a helpful agent that asks for confirmation before calling tools.", checkpointer=memory, interrupt_before=["tools"], ) console = Console() async def ask_and_run(user_input, config): """ Запускает потоковое выполнение агента, обрабатывает паузы и подтверждения. """ async for chunk in agent.stream(user_input, config=config, stream_mode=["messages", "updates"]): chunk_type, chunk_data = chunk # Потоковый вывод токенов if chunk_type == "messages": console.print(chunk_data, end="", style="cyan") continue # Вывод вызовов инструментов if chunk_type == "updates": console.print(chunk_data, style="magenta") continue # Обнаружение паузы перед инструментом if "__interrupt__" in chunk_data and agent.get_state(config).next == ("tools",): state = agent.get_state(config) # Последнее сообщение должно содержать вызов инструмента last_msg = state.values["messages"][-1] tool_call = last_msg.tool_calls[0] tool_name = tool_call["name"] tool_args = tool_call["args"] console.print(f"\nАгент хочет вызвать утилиту {tool_name}({tool_args})") answer = input("Разрешить? (Y/n): ") if answer.lower().strip() == "y": # Возобновляем выполнение с того места, где остановились await ask_and_run(None, config) else: console.print("Отменено", style="red") break async def main(): thread_id = f"session-{uuid.uuid4()}" config = {"configurable": {"thread_id": thread_id}} console.print("Введите 'exit' для выхода.", style="bold green") while True: user_input = input("\nВы: ") if user_input.lower() == "exit": break await ask_and_run( {"messages": [HumanMessage(content=user_input)]}, config, ) if __name__ == "__main__": asyncio.run(main())