From f214b914857cfe7475498e293ebae8198d82722a Mon Sep 17 00:00:00 2001 From: lonpatovaadelina Date: Thu, 28 May 2026 14:14:14 +0000 Subject: [PATCH] =?UTF-8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=20solution.py?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- solution.py | 95 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 solution.py diff --git a/solution.py b/solution.py new file mode 100644 index 0000000..a8b3c35 --- /dev/null +++ b/solution.py @@ -0,0 +1,95 @@ +# solution.py + +""" +Основной скрипт агента с потоковым выводом. +Используется стек: LangChain, OpenAI и rich. +""" + +from langchain import hub +from langchain.agents import initialize_agent, AgentType +from langchain.tools import tool +from langchain_community.llms.openai import OpenAI +from rich import print as rprint + +# ---------- 1. Подключаем LLM ---------- +llm = OpenAI(temperature=0, model="gpt-4o-mini", streaming=True) + +# ---------- 2. Определяем инструмент ---------- +@tool +def get_price(product: str, city: str) -> str: + """ + Возвращает таблицу цен на указанный продукт в заданном городе. + """ + # В реальном приложении здесь будет запрос к базе данных или API. + # Для демонстрации возвращаем статический ответ. + if product.lower() == "молоко": + return "| Продукт | Цена (руб.) | Магазин |\n| Молоко | 89 | Магнит |" + elif product.lower() == "хлеб": + return "| Продукт | Цена (руб.) | Магазин |\n| Хлеб | 25 | Пятёрочка |" + else: + return f"Информация о {product} в городе {city} недоступна." + +# ---------- 3. Создаём агента ---------- +tools = [get_price] +agent = initialize_agent( + tools, + llm, + agent=AgentType.OPENAI_FUNCTIONS, + verbose=False, # отключаем стандартный вывод +) + +# ---------- 4. Функции форматирования ---------- +def format_message(message) -> str: + """ + Форматируем сообщение для вывода в консоль. + Если есть content – возвращаем его, + иначе формируем строку вызова инструмента. + """ + if message.content: + return message.content + # В случае tool_calls: берём первый вызов + call = message.tool_calls[0] + name = call["name"] + args = call.get("args", {}) + return f"{name}({args})" + +def format_chunk_message(chunk): + """ + Обрабатываем чанк типа 'messages'. + Выводим токен без перевода строки, добавляем разделитель при смене шага. + """ + message, meta = chunk + global step + + if meta.get("langgraph_step") != step: + step = meta["langgraph_step"] + rprint("\n --- --- --- \n") + + content = format_message(message) + # Выводим без перевода строки, чтобы токены «текли» + print(content, end="", flush=True) + +# ---------- 5. Запускаем потоковый вывод ---------- +if __name__ == "__main__": + # Пример запроса + user_prompt = "Сколько стоит молоко в Казани? А как насчёт хлеба?" + + stream = agent.stream( + {"messages": [{"role": "human", "content": user_prompt}]}, + stream_mode=["messages", "updates"], + ) + + step = 1 + + for chunk in stream: + chunk_type, chunk_data = chunk + if chunk_type == "messages": + format_chunk_message(chunk_data) + elif chunk_type == "updates" and chunk_data.get("model"): + # После завершения шага выводим итоговое сообщение модели + last_msg = chunk_data["model"]["messages"][-1] + rprint("\n") + print(format_message(last_msg), flush=True) + + # Завершающий перевод строки, чтобы консоль оставалась аккуратной + print() \ No newline at end of file