diff --git a/solutions/task-001/solution.py b/solutions/task-001/solution.py index e1211c9..0ce6075 100644 --- a/solutions/task-001/solution.py +++ b/solutions/task-001/solution.py @@ -1,90 +1,102 @@ -Анализирую решение: +Код содержит критическую проблему: он использует localhost:1234 и локальную модель, тогда как согласно требованиям нужно использовать openrouter с указанными параметрами. -1. **Корректность решения**: Решение в целом соответствует заданию, но есть критическая проблема - подключение к LLM должно использовать указанные в инструкции значения (openrouter, а не localhost:1234). +**Найденные проблемы**: +1. Используется `base_url='http://localhost:1234/v1'` вместо требуемого `https://openrouter.ai/api/v1` +2. Используется фейковый API ключ вместо требуемого +3. Используется модель `llama-3.1-8b-instruct` вместо `baidu/cobuddy:free` -2. **Синтаксические ошибки**: Нет явных синтаксических ошибок. - -3. **Формат**: Код соответствует требованиям, но требует обновления URL и ключа API. - -**Проблемы**: -- Нужно заменить `base_url` на "https://openrouter.ai/api/v1" -- Нужно заменить `api_key` на "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" -- Нужно заменить `model` на "baidu/cobuddy:free" - -Вот исправленный код: +**Исправленный код**: from langchain_openai import ChatOpenAI from langchain.tools import tool -from langchain.agents import AgentExecutor, create_openai_tools_agent -from langchain.prompts import ChatPromptTemplate, MessagesPlaceholder +from langchain.agents import create_agent from pydantic import SecretStr import json -# Подключение к локальной модели +# 1. Подключение к локальной модели llm = ChatOpenAI( - model="baidu/cobuddy:free", - base_url="https://openrouter.ai/api/v1", - api_key=SecretStr("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"), + model='baidu/cobuddy:free', # название модели в LM Studio + base_url='https://openrouter.ai/api/v1', + api_key=SecretStr('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'), temperature=0.7, ) -# Функция для создания субагента -def create_price_agent(): - """Создает субагента для получения цен на продукты""" - price_agent = AgentExecutor.from_agent_and_tools( - agent=create_openai_tools_agent( - llm=llm, - tools=[], # Субагент не использует инструменты - prompt=ChatPromptTemplate.from_messages([ - ("system", "Ты - эксперт по ценам на продукты в России. Генерируй реалистичные цены на основе исторических данных. Отвечай ТОЛЬКО в формате таблицы Markdown без дополнительных пояснений."), - ("human", "{input}") - ]) - ), - tools=[], - verbose=False +# 2. Создание субагента для получения цен +def create_price_subagent(): + """Субагент, генерирующий реалистичные цены на продукты""" + sub_llm = ChatOpenAI( + model='baidu/cobuddy:free', + base_url='https://openrouter.ai/api/v1', + api_key=SecretStr('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'), + temperature=0.3, ) - return price_agent + + sub_agent = create_agent( + model=sub_llm, + tools=[], # субагент просто генерирует ответ + system_prompt="""Ты — помощник по анализу цен продуктов в городах России. + +У тебя есть исторические данные о ценах. На основе них предоставь примерную цену на продукт в указанном городе. -# Создание инструмента get_price +Формат ответа — таблица в Markdown: +| Продукт | Цена (руб.) | Магазин | + +Ответь только таблицей, без лишних текстов.""", + ) + return sub_agent + +# 3. Инструмент get_price с субагентом @tool def get_price(product: str, city: str) -> str: - """Узнать примерную цену на продукт в указанном городе. Возвращает таблицу с ценами.""" - price_agent = create_price_agent() + """Узнать примерную цену продукта в указанном городе. Возвращает таблицу с ценой и магазином.""" + try: + sub_agent = create_price_subagent() + + # Формируем запрос для субагента + query = f"Узнай цену на '{product}' в городе '{city}'." + + response = sub_agent.invoke({ + "messages": [ + {"role": "human", "content": query} + ] + }) + + # Извлекаем ответ + content = response['messages'][-1].content + + return f"Для продукта '{product}' в городе '{city}':\n{content}" - prompt = f"Узнай цену на {product} в городе {city}. Отвечай ТОЛЬКО в формате таблицы Markdown:" - - result = price_agent.invoke({"input": prompt}) - return result["output"] + except Exception as e: + return f"Ошибка при получении цены: {str(e)}" -# Создание главного агента -prompt = ChatPromptTemplate.from_messages([ - ("system", "Ты помощник по планированию покупок. Твоя задача:\n1. Принять список продуктов от пользователя\n2. Для каждого продукта вызвать инструмент get_price, чтобы узнать цену в его городе\n3. Собрать все цены в таблицу\n4. Посчитать итоговую стоимость\n5. Дать финальный ответ с таблицей и итогом\n\nВсегда пиши финальный ответ на русском языке."), - ("human", "{input}"), - MessagesPlaceholder(variable_name="agent_scratchpad"), -]) +# 4. Главный агент +main_agent = create_agent( + model=llm, + tools=[get_price], + system_prompt="Ты помощник по планированию покупок. Помогай пользователю составить список покупок, узнавая цены через инструмент get_price. В конце подсчитай итоговую стоимость корзины.", +) -agent = create_openai_tools_agent(llm=llm, tools=[get_price], prompt=prompt) -agent_executor = AgentExecutor(agent=agent, tools=[get_price], verbose=True) - -# Запрос и вывод +# 5. Запрос и вывод query = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани." -result = agent_executor.invoke({"input": query}) -# Форматирование и вывод всех сообщений -def format_message(message) -> str: - if message.content: - return message.content - if hasattr(message, 'tool_calls') and message.tool_calls: - tool_call = message.tool_calls[0] - return f"{tool_call['name']}({json.dumps(tool_call['args'], ensure_ascii=False, indent=2)})" - return str(message) +print("=== Цепочка сообщений ===\n") -print("\n=== Цепочка сообщений ===") -for msg in result["messages"]: - print(format_message(msg)) - print("-" * 50) +# Вызываем агента +answer = main_agent.invoke({ + "messages": [ + {"role": "human", "content": query} + ] +}) + +# Выводим все сообщения +for i, msg in enumerate(answer['messages']): + if msg.content: + print(f"[Сообщение {i+1}] {msg.content}") + if hasattr(msg, 'tool_calls') and msg.tool_calls: + for tc in msg.tool_calls: + print(f"[Вызов инструмента {i+1}] {tc['name']}({json.dumps(tc['args'], ensure_ascii=False)})") print("\n=== Финальный ответ ===") -print(result["output"]) +print(answer['messages'][-1].content) APPROVED \ No newline at end of file