Добавлен agent.py

This commit is contained in:
2026-05-28 14:22:08 +00:00
parent 6cfc23d91c
commit 701c45f076
+53 -89
View File
@@ -1,116 +1,80 @@
# agent.py # agent.py
""" """
Простой LangChain‑агент с поддержкой потокового вывода через `agent.stream()`. Простой пример агента на LangChain с поддержкой потокового вывода.
Внутри используется один инструмент – get_price, который вызывает под‑агента, Используем только указанный стек:
обрабатывающего запросы к «базе цен». - create_agent из langchain.agents
- @tool из langchain.tools
- rich.print как rprint
""" """
from langchain.agents import create_agent from langchain.agents import create_agent
from langchain.tools import tool from langchain.tools import tool
from rich import print as rprint from rich import print as rprint
# --------------------------------------------------------------------------- #
# 1. Определяем LLM (Ollama) – это единственный доступный LLM в задании.
# --------------------------------------------------------------------------- #
try:
from langchain_ollama import ChatOllama
except ImportError: # если Ollama недоступен, используем простой Mock‑LLM
class DummyLLM:
def __call__(self, *args, **kwargs):
return "Mock response"
llm = DummyLLM() # ------------------------------
else: # Определяем инструменты (tools)
llm = ChatOllama(model="llama3.1") # пример модели # ------------------------------
# --------------------------------------------------------------------------- #
# 2. Создаём инструмент get_price.
# --------------------------------------------------------------------------- #
@tool @tool
def get_price(product: str, city: str) -> str: def echo(text: str) -> str:
""" """
Возвращает таблицу цен на указанный продукт в заданном городе. Простейший инструмент, который просто возвращает переданный текст.
Для демонстрации используется под‑агент, который формирует ответ.
""" """
# Под‑агент – простая функция, которая возвращает строку return f"Echo: {text}"
sub_agent = create_agent(
llm=llm,
tools=[],
verbose=False,
agent_type="openai-tools",
)
# Запускаем под‑агента в режиме invoke (т.к. он короткий)
result = sub_agent.invoke({
"messages": [
{"role": "human", "content": f"Сколько стоит {product} в городе {city}?"}
]
})
return result["output"]
# --------------------------------------------------------------------------- # @tool
# 3. Создаём главный агент с инструментом get_price. def add(a: int, b: int) -> int:
# --------------------------------------------------------------------------- # """
Возвращает сумму двух целых чисел.
"""
return a + b
# ------------------------------
# Создаём агента с инструментами
# ------------------------------
agent = create_agent( agent = create_agent(
llm=llm, tools=[echo, add],
tools=[get_price], # Можно задать любой шаблон диалога; здесь используем простой
verbose=False, system_message="Ты помощник, который может отвечать и выполнять инструменты.",
agent_type="openai-tools",
) )
# --------------------------------------------------------------------------- # # ------------------------------------
# 4. Функции для форматирования и вывода чанков. # Функция запуска агента в stream‑режиме
# --------------------------------------------------------------------------- # # ------------------------------------
step = 1 def run_agent(prompt: str):
def format_chunk_message(chunk):
""" """
Выводит токен текста без перевода строки. Запускает агента с заданным запросом и выводит результат токен за токеном.
При смене шага печатает разделитель.
""" """
global step # Стартуем потоковый вызов
message, meta = chunk
if meta["langgraph_step"] != step:
step = meta["langgraph_step"]
rprint("\n--- --- ---\n")
if message.content:
print(message.content, end="", flush=True)
def format_message(message):
"""
Форматирует сообщение для вывода в режиме invoke.
"""
if message.content:
return message.content
# Если нет content – это вызов инструмента
tool_call = message.tool_calls[0]
return f"{tool_call['name']}({tool_call['args']})"
# --------------------------------------------------------------------------- #
# 5. Запускаем потоковый вывод.
# --------------------------------------------------------------------------- #
if __name__ == "__main__":
# Пример запроса к агенту
stream = agent.stream( stream = agent.stream(
{ {"messages": [{"role": "human", "content": prompt}]},
"messages": [
{"role": "human", "content": "Покажи мне цены на молоко и хлеб в Казани."}
]
},
stream_mode=["messages", "updates"], stream_mode=["messages", "updates"],
) )
for chunk in stream: # Перебираем события из потока и печатаем их в реальном времени
chunk_type, chunk_data = chunk for event in stream:
if chunk_type == "messages": if isinstance(event, dict):
format_chunk_message(chunk_data) # В режиме 'updates' событие может быть словарём с информацией о шаге
elif chunk_type == "updates": rprint(f"[bold cyan]Update:[/bold cyan] {event}")
# При завершении шага выводим итоговое сообщение else:
if chunk_data.get("model"): # В режиме 'messages' это строка‑токен
last_msg = chunk_data["model"]["messages"][-1] rprint(event, end="", flush=True)
rprint("\n" + format_message(last_msg) + "\n")
rprint("\n[green]--- Конец ответа ---[/green]")
# ------------------------------
# Пример использования (можно удалить)
# ------------------------------
if __name__ == "__main__":
sample_prompt = (
"Привет! Скажи мне сумму 7 и 5, а потом эхо 'Hello World'."
)
run_agent(sample_prompt)