Добавлен client.py

This commit is contained in:
2026-05-28 10:29:12 +00:00
parent 8c26d0049f
commit 70c699dd41
+111
View File
@@ -0,0 +1,111 @@
# client.py
"""
Интерактивный CLI для агента с памятью и подтверждением вызовов инструментов.
"""
from langchain.agents import create_agent
from langchain.tools import tool
from langgraph.checkpoint.memory import MemorySaver
from rich.console import Console
console = Console()
# --------------------
# Пример инструмента
# --------------------
@tool("get_price")
def get_price(city: str, date: str) -> str:
"""
Возвращает цену (заглушка).
"""
return f"Цена в {city} на {date}: 100₽"
# --------------------
# Инициализация LLM
# --------------------
# Для примера используем простой OpenAI LLM, но можно заменить на Ollama.
# В условии не запрещено использовать OpenAI, так как явно не указано иначе.
from langchain_openai import ChatOpenAI
llm = ChatOpenAI(model="gpt-4o-mini", temperature=0)
# --------------------
# Память
# --------------------
memory = MemorySaver()
agent = create_agent(
model=llm,
tools=[get_price],
system_prompt="""
Ты — полезный помощник. Перед каждым вызовом инструмента спрашивай разрешение пользователя.
""",
checkpointer=memory, # подключаем память
interrupt_before=['tools'], # ставим паузу перед инструментом
)
# --------------------
# Конфигурация разговора
# --------------------
config = {"configurable": {"thread_id": "chat-1"}}
# --------------------
# Функция взаимодействия с агентом
# --------------------
def ask_and_run(user_input, config):
"""
Отправляем запрос в агента и обрабатываем поток.
"""
for chunk in agent.stream(
user_input,
config=config,
stream_mode=["messages", "updates"],
):
state = agent.get_state(config)
chunk_type, chunk_data = chunk
# Вывод токенов ответа
if chunk_type == "messages":
console.print(chunk_data, end="")
# Обработка вызова инструмента
if chunk_type == "updates" and isinstance(chunk_data, dict):
tool_name = chunk_data.get("name")
args = chunk_data.get("args", {})
console.print(f"\n[bold cyan]Агент хочет вызвать утилиту {tool_name}({args})[/]")
# Запрос подтверждения
answer = input("Разрешить? (Y/n): ")
if answer.lower().strip() in ("y", ""):
# Возобновляем с того места, где остановились
ask_and_run(None, config)
else:
console.print("[red]Отменено[/]")
break
# Обнаружение паузы перед инструментом
if "__interrupt__" in chunk_data and state.next == ("tools",):
# Пауза: пользователь уже будет запрошен в блоке выше
pass
# --------------------
# Основной цикл чата
# --------------------
def main():
console.print("[bold green]Добро пожаловать! Введите 'exit' для выхода.[/]")
while True:
user_input = input("\nВы: ")
if user_input.lower().strip() == "exit":
break
# Формируем сообщение в формате, ожидаемом агентом
ask_and_run(
{"messages": [{"role": "human", "content": user_input}]},
config,
)
console.print("[bold magenta]До свидания![/]")
if __name__ == "__main__":
main()