💻 Примеры: агент с поиском и своим инструментом

← К оглавлению урока

⚡ Агент с поиском

agent = create_react_agent(llm, [TavilySearchResults(max_results=2)],
                           checkpointer=MemorySaver())
config = {"configurable": {"thread_id": "abc123"}}
for step in agent.stream(
        {"messages": [HumanMessage(content="погода в Берлине?")]},
        config, stream_mode="values"):
    step["messages"][-1].pretty_print()

Пример 1. Агент-поисковик с памятью (как в лекции)

Агент с одним инструментом — поиском Tavily. Память (MemorySaver + thread_id) позволяет во втором запросе вспомнить, что пользователь живёт в Берлине.

# ai6_1.py
import os
from dotenv import load_dotenv
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langchain_core.messages import HumanMessage
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent

load_dotenv()
# Google-библиотека ждёт ключ в GOOGLE_API_KEY; Tavily — в TAVILY_API_KEY
os.environ["GOOGLE_API_KEY"] = os.getenv("GEMINI_API_KEY")
os.environ["TAVILY_API_KEY"] = os.getenv("TAVILY_API_KEY")

llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")   # «мозг» агента
memory = MemorySaver()                                   # память диалога
search = TavilySearchResults(max_results=2)              # инструмент: поиск
tools = [search]

# ReAct-агент: модель + инструменты + память
agent_executor = create_react_agent(llm, tools, checkpointer=memory)

# thread_id — ключ диалога, по нему агент находит свою память
config = {"configurable": {"thread_id": "abc123"}}

# 1) Сообщаем о себе — агент запомнит
for step in agent_executor.stream(
        {"messages": [HumanMessage(content="hi im bob! and i live in berlin")]},
        config, stream_mode="values"):
    step["messages"][-1].pretty_print()

# 2) Спрашиваем «погоду там, где я живу» — агент вспомнит Берлин и вызовет поиск
for step in agent_executor.stream(
        {"messages": [HumanMessage(content="whats the weather where I live?")]},
        config, stream_mode="values"):
    step["messages"][-1].pretty_print()
Что видно в выводе. stream(..., stream_mode="values") печатает каждый шаг: сообщение пользователя → решение модели вызвать инструмент → результат поиска → финальный ответ. Так наглядно виден цикл ReAct.

Пример 2. Свой инструмент: текущая дата (как в лекции)

Добавим к поиску собственный инструмент — функцию, возвращающую дату/время. Агент сам решит вызвать её, когда спросят про сегодняшний день.

# ai6_2.py
import os
from datetime import datetime
from dotenv import load_dotenv
from langchain_core.tools import Tool
from langchain_core.messages import HumanMessage
from langchain_google_genai import ChatGoogleGenerativeAI
from langchain_community.tools.tavily_search import TavilySearchResults
from langgraph.checkpoint.memory import MemorySaver
from langgraph.prebuilt import create_react_agent

load_dotenv()
os.environ["GOOGLE_API_KEY"] = os.getenv("GEMINI_API_KEY")
os.environ["TAVILY_API_KEY"] = os.getenv("TAVILY_API_KEY")

llm = ChatGoogleGenerativeAI(model="gemini-2.0-flash")
memory = MemorySaver()
search = TavilySearchResults(max_results=2)


# Обычная функция, которую превратим в инструмент
def get_current_date(*args, **kwargs):
    return datetime.now().isoformat()


# Оборачиваем функцию в Tool. description подсказывает LLM, КОГДА её вызвать
date_tool = Tool(
    name="Datetime",
    func=get_current_date,
    description="Returns current datetime in ISO format.",
)

tools = [search, date_tool]                  # два инструмента
agent_executor = create_react_agent(llm, tools, checkpointer=memory)
config = {"configurable": {"thread_id": "abc123"}}

for step in agent_executor.stream(
        {"messages": [HumanMessage(content="hi im bob! and i live in berlin")]},
        config, stream_mode="values"):
    step["messages"][-1].pretty_print()

# Вопрос про дату — агент вызовет наш инструмент Datetime, а не поиск
for step in agent_executor.stream(
        {"messages": [HumanMessage(content="whats the date for today?")]},
        config, stream_mode="values"):
    step["messages"][-1].pretty_print()
⚠️ В современных версиях LangChain свой инструмент удобнее объявлять декоратором @tool над функцией с понятной сигнатурой и docstring — это надёжнее «голого» Tool(func=...). См. Старый vs Новый.