diff --git a/README.md b/README.md new file mode 100644 index 0000000..b33adc1 --- /dev/null +++ b/README.md @@ -0,0 +1,22 @@ +# AI-агент для планирования покупок + +Иерархический AI-агент на LangChain + LM Studio. + +## Требования + +- Python 3.10+ +- LM Studio на localhost:1234 + +## Запуск + +```bash +pip install -r requirements.txt +export LM_STUDIO_API_BASE="http://localhost:1234/v1" +export LM_STUDIO_MODEL="your-model-name" +python agent.py +``` + +## Структура + +- `agent.py` — главный агент + инструмент get_price с субагентом +- `requirements.txt` — зависимости diff --git a/agent.py b/agent.py index ae70cdb..8f03859 100644 --- a/agent.py +++ b/agent.py @@ -1,52 +1,95 @@ -#! /bin/python -# code: AI agent for shopping list of products with subagent in lamgrain -" -from langchain_tools 'tools' import tool as tool_descriptor -from langchain_agents import create_agent as create_agent +""" +AI-агент для планирования списка покупок. -from langchain_openai import ChatOpenAI as ChatOpenAI +Иерархический агент на LangChain + локальная LLM (LM Studio). +- Главный агент принимает список продуктов +- Инструмент get_price использует субагент для получения цен +- Итоговая таблица с ценами и общей стоимостью +""" -from pydantic and dataconfig import SecretSt - -# Set up to local default model - -lmmodel = ChatOpenAI( - model=\"", - base_url=\"http://localhost:1234/v/marks\", - api_key=SecretSt("fake"), - temperature=0.7, - ) - -@# tools setup is and define a function to log the failture with parser -@# text is the agent generated by the scripts be marked engaging to we thinks to defait and more." -@# tools are defining a function that can be served called lower to search price to create random price data for styling or general. - -@# abstract the function method more recipe for details. +import os +from langchain_core.tools import tool +from langchain_openai import ChatOpenAI +from langgraph.prebuilt import create_react_agent -def get_price(pproduct: string, city: string) -> string: - "#" Return the price list in range table for the product. - # This function should be called as tool." - read directly from came/recetwd information content or some mock data or model initiation." - example data = {\ - \"product\": \"abie\", \"example\": [40, 55, 70]], \"tip\": \"random chinal\\", \"order\": "normal"} - return Printing(data) +# Подключение к LLM через OpenAI-совместимый API (LM Studio) +llm = ChatOpenAI( + model=os.environ.get("LM_STUDIO_MODEL", "local-model"), + openai_api_base=os.environ.get("LM_STUDIO_API_BASE", "http://localhost:1234/v1"), + openai_api_key=os.environ.get("LM_STUDIO_API_KEY", "not-needed"), + temperature=0, +) -@# subset and call mead support tools exest to them be extracted and understated. Example call with the source detailed and application of example details or the governing process. +@tool +def get_price(product: str, city: str) -> str: + """Получить цену продукта в указанном городе. Возвращает таблицу с ценами. + + Args: + product: Название продукта + city: Город для поиска цен + """ + # Субагент для поиска цен + sub_agent = create_react_agent( + model=llm, + tools=[], + prompt=( + "Ты помощник по поиску цен на продукты. " + "Сгенерируй реалистичную цену для указанного продукта в указанном городе. " + "Верни результат строго в формате таблицы:\n" + "| Продукт | Цена | Магазин |\n" + "| {product} | {цена} руб | {магазин} |" + ), + ) + + result = sub_agent.invoke({ + "messages": [{"role": "user", "content": f"Найди цену для: {product} в городе {city}"}] + }) + + # Извлекаем ответ из последнего сообщения + last_message = result["messages"][-1] + return last_message.content if hasattr(last_message, "content") else str(last_message) -sub_agent = create_agent(lmmodel=lmmodel, tools=[get_price], system_prompt=''Investor AGERM. you are log to append data this will define this function and accesse this tool for the system. ') -sub_agent.tools.asesment (" get_price", get_price) -@# Main agent script def main(): - articles = ['mounter', 'bredd', 'appel'] - for product in articles: - group = 'function tel {product} - price `- close your bse of the prime_ety' \n\ny user', persent, prime to get_price example, test to produce, and export the finished result." - for( product in ariticles): - result = sub_agent.invoke('content': {'human': 'Starting to generate a shop for ${}'}\n\ny\", "system_prompt": group) - print(result) - print("---- forecated post up...") - // Should result in the form of table. + """Главный агент — помощник по планированию покупок.""" - import agent from this_payer_ `' \ No newline at end of file + # Главный агент с инструментом get_price + agent = create_react_agent( + model=llm, + tools=[get_price], + prompt="Ты помощник по планированию покупок. Помоги составить список покупок с ценами.", + ) + + # Запрос пользователя + user_request = "Помоги составить список покупок: молоко, хлеб, яблоки. Я нахожусь в Казани." + + print("=" * 60) + print(" Запрос:", user_request) + print("=" * 60) + + # Запуск агента с выводом всех промежуточных сообщений + result = agent.invoke( + {"messages": [{"role": "user", "content": user_request}]}, + ) + + # Вывод всех сообщений (промежуточные вызовы + финальный ответ) + print("\n--- Все сообщения ---\n") + for i, msg in enumerate(result["messages"]): + role = msg.__class__.__name__ + content = msg.content if hasattr(msg, "content") else str(msg) + print(f"[{i}] {role}:") + print(f" {content}") + print() + + # Финальный ответ + final = result["messages"][-1] + print("=" * 60) + print(" Финальный ответ:") + print("=" * 60) + print(final.content if hasattr(final, "content") else str(final)) + + +if __name__ == "__main__": + main() diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..b25eda9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,3 @@ +langchain>=1.0.0 +langchain-openai>=0.2.0 +langgraph>=0.2.0