From f9289b92fa95f44898dd8f110b07025a349af9a8 Mon Sep 17 00:00:00 2001 From: MrKan Date: Thu, 2 Apr 2026 00:59:41 +0300 Subject: [PATCH] =?UTF-8?q?=D0=BE=D0=B1=D0=BD=D0=BE=D0=B2=D0=BB=D0=B5?= =?UTF-8?q?=D0=BD=D0=BD=D1=8B=D0=B9=20README?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 125 ++++++++++++------------------------------------------ 1 file changed, 27 insertions(+), 98 deletions(-) diff --git a/README.md b/README.md index eb11610..50769bd 100644 --- a/README.md +++ b/README.md @@ -1,11 +1,13 @@ +from lambda_agent_api import AgentApi + # Lambda Agent API WebSocket API SDK для взаимодействия с AI-агентом. ## Установка - +В `master` всегда будет актуальная рабочая версия. ```bash -pip install . +pip install git+https://git.lambda.coredump.ru/platform/agent_api.git ``` Требуется Python 3.14+. @@ -14,32 +16,22 @@ pip install . ```python import asyncio -from lambda_agent_api.agent_api import AgentApi, OM - -def my_callback(message): - if isinstance(message, OM.MsgError): - print(f"\n[Ошибка: {message.code}] {message.details}") - elif isinstance(message, OM.MsgStatus): - print("✓ Agent status update") - elif isinstance(message, OM.MsgGracefulDisconnect): - print("✓ Agent gracefully requested disconnect") +from lambda_agent_api.agent_api import AgentApi +from lambda_agent_api.server import MsgEventTextChunk async def main(): - api = AgentApi("agent-1", "ws://localhost:8000/ws", callback=my_callback) + api = AgentApi("agent-1", "ws://localhost:8000/ws") await api.connect() try: response = await api.send_message("Привет, агент!") async for chunk in response: - if isinstance(chunk, OM.MsgEventTextChunk): + if isinstance(chunk, MsgEventTextChunk): print(chunk.text, end="", flush=True) - # После окончания Generation возможно получить EventEnd в очереди и сохранить tokens - # (в current implementation: `response` - генератор, для токенов смотрите `EventEnd` в callback) - finally: await api.close() @@ -47,40 +39,31 @@ async def main(): asyncio.run(main()) ``` -## AgentApi - Асинхронный Python клиент - -Новая библиотека `AgentApi` предоставляет типизированный асинхронный клиент для WebSocket взаимодействия с агентом. - -### Характеристики - -- ✅ **Асинхронный клиент** на основе `aiohttp` -- ✅ **Явное подключение/закрытие** через `connect()`/`close()` -- ✅ **Защита от параллельных запросов** через `AgentBusyException` -- ✅ **ResponseIterator** для асинхронной итерации по чанкам ответа -- ✅ **Callback** для обработки событий вне генерации ответа (`Status`, `Error`, `GracefulDisconnect`) -- ✅ **Типизированные сообщения** через Pydantic с дискриминированными объединениями -- ✅ **Обработка ошибок** с кастомным исключением `AgentException` -- ✅ **Логирование** на всех уровнях операций -- ✅ **Полная документация** всех методов - -### Использование +## Предполагаемое использование ```python -from lambda_agent_api.agent_api import AgentApi, OM +from lambda_agent_api.agent_api import AgentApi -api = AgentApi("agent-1", "ws://localhost:8000/ws", callback=my_callback) +connected_agents: dict[str, AgentApi] = {} -await api.connect() -try: - response = await api.send_message("Your question here") - async for chunk in response: - if isinstance(chunk, OM.MsgEventTextChunk): - print(chunk.text, end="", flush=True) +# агент автоматически выключится после нескольких минут бездействия +# этот колбек вызовется при разрыве соединения +def on_agent_disconnect(agent: AgentApi): + del connected_agents[agent.id] - print("\nDone!") -finally: - await api.close() + +async def on_telegram_message(from_user: int, text: str): + agent_id = get_agent_id_by_user(user_id) + + agent = connected_agents.get(agent_id, None) + if not agent: + agent = AgentApi(agent_id, get_agent_url(agent_id), on_disconnect=on_agent_disconnect) + await agent.connect() + connected_agents[agent_id] = agent + + async for event in agent.send_message(text): + ... ``` # Обработка ошибок @@ -89,55 +72,6 @@ finally: - `AgentException` возникает, если агент возвращает `ERROR` или есть проблемы с подключением. - `on_disconnect` callback вызывается один раз при закрытии/разрыве соединения. -Callback функция для обработки событий вне генерации: - -```python -def my_callback(message): - if isinstance(message, OM.MsgStatus): - print("Agent status update") - elif isinstance(message, OM.MsgError): - print(f"Agent error: {message.code} - {message.details}") - elif isinstance(message, OM.MsgGracefulDisconnect): - print("Agent disconnecting gracefully") -``` - -## Классический подход (низкоуровневый) - -```python -import asyncio -import websockets -from lambda_agent_api.server import ServerMessage, OM - - -async def main(): - uri = "ws://localhost:8000/ws" - - async with websockets.connect(uri) as ws: - # 1. Ждём STATUS - подтверждение готовности - status = await ws.recv() - print(f"Connected: {status}") - - # 2. Отправляем сообщение - await ws.send('{"type": "USER_MESSAGE", "text": "Привет!"}') - - # 3. Читаем ответ в виде потока событий - while True: - msg = await ws.recv() - data = ServerMessage.model_validate_json(msg) - - match data: - case OM.AgentEvent(subtype=OM.AgentEventType.TEXT_CHUNK): - print(data.text, end="", flush=True) - case OM.MsgEventEnd(): - print(f"\n[Завершено, использовано токенов: {data.tokens_used}]") - break - case OM.MsgError(): - print(f"\n[Ошибка: {data.code}] {data.details}") - break - - -asyncio.run(main()) -``` ## Протокол @@ -231,8 +165,3 @@ asyncio.run(main()) ``` ![Схема взаимодействия](docs/schema.png) - -## Зависимости - -- Python 3.14+ -- pydantic >= 2.12.5