Stream-режим AI-агента: solution.py
This commit is contained in:
@@ -0,0 +1,108 @@
|
|||||||
|
# solution.py
|
||||||
|
"""
|
||||||
|
Основной скрипт агента с потоковым выводом.
|
||||||
|
Используются только библиотеки, указанные в условии:
|
||||||
|
- langchain.agents.create_agent
|
||||||
|
- langchain_ollama.ChatOllama
|
||||||
|
- langchain.tools.tool
|
||||||
|
- rich.print
|
||||||
|
|
||||||
|
Потоковый вывод реализован через agent.stream().
|
||||||
|
"""
|
||||||
|
|
||||||
|
# ────────────────────── подключение к LLM ──────────────────────
|
||||||
|
from langchain_ollama import ChatOllama
|
||||||
|
from langchain.agents import create_agent
|
||||||
|
from langchain.tools import tool
|
||||||
|
from rich import print as rprint
|
||||||
|
|
||||||
|
# Создаём объект модели Ollama (используем локальный сервер)
|
||||||
|
llm = ChatOllama(model="llama3.1") # можно заменить на любой доступный модельный тег
|
||||||
|
|
||||||
|
# ────────────────────── определение инструмента с субагентом ──────────────────────
|
||||||
|
@tool
|
||||||
|
def get_price(product: str, city: str) -> str:
|
||||||
|
"""
|
||||||
|
Симуляция запроса цены продукта в указанном городе.
|
||||||
|
В реальном проекте здесь могла бы быть интеграция с API магазина.
|
||||||
|
"""
|
||||||
|
# простая фиктивная логика для демонстрации работы инструмента
|
||||||
|
prices = {
|
||||||
|
("молоко", "Казань"): 89,
|
||||||
|
("хлеб", "Казань"): 35,
|
||||||
|
("яблоки", "Казань"): 120,
|
||||||
|
}
|
||||||
|
price = prices.get((product.lower(), city.lower()), None)
|
||||||
|
if price is None:
|
||||||
|
return f"Цена на {product} в городе {city} не найдена."
|
||||||
|
# форматируем таблицу
|
||||||
|
table = (
|
||||||
|
"| Продукт | Цена (руб.) | Магазин |\n"
|
||||||
|
"|---------|-------------|---------|\n"
|
||||||
|
f"| {product.title()} | {price:<11} | Магнит |\n"
|
||||||
|
)
|
||||||
|
return table
|
||||||
|
|
||||||
|
# ────────────────────── создание главного агента ──────────────────────
|
||||||
|
agent = create_agent(
|
||||||
|
llm=llm,
|
||||||
|
tools=[get_price],
|
||||||
|
verbose=False, # отключаем внутренний вывод LangChain
|
||||||
|
)
|
||||||
|
|
||||||
|
# ────────────────────── потоковый вывод ──────────────────────
|
||||||
|
def format_message(message) -> str:
|
||||||
|
"""
|
||||||
|
Форматируем сообщение для вывода в консоль.
|
||||||
|
Если у сообщения есть content – возвращаем его,
|
||||||
|
иначе формируем строку вызова инструмента.
|
||||||
|
"""
|
||||||
|
if message.content:
|
||||||
|
return message.content
|
||||||
|
# если нет content, но есть tool_calls – выводим их как строку
|
||||||
|
if message.tool_calls:
|
||||||
|
call = message.tool_calls[0]
|
||||||
|
name = call["name"]
|
||||||
|
args = call.get("args", {})
|
||||||
|
return f"{name}({args})"
|
||||||
|
return ""
|
||||||
|
|
||||||
|
def format_chunk_message(chunk):
|
||||||
|
"""
|
||||||
|
Обрабатываем чанк типа 'messages'.
|
||||||
|
Выводим токен сразу, добавляя разделитель при смене шага.
|
||||||
|
"""
|
||||||
|
message, meta = chunk
|
||||||
|
# Проверяем шаг агента
|
||||||
|
if meta.get("langgraph_step") != format_chunk_message.step:
|
||||||
|
format_chunk_message.step = meta["langgraph_step"]
|
||||||
|
rprint("\n --- --- --- \n")
|
||||||
|
content = message.content or ""
|
||||||
|
if content:
|
||||||
|
rprint(content, end="", flush=True)
|
||||||
|
|
||||||
|
# Инициализируем переменную шага
|
||||||
|
format_chunk_message.step = 0
|
||||||
|
|
||||||
|
# Запускаем потоковый вывод
|
||||||
|
stream = agent.stream(
|
||||||
|
{
|
||||||
|
"messages": [
|
||||||
|
{"role": "human", "content": "Сколько стоит молоко в Казани?"}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
stream_mode=["messages", "updates"],
|
||||||
|
)
|
||||||
|
|
||||||
|
for chunk_type, chunk_data in stream:
|
||||||
|
if chunk_type == "messages":
|
||||||
|
format_chunk_message(chunk_data)
|
||||||
|
elif chunk_type == "updates":
|
||||||
|
# Обрабатываем события обновления состояния (например, завершение шага модели)
|
||||||
|
model_info = chunk_data.get("model")
|
||||||
|
if model_info:
|
||||||
|
last_msg = model_info["messages"][-1]
|
||||||
|
rprint("\n" + format_message(last_msg) + "\n")
|
||||||
|
|
||||||
|
# Завершаем вывод
|
||||||
|
rprint("\n--- Конец ответа ---\n")
|
||||||
Reference in New Issue
Block a user