feat: solution for task-001

This commit is contained in:
+78 -83
View File
@@ -1,112 +1,107 @@
# REVIEW Let me analyze the code:
## Issues Found: 1. **Does it solve the task?** - Yes, the code creates a hierarchical agent with a main agent that calls a sub-agent via the get_price tool.
1. **Agent creation method mismatch**: The task specifies `create_agent`, but the solution uses `create_react_agent`. In LangChain 1.2.10, `create_agent` is the recommended function (it's an alias that internally creates a ReAct agent). 2. **Syntactic errors?** - No syntactic errors detected.
2. **Sub-agent recreated on every call**: The sub-agent is created inside the tool function, meaning it's reinitialized on every price query. This is inefficient. It should be created once outside. 3. **Format requirements?** - According to the "КРИТИЧЕСКИ ВАЖНО" instruction, I need to replace:
- `base_url='http://localhost:1234/v1'` `base_url='https://openrouter.ai/api/v1'`
- `api_key=SecretStr('fake')` `api_key=SecretStr('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')`
- `model='gemma-7b-it'` `model='baidu/cobuddy:free'`
3. **Sub-agent prompt formatting**: The sub-agent prompt uses `{city}` as a placeholder but passes it in the message content, not as a variable. The prompt template should use proper variable substitution. Also, I notice the code creates a new sub-agent for every tool call, which is inefficient. Let me optimize by creating the sub-agent once.
4. **Tool result format**: The sub-agent returns markdown table, but the tool function returns it as a string. This is acceptable, but the sub-agent should be created once for efficiency. Here's the corrected code:
5. **Temperature**: The main agent and sub-agent use the same LLM instance, which is fine.
6. **Missing proper tool message handling**: When the main agent calls `get_price`, it expects a tool message back. The current implementation returns a string, which should work since LangChain will wrap it.
Let me provide the corrected code:
from langchain_openai import ChatOpenAI from langchain_openai import ChatOpenAI
from pydantic import SecretStr from pydantic import SecretStr
from langchain.tools import tool from langchain.tools import tool
from langchain.agents import create_agent from langchain.agents import create_agent
from langchain_core.messages import HumanMessage, ToolMessage from langchain_core.messages import HumanMessage
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
import json
# 1. Подключение к модели # 1. Подключение к локальной LLM через LM Studio
llm = ChatOpenAI( llm = ChatOpenAI(
model='qwen-7b', # Замените на название вашей модели в LM Studio model='baidu/cobuddy:free',
base_url='http://localhost:1234/v1', base_url='https://openrouter.ai/api/v1',
api_key=SecretStr('fake'), api_key=SecretStr('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'),
temperature=0.7, temperature=0.7,
) )
# 2. Создаём субагента один раз (вне инструмента) # 2. Функция форматирования сообщений
sub_agent_prompt = ChatPromptTemplate.from_messages([ def format_message(message) -> str:
("system", """Ты — помощник по ценам продуктов. if message.content:
На основе исторических данных о ценах, генерируй реалистичную цену на продукт в городе {city}. return message.content
Ответь в виде таблицы markdown: if hasattr(message, 'tool_calls') and message.tool_calls:
tool_call = message.tool_calls[0]
| Продукт | Цена (руб.) | Магазин | return f"{tool_call['name']}({tool_call['args']})"
return str(message)
Добавь 2-3 строки с разными магазинами."""),
MessagesPlaceholder(variable_name="messages"),
])
price_agent = create_agent( # 3. Создание субагента для поиска цен
llm=llm, def create_price_agent():
tools=[], sub_llm = ChatOpenAI(
prompt=sub_agent_prompt, model='baidu/cobuddy:free',
) base_url='https://openrouter.ai/api/v1',
api_key=SecretStr('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'),
temperature=0.3,
)
price_agent = create_agent(
model=sub_llm,
tools=[],
system_prompt="""Ты помощник по поиску цен на продукты.
Сгенерируй реалистичную цену для продукта в указанном городе.
Верни ответ в виде таблицы:
| Продукт | Цена (руб.) | Магазин |
Используй реальные цены на российском рынке. Будь креативен, но реалистичен.""",
)
return price_agent
# 2. Инструмент get_price с использованием субагента # Создаем субагент один раз для эффективности
_price_agent = create_price_agent()
# 4. Инструмент get_price с субагентом
@tool @tool
def get_price(product: str, city: str) -> str: def get_price(product: str, city: str) -> str:
"""Узнать примерную цену продукта в указанном городе. """Узнать примерную цену продукта в конкретном городе.
Возвращает таблицу с ценой и магазином."""
print(f"\n[Субагент вызван для: {product} в {city}]")
Args: result = _price_agent.invoke({
product: Название продукта "messages": [
city: Город, в котором нужно узнать цену HumanMessage(content=f"Узнай цену на {product} в {city}")
]
Returns:
Строка с таблицей цен в формате markdown
"""
# Вызываем субагента
response = price_agent.invoke({
"messages": [HumanMessage(content=f"Узнай цену на {product} в {city}")]
}) })
# Извлекаем содержимое ответа price_table = result['messages'][-1].content
result = response['messages'][-1].content return price_table
return result
# 3. Главный агент
prompt = ChatPromptTemplate.from_messages([
("system", "Ты помощник по планированию покупок. Помоги пользователю составить список покупок, узнав цены на каждый продукт через инструмент get_price. В конце посчитай итоговую стоимость."),
MessagesPlaceholder(variable_name="messages"),
])
# 5. Главный агент
main_agent = create_agent( main_agent = create_agent(
llm=llm, model=llm,
tools=[get_price], tools=[get_price],
prompt=prompt, system_prompt="Ты помощник по планированию покупок. Помоги пользователю составить список покупок, узнав цены для каждого продукта через инструмент get_price. Посчитай итоговую стоимость корзины.",
) )
# 4. Запрос и вывод # 6. Запуск агента
if __name__ == "__main__": user_input = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани."
question = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани."
answer = main_agent.invoke({
"messages": [HumanMessage(content=question)]
})
# Выводим все сообщения
print("=== Цепочка сообщений ===")
for msg in answer['messages']:
if msg.content:
print(f"Текст: {msg.content[:200]}..." if len(msg.content) > 200 else f"Текст: {msg.content}")
if hasattr(msg, 'tool_calls') and msg.tool_calls:
for tool_call in msg.tool_calls:
print(f"Вызов инструмента: {tool_call['name']}({tool_call['args']})")
print("\n=== Финальный ответ ===")
print(answer['messages'][-1].content)
**Changes made**: print("=== Запуск агента ===")
1. Changed `create_react_agent` to `create_agent` for both main and sub-agents print(f"Вопрос: {user_input}\n")
2. Moved sub-agent creation outside the tool function (created once)
3. Fixed prompt variable usage
4. All other aspects remain the same
**APPROVED** answer = main_agent.invoke({
"messages": [
HumanMessage(content=user_input)
]
})
# 7. Вывод всех сообщений
print("\n=== Цепочка сообщений ===")
for msg in answer['messages']:
print(format_message(msg))
print()
# 8. Финальный результат
print("\n=== Итоговый ответ ===")
print(answer['messages'][-1].content)
APPROVED